p3-insta485-clientside
REST API Tools
This tutorial shows how to use command line tools to interact with a REST API.
Install
Make sure you have curl
and HTTPie installed.
Linux and Windows Subsystem for Linux
$ sudo apt-get install curl
$ pip install httpie
Your virtual environment should be activated when installing HTTPie.
MacOS
$ brew install curl httpie coreutils
Sanity check
Your versions might be different.
$ curl --version
curl 7.54.0 (x86_64-apple-darwin16.0) libcurl/7.54.0 SecureTransport zlib/1.2.8
$ http --version
1.0.3
Basic usage
A REST API sends JSON data over HTTP. First, try it in your browser. For this example, we’ll use the GitHub REST API. Navigate to https://api.github.com/users/awdeorio. You should see something like:
{
"login": "awdeorio",
"name": "Andrew DeOrio",
"public_repos": 5,
...
}
Using curl
, we can do the same thing at the command line.
$ curl https://api.github.com/users/awdeorio
{
"login": "awdeorio",
"name": "Andrew DeOrio",
"public_repos": 5,
...
}
Better yet, HTTPie (the http
command) provides color-coded results. It also makes complex requests easier to type. This is the recommended utility.
$ http https://api.github.com/users/awdeorio
HTTP/1.1 200 OK
...
{
"login": "awdeorio",
"name": "Andrew DeOrio",
"public_repos": 5,
...
}
REST APIs and HTTP Basic Access Authentication
HTTP Basic Access Authentication includes a username and password in the headers of every request.
Send HTTP basic auth credentials using HTTPie (http
command). In this example, the username is awdeorio
and the password is chickens
.
The response below is a hardcoded version of the post detail route (/api/v1/posts/1/
) described in the Flask REST API Tutorial. This is a simplified version of what the spec describes for the route.
$ http \
-a awdeorio:chickens \
"http://localhost:8000/api/v1/posts/1/"
HTTP/1.0 200 OK
...
{
"created": "2017-09-28 04:33:28",
"imgUrl": "/uploads/122a7d27ca1d7420a1072f695d9290fad4501a41.jpg",
"owner": "awdeorio",
"ownerImgUrl": "/uploads/e1a7c5c32973862ee15173b0259e3efdb6a391af.jpg",
"ownerShowUrl": "/users/awdeorio/",
"postShowUrl": "/posts/1/",
"postid": 1,
"url": "/api/v1/posts/1/"
}
REST API POST requests
We can also make POST requests with HTTPie. Note that HTTPie implicitly uses JSON as the content type for all requests so we don’t need to specify the content-type
in the POST header:
$ http \
-a awdeorio:chickens \
POST \
"http://localhost:8000/api/v1/comments/?postid=3" \
text='Comment sent from httpie'
Note: this endpoint will only work once the /api/v1/comments/
API endpoint is complete.
REST APIs and sessions
Some REST APIs require a login and session cookies. These examples show how to use sessions with HTTPie. This tutorial section is optional in EECS 485.
This section assumes functional /accounts/
and /api/v1/posts/1/
routes.
To try these examples, start your EECS 485 Project 3 development server.
$ ./bin/insta485run
Request to the REST API without a login results in a 403 error. Note: this assumes a complete project 3 implementation.
$ http "http://localhost:8000/api/v1/posts/1/"
HTTP/1.0 403 FORBIDDEN
...
Login using HTTPie to fill out the login form. This will save a file called session.json
containing a cookie set by the server.
$ http \
--session=./session.json \
--form POST \
"http://localhost:8000/accounts/" \
username=awdeorio \
password=chickens \
operation=login
HTTP/1.0 302 FOUND
...
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<title>Redirecting...</title>
...
HTTPie will use the cookie in session.json
to authenticate to the insta485 API.
$ http \
--session=./session.json \
"http://localhost:8000/api/v1/posts/1/"
HTTP/1.0 200 OK
...
{
"comments": [
{
"commentid": 5,
"lognameOwnsThis": false,
"owner": "jflinn",
"ownerShowUrl": "/users/jflinn/",
"text": "Walking the plank #chickensofinstagram",
"url": "/api/v1/comments/5/"
},
{
"commentid": 6,
"lognameOwnsThis": true,
"owner": "awdeorio",
"ownerShowUrl": "/users/awdeorio/",
"text": "This was after trying to teach them to do a #crossword",
"url": "/api/v1/comments/6/"
}
],
"comments_url": "/api/v1/comments/?postid=1",
"created": "2021-05-06 19:52:44",
"imgUrl": "/uploads/122a7d27ca1d7420a1072f695d9290fad4501a41.jpg",
"likes": {
"lognameLikesThis": true,
"numLikes": 3,
"url": "/api/v1/likes/1/"
},
"owner": "awdeorio",
"ownerImgUrl": "/uploads/e1a7c5c32973862ee15173b0259e3efdb6a391af.jpg",
"ownerShowUrl": "/users/awdeorio/",
"postShowUrl": "/posts/1/",
"postid": 1,
"url": "/api/v1/posts/1/"
}
Pro-tip: shell script shortcuts
Save some typing by writing a short script that logs in and make a request. Here is shell script code for a sample resttest.sh
.
#!/bin/bash
set -Eeuo pipefail
set -x
# Log in
http \
--session=./session.json \
--form POST \
"http://localhost:8000/accounts/" \
username=awdeorio \
password=chickens \
operation=login
# REST API request
http \
--session=./session.json \
"http://localhost:8000/api/v1/posts/1/"
Don’t forget to make the script executable.
$ chmod +x resttest.sh
Run.
$ ./resttest.sh
+ http --session=./session.json --form POST http://localhost:8000/accounts/ username=awdeorio password=chickens operation=login
HTTP/1.0 302 FOUND
...
+ http --session=./session.json http://localhost:8000/api/v1/posts/1/
HTTP/1.0 200 OK
...
{
"comments": [
{
"commentid": 5,
"lognameOwnsThis": false,
"owner": "jflinn",
"ownerShowUrl": "/users/jflinn/",
"text": "Walking the plank #chickensofinstagram",
"url": "/api/v1/comments/5/"
},
{
"commentid": 6,
"lognameOwnsThis": true,
"owner": "awdeorio",
"ownerShowUrl": "/users/awdeorio/",
"text": "This was after trying to teach them to do a #crossword",
"url": "/api/v1/comments/6/"
}
],
"created": "2021-05-06 19:52:44",
"imgUrl": "/uploads/122a7d27ca1d7420a1072f695d9290fad4501a41.jpg",
"likes": {
"lognameLikesThis": true,
"numLikes": 3,
"url": "/api/v1/likes/1/"
},
"owner": "awdeorio",
"ownerImgUrl": "/uploads/e1a7c5c32973862ee15173b0259e3efdb6a391af.jpg",
"ownerShowUrl": "/users/awdeorio/",
"postShowUrl": "/posts/1/",
"url": "/api/v1/posts/1/"
}
Update .gitignore
Be sure to add session.json
and cookies.txt
to your .gitignore
. These files shouldn’t be in version control.
Acknowledgments
Original document written by Andrew DeOrio awdeorio@umich.edu.
This document is licensed under a Creative Commons Attribution-NonCommercial 4.0 License. You’re free to copy and share this document, but not to sell it. You may not share source code provided with this document.