CLI の HTTP クライアントである xh の基本的な使い方
以前に HTTPie のインストールと基本的な使い方 というメモを書きました。 HTTPie は CLI の HTTP / HTTPS クライアントです。 これを Rust で書き直したものが xh です。 xh は HTTPie とオプションがほぼ互換である為、HTTPie の利用経験があれば xh も利用出来るはずです。 HTTPie と xh の比較については How xh compares to HTTPie に以下の記載があります。
Advantages¶
- Improved startup speed.
- Available as a single statically linked binary that's easy to install and carry around.
- HTTP/2 support.
- Builtin translation to curl commands with the --curl flag.
- Short, cheatsheet-style output from --help. (For longer output, pass help.)
Disadvantages¶
- Not all of HTTPie's features are implemented. (#4)
- No plugin system.
- General immaturity. HTTPie is old and well-tested.
- Worse documentation.
今回は xh の基本的な使い方をメモしておきます。
検証環境¶
対象 | バージョン |
---|---|
Ubuntu | 24.04.2 LTS |
xh | 0.24.0 |
インストール¶
Ubuntu へ xh をインストールするには下記などの方法があります。
- Rust Tools apt repo からインストールする
- シェルスクリプトでインストールする
Rust Tools apt repo からインストールする¶
Rust Tools apt repo の追加方法は Ubuntu に「Rust Tools apt repo」をインストールする にメモしてあります。
curl -fsSL https://apt.cli.rs/pubkey.asc | sudo tee -a /usr/share/keyrings/rust-tools.asc &&
curl -fsSL https://apt.cli.rs/rust-tools.list | sudo tee /etc/apt/sources.list.d/rust-tools.list &&
sudo apt update &&
sudo apt -y install xh
シェルスクリプトでインストールする¶
シェルスクリプトでインストールする場合は公式ページに記載されている通り、以下を実行します。
curl -sfL https://raw.githubusercontent.com/ducaale/xh/master/install.sh | sh
インストールされるファイル¶
xh を apt をインストールした場合、以下のファイル群がインストールされます。 バイナリとして /usr/bin/xh
と /usr/bin/xhs
のふたつがインストールされます。
# dpkg -L xh | sort
/usr
/usr/bin
/usr/bin/xh
/usr/bin/xhs
/usr/share
/usr/share/bash-completion
/usr/share/bash-completion/completions
/usr/share/bash-completion/completions/xh
/usr/share/doc
/usr/share/doc/xh
/usr/share/doc/xh/NEWS.gz
/usr/share/doc/xh/README
/usr/share/doc/xh/copyright
/usr/share/fish
/usr/share/fish/vendor_completions.d
/usr/share/fish/vendor_completions.d/xh.fish
/usr/share/man
/usr/share/man/man1
/usr/share/man/man1/xh.1.gz
/usr/share/man/man1/xhs.1.gz
/usr/share/zsh
/usr/share/zsh/vendor-completions
/usr/share/zsh/vendor-completions/_xh
オプションを何も指定せずに実行する¶
オプションを何も指定せず、実行した場合は (HTTPS では無く) HTTP リクエストを実行します。
# xh httpbin.org/get
HTTP/1.1 200 OK
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: *
Connection: keep-alive
Content-Length: 302
Content-Type: application/json
Date: Sun, 23 Feb 2025 00:53:56 GMT
Server: gunicorn/19.9.0
{
"args": {},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate, br, zstd",
"Host": "httpbin.org",
"User-Agent": "xh/0.24.0",
"X-Amzn-Trace-Id": "Root=1-67ba71a4-3ff5911004fb8f5648199362"
},
"origin": "192.0.2.1",
"url": "http://httpbin.org/get"
}
ヘッダ・ボディを表示する¶
xh は指定が無い場合はレスポンス、具体的にはレスポンスヘッダとレスポンスボディのみ、表示します。 指定した部分だけを表示するには --print
オプションに続けて文字列を指定します。
--print に指定する文字列 |
リクエスト/レスポンス | ヘッダ/ボディ |
---|---|---|
H |
リクエスト | ヘッダ |
B |
リクエスト | ボディ |
h |
レスポンス | ヘッダ |
b |
レスポンス | ボディ |
幾つかの実行例をメモしておきます。
レスポンスのみ、表示する (デフォルト)¶
これはデフォルトの動作です。 つまり、xh httpbin.org/get
と xh --print=hb httpbin.org/get
は同じ振る舞いをします。
# xh --print=hb httpbin.org/get
HTTP/1.1 200 OK
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: *
Connection: keep-alive
Content-Length: 302
Content-Type: application/json
Date: Sun, 23 Feb 2025 00:56:17 GMT
Server: gunicorn/19.9.0
{
"args": {},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate, br, zstd",
"Host": "httpbin.org",
"User-Agent": "xh/0.24.0",
"X-Amzn-Trace-Id": "Root=1-67ba7231-33ac10c856212b6278eea152"
},
"origin": "192.0.2.1",
"url": "http://httpbin.org/get"
}
リクエストヘッダのみ、表示する¶
# xh --print=H httpbin.org/get
GET /get HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate, br, zstd
Connection: keep-alive
Host: httpbin.org
User-Agent: xh/0.24.0
レスポンスヘッダのみ、表示する¶
# xh --print=h httpbin.org/get
HTTP/1.1 200 OK
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: *
Connection: keep-alive
Content-Length: 302
Content-Type: application/json
Date: Sun, 23 Feb 2025 00:55:21 GMT
Server: gunicorn/19.9.0
リクエストボディのみ、表示する¶
POST リクエストを実行する場合のデータ部分を表示することも出来ます。
# echo "[1, 2, 3]" | xh post --print=B httpbin.org/post
[
1,
2,
3
]
レスポンスボディのみ、表示する¶
# xh --print=b httpbin.org/get
{
"args": {},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate, br, zstd",
"Host": "httpbin.org",
"User-Agent": "xh/0.24.0",
"X-Amzn-Trace-Id": "Root=1-67ba720a-12f37af63daea3183cc2741e"
},
"origin": "192.0.2.1",
"url": "http://httpbin.org/get"
}
ヘッダのみ、表示する (リクエストヘッダ&レスポンスヘッダ)¶
# xh --print=Hh httpbin.org/get
GET /get HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate, br, zstd
Connection: keep-alive
Host: httpbin.org
User-Agent: xh/0.24.0
HTTP/1.1 200 OK
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: *
Connection: keep-alive
Content-Length: 302
Content-Type: application/json
Date: Sun, 23 Feb 2025 00:56:00 GMT
Server: gunicorn/19.9.0
HTTPS アクセスする¶
xh は http://
や https://
といった指定が無い場合、デフォルトで (HTTPS リクエストでは無く) HTTP リクエストを発行します。
# xh --print=b httpbin.org/get
{
"args": {},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate, br, zstd",
"Host": "httpbin.org",
"User-Agent": "xh/0.24.0",
"X-Amzn-Trace-Id": "Root=1-67ba74c0-4382cc512eda1fa7150933a3"
},
"origin": "192.0.2.1",
"url": "http://httpbin.org/get"
}
アクセス先が HTTPS の場合、xh https://example.com
と実行するか、もしくは xhs example.com
と実行することで HTTPS リクエストを発行出来ます。
# xhs --print=b httpbin.org/get
{
"args": {},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate, br, zstd",
"Host": "httpbin.org",
"User-Agent": "xh/0.24.0",
"X-Amzn-Trace-Id": "Root=1-67ba74c5-4c0d1a0f5075367f2257ff5d"
},
"origin": "192.0.2.1",
"url": "https://httpbin.org/get"
}
結果を保存する¶
結果を保存するには -d
(--download
) と -o
(--output
) オプションを指定します。
# xh -d httpbin.org/json -o res.json
HTTP/1.1 200 OK
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: *
Connection: keep-alive
Content-Length: 429
Content-Type: application/json
Date: Sun, 23 Feb 2025 01:08:18 GMT
Server: gunicorn/19.9.0
Downloading 429 B to "res.json"
Done. 429 B in 0.00027s (1.54 MiB/s)
# cat res.json
{
"slideshow": {
"author": "Yours Truly",
"date": "date of publication",
"slides": [
{
"title": "Wake up to WonderWidgets!",
"type": "all"
},
{
"items": [
"Why <em>WonderWidgets</em> are great",
"Who <em>buys</em> WonderWidgets"
],
"title": "Overview",
"type": "all"
}
],
"title": "Sample Slide Show"
}
}
リクエストヘッダを追加する¶
リクエストヘッダを追加するには HEADER:VALUE
のように指定します。
# xh --print=H httpbin.org/get X-AAA:aaa X-BBB:bbb X-CCC:ccc
GET /get HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate, br, zstd
Connection: keep-alive
Host: httpbin.org
User-Agent: xh/0.24.0
X-Aaa: aaa
X-Bbb: bbb
X-Ccc: ccc
但し、リクエストアイテム部分を URL より前に指定するとエラーになるので注意が必要です。
# xh --print=H X-AAA:aaa httpbin.org/get
error: Invalid value for '[REQUEST_ITEM]...': "httpbin.org/get"
Usage: xh [OPTIONS] <[METHOD] URL> [REQUEST_ITEM]...
For more information, try '--help'.
User-Agent を書き換える¶
リクエストヘッダの追加とほぼ同様の手順ですが、User-Agent
を書き換えるには user-agent:VALUE
のように指定します。
# xh --print=H httpbin.org/get user-agent:foobar
GET /get HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate, br, zstd
Connection: keep-alive
Host: httpbin.org
User-Agent: foobar
サーバ証明書の警告を無視する¶
サーバ証明書に問題がある場合、デフォルトではアクセスすることが出来ません。
# xh https://192.0.2.100
xh: error: error sending request for url (https://192.0.2.100/)
Caused by:
0: client error (Connect)
1: invalid peer certificate: UnknownIssuer
サーバ証明書の警告を無視してアクセスを続行するには --verify no
を指定します。
# xh --verify no https://192.0.2.100
HTTP/1.1 200 OK
Accept-Ranges: bytes
Connection: Keep-Alive
Content-Length: 10
Content-Type: text/html
Date: Sun, 23 Feb 2025 01:22:49 GMT
Etag: "a-62ec50fa12960"
Keep-Alive: timeout=5, max=100
Last-Modified: Sun, 23 Feb 2025 01:22:45 GMT
Server: Apache/2.4.58 (Ubuntu)
It works!
Proxy 経由でアクセスする¶
Proxy 経由でアクセスする場合は --proxy PROTOCOL:PROXY_URL
オプションを指定します。 下記の実行例では --proxy http:http://
と記載されており、一見誤っているように見えますが PROTOCOL:PROXY_URL
と指定する必要がある為、これは正しい指定です。
# xh --proxy http:http://192.0.2.200:8080 http://httpbin.org/get
HTTP/1.1 200 OK
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: *
Cache-Status: unknown;detail=no-cache
Connection: keep-alive
Content-Length: 351
Content-Type: application/json
Date: Sun, 23 Feb 2025 01:29:55 GMT
Server: gunicorn/19.9.0
Via: 1.1 unknown (squid)
{
"args": {},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate, br, zstd",
"Cache-Control": "max-age=259200",
"Host": "httpbin.org",
"User-Agent": "xh/0.24.0",
"X-Amzn-Trace-Id": "Root=1-67ba7a13-53e282720676bfaf6be2fe47"
},
"origin": "unknown, 192.0.2.1",
"url": "http://httpbin.org/get"
}
設定ファイルでデフォルト値を指定する¶
xh を実行した時のデフォルト値は予め .config/xh/config.json
ファイルに JSON 形式で指定しておくことが出来ます。 例えば以下のように指定します。
{ "default_options": ["--print=Hh", "--verify=no"] }
この設定を行うことにより「リクエスト・レスポンスのヘッダのみを表示し、サーバ証明書の検証を行わない」という振る舞いをします。
# xh httpbin.org/get
GET /get HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate, br, zstd
Connection: keep-alive
Host: httpbin.org
User-Agent: xh/0.24.0
HTTP/1.1 200 OK
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: *
Connection: keep-alive
Content-Length: 302
Content-Type: application/json
Date: Sun, 23 Feb 2025 03:28:17 GMT
Server: gunicorn/19.9.0
但し、現時点では以下のように KEY:VALUE を指定するとエラーになってしまうようです。
{ "default_options": ["--print=Hh", "foo:bar"] }
参考¶
xh のヘルプ¶
# xh --help
xh is a friendly and fast tool for sending HTTP requests
Usage: xh [OPTIONS] <[METHOD] URL> [REQUEST_ITEM]...
Arguments:
<[METHOD] URL> The request URL, preceded by an optional HTTP method
[REQUEST_ITEM]... Optional key-value pairs to be included in the request.
Options:
-j, --json (default) Serialize data items from the command line as a JSON object
-f, --form Serialize data items from the command line as form fields
--multipart Like --form, but force a multipart/form-data request even without files
--raw <RAW> Pass raw request data without extra processing
--pretty <STYLE> Controls output processing [possible values: all, colors, format, none]
--format-options <FORMAT_OPTIONS> Set output formatting options
-s, --style <THEME> Output coloring style [possible values: auto, solarized, monokai, fruity]
--response-charset <ENCODING> Override the response encoding for terminal display purposes
--response-mime <MIME_TYPE> Override the response mime type for coloring and formatting for the terminal
-p, --print <FORMAT> String specifying what the output should contain
-h, --headers Print only the response headers. Shortcut for --print=h
-b, --body Print only the response body. Shortcut for --print=b
-m, --meta Print only the response metadata. Shortcut for --print=m
-v, --verbose... Print the whole request as well as the response
--debug Print full error stack traces and debug log messages
--all Show any intermediary requests/responses while following redirects with --follow
-P, --history-print <FORMAT> The same as --print but applies only to intermediary requests/responses
-q, --quiet... Do not print to stdout or stderr
-S, --stream Always stream the response body
-x, --compress... Content compressed (encoded) with Deflate algorithm
-o, --output <FILE> Save output to FILE instead of stdout
-d, --download Download the body to a file instead of printing it
-c, --continue Resume an interrupted download. Requires --download and --output
--session <FILE> Create, or reuse and update a session
--session-read-only <FILE> Create or read a session without updating it form the request/response exchange
-A, --auth-type <AUTH_TYPE> Specify the auth mechanism [possible values: basic, bearer, digest]
-a, --auth <USER[:PASS] | TOKEN> Authenticate as USER with PASS (-A basic|digest) or with TOKEN (-A bearer)
--ignore-netrc Do not use credentials from .netrc
--offline Construct HTTP requests without sending them anywhere
--check-status (default) Exit with an error status code if the server replies with an error
-F, --follow Do follow redirects
--max-redirects <NUM> Number of redirects to follow. Only respected if --follow is used
--timeout <SEC> Connection timeout of the request
--proxy <PROTOCOL:URL> Use a proxy for a protocol. For example: --proxy https:http://proxy.host:8080
--verify <VERIFY> If "no", skip SSL verification. If a file path, use it as a CA bundle
--cert <FILE> Use a client side certificate for SSL
--cert-key <FILE> A private key file to use with --cert
--ssl <VERSION> Force a particular TLS version [possible values: auto, tls1, tls1.1, tls1.2, tls1.3]
--https Make HTTPS requests if not specified in the URL
--http-version <VERSION> HTTP version to use [possible values: 1.0, 1.1, 2, 2-prior-knowledge]
--resolve <HOST:ADDRESS> Override DNS resolution for specific domain to a custom IP
--interface <NAME> Bind to a network interface or local IP address
-4, --ipv4 Resolve hostname to ipv4 addresses only
-6, --ipv6 Resolve hostname to ipv6 addresses only
-I, --ignore-stdin Do not attempt to read stdin
--curl Print a translation to a curl command
--curl-long Use the long versions of curl's flags
--generate <KIND> Generate shell completions or man pages
--help Print help
-V, --version Print version
Each option can be reset with a --no-OPTION argument.
Run "xh help" for more complete documentation.