Unit 8: APIs
Welcome to Unit 8β
Building off of last unit, we are going to make requests to APIs in our web app. This will let us spice up our project, and include more from the web.
Unit 8 Lecture Videoβ
Only the first 100 seconds, we won't be talking about how to build an API (around 2:30)
What is an API?β
API stands for (A)pplication (P)rogramming (I)nterface. It provides a structured way to communicate with an application by sending and receiving data.
When we go to a website (i.e. facebook.com). We are making a request to Facebook's servers and are asking them to respond with some data. When you do this, your browser is interacting with Facebook's API to display some data.
APIs are also used for programs to interact with each other. We will be using APIs in our own website so that we can retrieve some data from the internet.
REST APIβ
REST stands for Representational State Transfer, and is an architectural style for creating web services. REST treats each any data as a resource, that the client can fetch/edit/delete. We specify these resources through URLs and then sending a request. The server will then provide a response.
HTTP Methodsβ
With REST APIs we send HTTP Requests. Each of these requests has a method type, that usually correspond to what we want our request to do.
- GET - Getting a resource.
- POST - Creating and saving a new resource.
- PUT - Updating a resource.
- DELETE - Deleting a resource.
Once we make a request, the server will give a response. Most times the response will be in JSON (JavaScript Object Notation). This is the primary data format passed between APIs.
An Exampleβ
Let's do an example with the PeterPortal API. This API was created by ICSSC and is in use by applications like AntAlmanac and Zotistics. It provides data such as courses, instructors, grades, etc.
To make a request, we can use cURL in our shell. cURL lets us make an HTTP request in our shell. By default cURL is making a GET request.
cURL https://api.peterportal.org/rest/v0/courses/COMPSCI161
The output will look a little weird but after it's made pretty, it will look like this:
{
"id": "COMPSCI161",
"department": "COMPSCI",
"number": "161",
"school": "Donald Bren School of Information and Computer Sciences",
"title": "Design and Analysis of Algorithms",
"course_level": "Upper Division (100-199)",
"department_alias": [
"CS"
],
"units": [
4,
4
],
"description": "Techniques for efficient algorithm design, including divide-and-conquer and dynamic programming, and time/space analysis. Fast algorithms for problems applicable to networks, computer games, and scientific computing, such as sorting, shortest paths, minimum spanning trees, network flow, and pattern matching.",
"department_name": "Computer Science",
...
}
I've excluded some other fields here, but as you can see the request gives us more information on the requested resource. Let's break the URL down a little bit.
https://api.peterportal.org
- This means we want to make a request to this server. Your internet will use this to find the server./rest/v0/courses/
- When we find the server, what resource do we want. In our case we want a specific course.COMPSCI161
- This is our parameter, we can change this to another course if we want a different course.
How we know exactly what format to make our URL is usually specified in the API documentation. For the PeterPortal API, we looked here for how to use the courses endpoint. https://api.peterportal.org/REST-API/courses/
HTTP Status Codesβ
In the above response we also received a status code of 200. 200 indicates a successful request. There are lots of different HTTP status codes, but the gist of it is this:
2xx - Success!
4xx - You did something wrong
5xx - There is a problem with the server.
For more specific status codes, you can read more here.
If we made a request like this:
cURL https://api.peterportal.org/rest/v0/courses/NONEXISTENT121
Our response will give us an error, indicating this course was not found.
{
"timestamp": "Tue, 15 Feb 2022 22:39:23 GMT",
"status": 404,
"error": "Bad Request: Invalid parameter",
"message": "Course not found"
}
URL Encodingβ
When specifying parameters in URLs, you will need to URL Encode them, especially if there are any special characters. This is because URLs usually use these special characters for other important notation.
# Here the '&' was URL encoded to %26.
cURL https://api.peterportal.org/rest/v0/courses/I%26CSCI33
In JavaScript, we can use encodeURIComponent
to URL encode our parameter strings.
Fetchβ
To make a request to an API in JavaScript, we use the fetch library.
npm install node-fetch
Fetch is a function that takes 2 arguments. The url and a configuration object.
const url = "https://api.peterportal.org/rest/v0/courses/all";
const response = await fetch(url, {
"method": "GET"
});
console.log(response.json());
Learn more about Fetch, in Mozilla documentation:
Using the Fetch API - Web APIs | MDN
GraphQLβ
What is GraphQL?β
π‘ GraphQL is a query language for Web APIs. GraphQL itself is not a tool or a framework, it is a language.
Three cool features of GraphQL
- Get exactly what you ask for
- Get multiple resources in one request
- Type System to know what is possible
Why GraphQL?β
Let's say you're consuming an API for a social media platform. What kind of data resources are you looking for?
- Posts
- Pictures
- Likes
- Comments
If you're familiar with REST, a REST API endpoints for this app may look like this:
/newsfeed
β> [post IDs]/post/{id}
β> picture ID, user ID, likes/picture/{id}
β> picture data/user/{id}/picture
β> commenter profile pic
What's the problem with the REST approach?β
Too much data
With REST, the fields I get from each endpoint cannot be changed.
If I just want to get the user who posted a post, the /post/{id}
endpoint returns more than just the user β it also returns the picture ID
and the number of likes
.
I don't need all of that, and such inefficiency can be costly in the long run.
Complicated
Certain use cases can lead to multiple, complicated requests to get the resources I want. Let's say I want to get the profile picture of every user who posted on the newsfeed.
/newsfeed
I need to get all thepost ID
from the newsfeed/post/{id}
I then need to get theuser ID
of who made each post/user/{id}/picture
I then use theuser ID
from each post to get the profile picture
Now that's complicated.
Instead, we can use GraphQL! π€
Scalabilityβ
Don't get more data than you needβ
With GraphQL, you get exactly what you need. In each request, you can specify what fields are to be returned. If you want to add another field later on, like a commenter's username, simply add it into the request!
Simplified usageβ
So we know that GraphQL puts all resources under one endpoint, but how does it do this and keep things simple? A type system defines the fields available in a type as well as a type's relationship with other types. So if we get an overhead perspective, we can see that this is what puts the graph in GraphQL.
How to use GraphQLβ
Like in REST, we can use the Fetch API to make a request. First, we define our URL, and our query. In our query we specify what data we want, and which fields we want. Usually the documentation for the API will tell you the names of the fields.
For the PeterPortal API, the documentation is found in its GraphQL Playground, under the docs
tab on the right.
The playground is usually in most GraphQL APIs that let you test out their queries.
const url = "https://api.peterportal.org/graphql/";
const query = `
query {
course(id: "DANCE3"){
id
department
school
instructor_history {
ucinetid
department
}
}
}`;
In this query, we are querying course
with the id DANCE3
.
The course query returns a Course type, that we specify what fields we want.
One of these is the instructor_history
which is an array of Instructor types.
Since this is also a type, we need to give it some more fields of the Instructor type.
In GraphQL, all requests are POST requests to the endpoint, /graphql/
.
The fetch function takes in two arguments.
A URL is the first one, and the second one is options (we pass in as a JavaScript Object).
const response = await fetch(url, {
"method": "POST",
"body": JSON.stringify({query}),
// Not necessary for every Web API, but it's good practice
"headers" : {
"Content-Type": "application/json",
}
});
console.log(response.json());
GraphQL is super cool and an up and coming way of communicating with APIs. More and more apps everywhere are using GraphQL, and it's definitely worth learning. There is a lot more we can do with GraphQL, and this is only the beginning.
PeterPortal APIβ
The PeterPortal API was created by ICSSC to encourage user development of projects to benefit UCI. It includes data on Courses, Instructors, Grades and Schedule of Classes. It is being used by our current projects including AntAlmanac, Zotistics, and even our newest project, PeterPortal.
Check it out here: PeterPortal API Docs
Assignmentβ
For the assignment this unit, we will be building off of last unit's project and make requests to the PeterPortal API to display some data!
Required Tasks
- Make a Request to the PeterPortal API REST Endpoint with Fetch
- Display the data from the REST API
- Make a request to the PeterPortal API GraphQL Endpoint
- Display data from GraphQL API
- Style the data you just added!
Optional Stretch Goals
- Use GraphQL to also display Instructor History and each of their names
Submissionβ
Complete the Google Form
External Resources
PeterPortal API
GraphQL
Presentation Slides: