Alex headshot

AlBlue’s Blog

Macs, Modularity and More

HTTPie

2012

I came across HTTPie today, a Python-based command line utility for executing HTTP requests in a sane way. I’m pretty sure this is going to become a regular in my day-to-day toolbox of utilities.

Installing it onto a decent operating systems is pretty easy:

Installing HTTPie
1
2
$ sudo easy_install pip
$ sudo pip install -U httpie

Once it had downloaded the pre-requisites, it gives you a utility which you can use to see output from HTTP requests, be able to supply parameters, and colourise the output.

Example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$ http GET https://www.googleapis.com/discovery/v1/apis/
HTTP/1.1 200 OK
Expires: Thu, 08 Mar 2012 16:56:17 GMT
Date: Thu, 08 Mar 2012 16:51:17 GMT
Cache-Control: public, max-age=300, must-revalidate, no-transform
ETag: "H6ld74DKed8AAlT0jfgIC1JiBUc/n78e9I7ZrCSK0CfSxKuC-JZ9LRI"
Content-Type: application/json; charset=UTF-8
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
Server: GSE
Transfer-Encoding: chunked

{
    "discoveryVersion": "v1",
    "items": [
        {
            "description": "Gives AdSense publishers access to their inventory and the ability to generate reports",
            "discoveryLink": "./apis/adsense/v1/rest",
            "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/adsense/v1/rest",
        ...
    ],
    "kind": "discovery#directoryList"
}

The colours won’t show up correctly here – but if you run this in a shell then you’ll notice that the output is coloured appropriately.

In the example above, I used https because the server requires it. If you’re just using it over HTTP you don’t need to specify the prefix:

Accesssing with HTTP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
$ http GET www.googleapis.com/discovery/v1/apis/
HTTP/1.1 403 Forbidden
Content-Type: application/json; charset=UTF-8
Date: Thu, 08 Mar 2012 16:59:26 GMT
Expires: Thu, 08 Mar 2012 16:59:26 GMT
Cache-Control: private, max-age=0
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
Server: GSE
Transfer-Encoding: chunked

{
    "error": {
        "code": 403,
        "errors": [
            {
                "domain": "global",
                "message": "SSL is required to perform this operation.",
                "reason": "sslRequired"
            }
        ],
        "message": "SSL is required to perform this operation."
    }
}

If you want to send other data to the server, you can specify key=value pairs which can be sent via a multi-part form encoded (--form) or encoded as a JSON object.

Asking DuckDuckGo about ZFS
1
2
3
4
5
6
7
8
9
10
11
12
13
http --form POST duckduckgo.com q=zfs format=json
HTTP/1.1 200 OK
Server: nginx
Date: Thu, 08 Mar 2012 17:11:18 GMT
Content-Type: application/x-javascript; charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive
Expires: Thu, 08 Mar 2012 17:11:19 GMT
Cache-Control: max-age=1
Content-Encoding: gzip

{"Definition":"ZFS A distributed file system from Sun that
was added to OpenSolaris in 2005 and Solaris 10 in 2006 ...}

If the result is a JSON type (but not declared as JavaScript) then you can use the --pretty to format the results in an indented fashion.

Finally, if you need to specify specific headers, then you can pass them in as well, by using : as a separator instead of = (enclosing in quotes if there are spaces):

Passing in custom headers
1
2
3
4
5
6
$ http GET alblue.bandlem.com "If-Modified-Since: Thu, 08 Mar 2012 17:30:07 GMT"
HTTP/1.1 304 Not Modified
Date: Thu, 08 Mar 2012 17:30:18 GMT
Server: Apache/2.2.9 (Debian) mod_ssl/2.2.9 OpenSSL/0.9.8g
ETag: "4e10073-41b6-4baaec4d1c400"
Cache-Control: max-age=172800, public, must-revalidate

This is a newly released tool but I think it’s going to gain in popularity a lot, over existing wget and curl style interfaces which are often pretty clunky.