REST APIs¶
Now that we know about Ajax and we know that we can use $.get()
and
$.put()
and, indeed, $.ajax()
to make requests of servers directly
from JavaScript, it's time to learn about REST APIs.
Servers often provide various services via HTTP, including the ability to interact with databases of various sorts. Furthermore, they often make use of additional HTTP "methods"1, beyond just GET and POST.
A particular way that JavaScript and these HTTP methods can be used is called a REST API (Representational State Transfer).
REST Concepts¶
Let's be concrete, using the CoffeeRun example. The attributes of each "order" will be just simple strings and numbers; in principle, they could be a lot more complex. Each order will also have a id.
The server will have a "database" of these coffee orders.
The key for each order will be its id, which is a string like
scott.anderson@wellesley.edu
. The value will be a dictionary, with a
key/value pairs like strength: 76
and flavor: 'almond'
.
What operations might we want to support on this database? The following operations seem like a good minimal set:
- GET all orders in the database
- ADD a new order
- for a particular order, identified by its id:
- GET all information about it
- REPLACE all information about it
- DELETE it
So, 5 operations. Now, let's see how those might map to HTTP methods.
HTTP Methods¶
The HTTP standard defines a lot more methods than GET and POST,
which are the only ones we've used so far. (And the only ones
supported by the <form>
element, so you can't have a <form
method='put'>
or <form method='delete>
, which I find weird.) See HTTP
request
methods
for a comprehensive list. These are sometimes called verbs because
of their part of speech and active nature.
Let's fill out our list with a few more (this is not all HTTP methods).
- GET The GET method requests a representation of the specified resource. Requests using GET should only retrieve data. We'll use this to return a particular coffee order from the database.
- POST The POST method is used to submit an entity to the specified resource, often causing a change in state or side effects on the server. We'll use this to create a new coffee order, adding it to the database. We'll return the email address as the ID with the response. The data for the new entity is sent in the body of the request, not in the URL.
- PUT The PUT method replaces all current representations of the target resource with the request payload. So, we'll use this to replace the coffee order item. Like POST, the data for the entity is in the body of the request.
- DELETE The DELETE method deletes the specified resource. This one is an easy mapping: We'll delete the specified coffee order.
The HTTP method is only part of the request. The request also includes the URL. The combination of the two will map to a particular chunk of Flask code that will implement the operation:
method | url | operation |
---|---|---|
GET | /api/coffeeorders |
return all coffee orders |
POST | /api/coffeeorders |
create a new coffee order, returning its ID |
GET | /api/coffeeorders/<id> |
return the order with that id (email) |
PUT | /api/coffeeorders/<id> |
replace the order with that id (email) |
DELETE | /api/coffeeorders/<id> |
delete the order with that id (email) |
You'll notice that there are many combinations we don't support. We
don't support PUT to the /api/coffeeorders
URL. Presumably, this
would replace the entire database with a new database. This is
certainly possible, but not required, and we won't.
Note that in coffeerun, an new order specifies its ID in the data that is sent via POST, but not all databases will work that way. If we make a POST on Facebook or some other app, typically the database response will tell us what ID we were issued (probably some very long unique identifier, since there are a lot of such posts).
So, not every API will work identically, but this is close.
Notice also that that certain combinations aren't allowed. PUT requires a key, and POST requires the record to be brand new. If you want more, see REST PUT vs POST
REST APIs have become a very popular web API.
Examples¶
There are many databases out there that support a REST API. That means you can write a web application that interacts with these servers.
I'm grateful to Sara Clark for finding these examples.
Note that Spotify requires authentication (who are you?) and authorization (what are you allowed to do?), which are collectively known as "auth". That is, you can write a web app that interacts with Spotify, but you have to create a Spotify account that allows them to know who you are and determine what you are allowed to do and to hold you accountable for your actions. (And, no, they aren't going to allow you to destroy anything, so no need to be timid.) In fact, looking at their accounts login page, it appears you can login with your Facebook, Apple or Google account, in addition to creating your own username and password.
Some of the public apis that Sara found will allow you to GET data without auth, though none will allow you to POST or PUT data without auth. For example, the following cat picture is placed on this page thanks to the catAPI:
Here's the code that does it. First, the image:
<img id="catpic" src="" alt="random cat picture">
and the JavaScript:
$.get("https://thatcopy.pw/catapi/rest/",
function (response) {
$("#catpic").attr('src', response.webpurl);
});
I knew that the response would have a .webpurl
attribute because of
the documentation for the catapi
CS 204 Cloud Store¶
For your use in the Shopping Lists assignment and for you final projects, I will provide a key/value cloud-based database.
The CS 204 Cloud Store is all under the following URL:
https://cs.wellesley.edu/cs204cloud/
Auth¶
The CS 204 Cloud Store does require auth, via a username and password. For the Shopping Lists assignment, I'll provide a username and password that you will all use. For your projects, you can create a personal username and password, so that you can keep your data separate from other CS 204 students. (I might change my mind about how this is done; I'm open to suggestions.)
note: While I'll make every effort to make sure that the data is secure from hackers, it will be stored unencrypted on Tempest and so is possibly vulnerable. Furthermore, I will have access to all your data. So, you should not store anything in your app that is personal or sensitive.
The login has the following URL and data:
POST https://cs.wellesley.edu/cs204cloud/login/
{username: <user>,
password: <passwd>}
I'll give you this username and password in class, or you'll create your own. For obvious2 reasons, you should not code the password directly into your app.
One way to get the password dynamically is to pop up a box that the user (you) can type the password into, using the built-in prompt function:
var user = 'your account';
var pwd = prompt('what is the password?');
$.post('https://cs.wellesley.edu/cs204cloud/login',
{username: user, password: pwd},
function (resp) {
if(resp.error) { alert(resp.errmsg); }
});
If the response's .error
property is false, then the login was
successful.
A more sophisticated way to get the password would be to provide a
<form>
and grab the password from the input you provide. You could
even make the input type=password
so that the password is not
visible.
API¶
Once you have logged in, the server provides the following API under the main URL:
GET
returns all your entries from the databasePUT
replaces all your database entries. The data should be a JavaScript object literal (a dictionary)POST
creates a new key/value pair. The data should be a single key/value pair repesented as a JavaScript object literal (a dictionary). For example:{a: 3}
DELETE
deletes your entire database. You probably wouldn't use this often.
Given a particular key that is appended to the main URL:
GET
returns the valuePUT
replaces the valueDELETE
deletes the key/value pair
note I'm still thinking about how this will work best, so that may change.
Summary¶
REST APIs are an important way that websites and servers interact. It allows innovation in UX (user experience) as web developers think about different ways that web pages can work, while relying on a generic but capable API to store and retrieve data.