knowledge/technology/applications/development/HTTPie.md
2024-09-04 15:15:40 +02:00

17 KiB
Raw Blame History

obj repo website flatpak-id
application https://github.com/httpie/httpie https://httpie.io io.httpie.Httpie

HTTPie

modern, user-friendly command-line HTTP client (with optional GUI) for the API era. JSON support, colors, sessions, downloads, plugins & more.

GUI

HTTPie features a graphical application for API testing. It supports everything features in the CLI version but with graphics.

Screenshot

CLI

Usage:

http [flags] [METHOD] URL [ITEM [ITEM]]

Querystring parameters

If you find yourself manually constructing URLs with querystring parameters on the terminal, you may appreciate the param==value syntax for appending URL parameters.

With that, you dont have to worry about escaping the & separators for your shell. Additionally, any special characters in the parameter name or value get automatically URL-escaped (as opposed to the parameters specified in the full URL, which HTTPie doesnt modify).

$ http https://api.github.com/search/repositories q==httpie per_page==1
GET /search/repositories?q=httpie&per_page=1 HTTP/1.1

Request Items

Item Type Description
HTTP Headers Name:Value Arbitrary HTTP header, e.g. X-API-Token:123
URL parameters name==value Appends the given name/value pair as a querystring parameter to the URL. The == separator is used.
Data Fields field=value Request data fields to be serialized as a JSON object (default), to be form-encoded (with --form, -f), or to be serialized as multipart/form-data (with --multipart)
Raw JSON fields field:=json Useful when sending JSON and one or more fields need to be a Boolean, Number, nested Object, or an Array, e.g., meals:='["ham","spam"]' or pies:=[1,2,3] (note the quotes)
File upload fields field@/dir/file, field@file;type=mime Only available with --form, -f and --multipart. For example screenshot@~/Pictures/img.png, or 'cv@cv.txt;type=text/markdown'. With --form, the presence of a file field results in a --multipart request

JSON Requests

Data is send as JSON by default.

Non-string JSON fields use the := separator, which allows you to embed arbitrary JSON data into the resulting JSON object. Additionally, text and raw JSON files can also be embedded into fields using =@ and :=@:

$ http PUT pie.dev/put \
    name=John \                        # String (default)
    age:=29 \                          # Raw JSON — Number
    married:=false \                   # Raw JSON — Boolean
    hobbies:='["http", "pies"]' \      # Raw JSON — Array
    favorite:='{"tool": "HTTPie"}' \   # Raw JSON — Object
    bookmarks:=@files/data.json \      # Embed JSON file
    description=@files/text.txt        # Embed text file
PUT /person/1 HTTP/1.1
Accept: application/json, */*;q=0.5
Content-Type: application/json
Host: pie.dev

{
    "age": 29,
    "hobbies": [
        "http",
        "pies"
    ],
    "description": "John is a nice guy who likes pies.",
    "married": false,
    "name": "John",
    "favorite": {
        "tool": "HTTPie"
    },
    "bookmarks": {
        "HTTPie": "https://httpie.org",
    }
}

Forms

Submitting forms is very similar to sending JSON requests. Often the only difference is in adding the --form, -f option, which ensures that data fields are serialized as, and Content-Type is set to application/x-www-form-urlencoded; charset=utf-8.

Regular forms

$ http --form POST pie.dev/post name='John Smith'
POST /post HTTP/1.1
Content-Type: application/x-www-form-urlencoded; charset=utf-8

name=John+Smith

File upload forms

If one or more file fields is present, the serialization and content type is multipart/form-data:

$ http -f POST pie.dev/post name='John Smith' cv@~/files/data.xml

The request above is the same as if the following HTML form were submitted:

<form enctype="multipart/form-data" method="post" action="http://example.com/jobs">
    <input type="text" name="name" />
    <input type="file" name="cv" />
</form>

Please note that @ is used to simulate a file upload form field, whereas =@ just embeds the file content as a regular text field value.

When uploading files, their content type is inferred from the file name. You can manually override the inferred content type:

$ http -f POST pie.dev/post name='John Smith' cv@'~/files/data.bin;type=application/pdf'

HTTP headers

To set custom headers you can use the Header:Value notation:

$ http pie.dev/headers User-Agent:Bacon/1.0 'Cookie:valued-visitor=yes;foo=bar' \
    X-Foo:Bar Referer:https://httpie.org/
GET /headers HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
Cookie: valued-visitor=yes;foo=bar
Host: pie.dev
Referer: https://httpie.org/
User-Agent: Bacon/1.0
X-Foo: Bar

Default request headers

There are a couple of default headers that HTTPie sets:

GET / HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
User-Agent: HTTPie/<version>
Host: <taken-from-URL>

All of these can be overwritten or unset.

Reading headers from a file

You can read headers from a file by using the :@ operator. This would also effectively strip the newlines from the end.

$ http pie.dev/headers X-Data:@files/text.txt

Empty headers and header un-setting

To unset a previously specified header (such a one of the default headers), use Header::

$ http pie.dev/headers Accept: User-Agent:

To send a header with an empty value, use Header;, with a semicolon:

$ http pie.dev/headers 'Header;'

Please note that some internal headers, such as Content-Length, cant be unset if they are automatically added by the client itself.

Multiple header values with the same name

If the request is sent with multiple headers that are sharing the same name, then the HTTPie will send them individually.

http example.org Cookie:one Cookie:two
GET / HTTP/1.1
Cookie: one
Cookie: two

It is also possible to pass a single header value pair, where the value is a comma separated list of header values. Then the client will send it as a single header.

http example.org Numbers:one,two
GET / HTTP/1.1
Numbers: one,two

Also be aware that if the current session contains any headers they will get overwritten by individual commands when sending a request instead of being joined together.

Offline mode

Use --offline to construct HTTP requests without sending them anywhere. With --offline, HTTPie builds a request based on the specified options and arguments, prints it to stdout, and then exits. It works completely offline; no network connection is ever made. This has a number of use cases, including:

Generating API documentation examples that you can copy & paste without sending a request:

$ http --offline POST server.chess/api/games API-Key:ZZZ w=magnus b=hikaru t=180 i=2
$ http --offline MOVE server.chess/api/games/123 API-Key:ZZZ p=b a=R1a3 t=77

Generating raw requests that can be sent with any other client:

# 1. save a raw request to a file:
$ http --offline POST pie.dev/post hello=world > request.http

# 2. send it over the wire with, for example, the fantastic netcat tool:
$ nc pie.dev 80 < request.http

You can also use the --offline mode for debugging and exploring HTTP and HTTPie, and for “dry runs”.

Cookies

HTTP clients send cookies to the server as regular HTTP headers. That means, HTTPie does not offer any special syntax for specifying cookies — the usual Header:Value notation is used:

Send a single cookie:

$ http pie.dev/cookies Cookie:sessionid=foo
GET / HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
Connection: keep-alive
Cookie: sessionid=foo
Host: pie.dev
User-Agent: HTTPie/0.9.9

Send multiple cookies (note: the header is quoted to prevent the shell from interpreting the ;):

$ http pie.dev/cookies 'Cookie:sessionid=foo;another-cookie=bar'
GET / HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
Connection: keep-alive
Cookie: sessionid=foo;another-cookie=bar
Host: pie.dev
User-Agent: HTTPie/0.9.9

Authentication

Basic auth

$ http -a username:password pie.dev/basic-auth/username/password

Digest auth

$ http -A digest -a username:password pie.dev/digest-auth/httpie/username/password

Bearer auth

https -A bearer -a token pie.dev/bearer

Password prompt

If you omit the password part of --auth, -a, HTTPie securely prompts you for it:

$ http -a username pie.dev/basic-auth/username/password

HTTP redirects

By default, HTTP redirects are not followed and only the first response is shown:

$ http pie.dev/redirect/3

Follow Location

To instruct HTTPie to follow the Location header of 30x responses and show the final response instead, use the --follow, -F option:

$ http --follow pie.dev/redirect/3

With 307 Temporary Redirect and 308 Permanent Redirect, the method and the body of the original request are reused to perform the redirected request. Otherwise, a body-less GET request is performed.

Showing intermediary redirect responses

If you wish to see the intermediary requests/responses, then use the --all option:

$ http --follow --all pie.dev/redirect/3

Limiting maximum redirects followed

To change the default limit of maximum 30 redirects, use the --max-redirects=<limit> option:

$ http --follow --all --max-redirects=2 pie.dev/redirect/3

Proxies

You can specify proxies to be used through the --proxy argument for each protocol (which is included in the value in case of redirects across protocols):

$ http --proxy=http:http://10.10.1.10:3128 --proxy=https:https://10.10.1.10:1080 example.org

With Basic authentication:

$ http --proxy=http:http://user:pass@10.10.1.10:3128 example.org

Environment variables

You can also configure proxies by environment variables ALL_PROXY, HTTP_PROXY and HTTPS_PROXY, and the underlying Requests library will pick them up. If you want to disable proxies configured through the environment variables for certain hosts, you can specify them in NO_PROXY.

In your ~/.bash_profile:

export HTTP_PROXY=http://10.10.1.10:3128
export HTTPS_PROXY=https://10.10.1.10:1080
export NO_PROXY=localhost,example.com

SOCK

Usage for SOCKS is the same as for other types of proxies:

$ http --proxy=http:socks5://user:pass@host:port --proxy=https:socks5://user:pass@host:port example.org

HTTPS

To skip the hosts SSL certificate verification, you can pass --verify=no (default is yes):

$ http --verify=no https://pie.dev/get

Output options

By default, HTTPie only outputs the final response and the whole response message is printed (headers as well as the body). You can control what should be printed via several options:

Option What is printed
--headers, -h Only the response headers are printed
--body, -b Only the response body is printed
--meta, -m Only the response metadata is printed
--verbose, -v Print the whole HTTP exchange (request and response). This option also enables --all (see below)
--verbose --verbose, -vv Just like -v, but also include the response metadata.
--print, -p Selects parts of the HTTP exchange
--quiet, -q Dont print anything to stdout and stderr

Download mode

HTTPie features a download mode in which it acts similarly to wget.

When enabled using the --download, -d flag, response headers are printed to the terminal (stderr), and a progress bar is shown while the response body is being saved to a file.

$ http --download https://github.com/httpie/cli/archive/master.tar.gz
HTTP/1.1 200 OK
Content-Disposition: attachment; filename=httpie-master.tar.gz
Content-Length: 257336
Content-Type: application/x-gzip

Downloading 251.30 kB to "httpie-master.tar.gz"
Done. 251.30 kB in 2.73862s (91.76 kB/s)

Downloaded filename

There are three mutually exclusive ways through which HTTPie determines the output filename (with decreasing priority):

  1. You can explicitly provide it via --output, -o. The file gets overwritten if it already exists (or appended to with --continue, -c).
  2. The server may specify the filename in the optional Content-Disposition response header. Any leading dots are stripped from a server-provided filename.
  3. The last resort HTTPie uses is to generate the filename from a combination of the request URL and the response Content-Type. The initial URL is always used as the basis for the generated filename — even if there has been one or more redirects.

To prevent data loss by overwriting, HTTPie adds a unique numerical suffix to the filename when necessary (unless specified with --output, -o).

Piping while downloading

You can also redirect the response body to another program while the response headers and progress are still shown in the terminal:

$ http -d https://github.com/httpie/cli/archive/master.tar.gz | tar zxf -

Resuming downloads

If --output, -o is specified, you can resume a partial download using the --continue, -c option. This only works with servers that support Range requests and 206 Partial Content responses. If the server doesnt support that, the whole file will simply be downloaded:

$ http -dco file.zip example.org/file

-dco is shorthand for --download --continue --output.

Sessions

By default, every request HTTPie makes is completely independent of any previous ones to the same host.

However, HTTPie also supports persistent sessions via the --session=SESSION_NAME_OR_PATH option. In a session, custom HTTP headers (except for the ones starting with Content- or If-), authentication, and cookies (manually specified or sent by the server) persist between requests to the same host.

# Create a new session:
$ http --session=./session.json pie.dev/headers API-Token:123

# Inspect / edit the generated session file:
$ cat session.json

# Re-use the existing session — the API-Token header will be set:
$ http --session=./session.json pie.dev/headers

All session data, including credentials, prompted passwords, cookie data, and custom headers are stored in plain text. That means session files can also be created and edited manually in a text editor—they are regular JSON. It also means that they can be read by anyone who has access to the session file.

Readonly session

To use the original session file without updating it from the request/response exchange after it has been created, specify the session name via --session-read-only=SESSION_NAME_OR_PATH instead.

# If the session file doesnt exist, then it is created:
$ http --session-read-only=./ro-session.json pie.dev/headers Custom-Header:orig-value

# But it is not updated:
$ http --session-read-only=./ro-session.json pie.dev/headers Custom-Header:new-value