🔥

httpie 使い方メモ

10 min read

ついついcurl使いがちなんだけど、httpieに移行していきたいと思ったので使い方メモ

Install

brew install httpie

Help

helpとかmanを眺めるのって大事だよね

$ http --help
usage: http [--json] [--form] [--multipart] [--boundary BOUNDARY] [--raw RAW] [--compress]
            [--pretty {all,colors,format,none}] [--style STYLE] [--unsorted] [--sorted]
            [--response-charset ENCODING] [--response-mime MIME_TYPE] [--format-options FORMAT_OPTIONS]
            [--print WHAT] [--headers] [--body] [--verbose] [--all] [--history-print WHAT] [--stream]
            [--output FILE] [--download] [--continue] [--quiet]
            [--session SESSION_NAME_OR_PATH | --session-read-only SESSION_NAME_OR_PATH]
            [--auth USER[:PASS]] [--auth-type {basic,digest}] [--ignore-netrc] [--offline]
            [--proxy PROTOCOL:PROXY_URL] [--follow] [--max-redirects MAX_REDIRECTS]
            [--max-headers MAX_HEADERS] [--timeout SECONDS] [--check-status] [--path-as-is] [--chunked]
            [--verify VERIFY] [--ssl {ssl2.3,tls1,tls1.1,tls1.2}] [--ciphers CIPHERS] [--cert CERT]
            [--cert-key CERT_KEY] [--ignore-stdin] [--help] [--version] [--traceback]
            [--default-scheme DEFAULT_SCHEME] [--debug]
            [METHOD] URL [REQUEST_ITEM ...]

Usage

普通にGET取得する

$ http GET https://mattak.netlify.app

HTTP/1.1 200 OK
age: 1
cache-control: public, max-age=0, must-revalidate
content-encoding: gzip
content-type: text/html; charset=UTF-8
date: Tue, 14 Dec 2021 13:58:19 GMT
etag: "7bb91bbc5f12f51ab5a7d047d15173e0-ssl-df"
server: Netlify
strict-transport-security: max-age=31536000; includeSubDomains; preload
transfer-encoding: chunked
vary: Accept-Encoding
x-nf-request-id: 01FPWKS8HYSCG8TAWT499DC8W1

<!DOCTYPE html><html><head>
...

リダイレクトつけるとheaderは無くしつつcontentだけ出力してくれるっぽい (親切)

$ http GET https://mattak.netlify.app > /tmp/index.html
$ open /tmp/index.html # そのまま開ける

jqでそのままつなげる

$ http GET https://api.github.com/users/defunkt | jq .
{
    "avatar_url": "https://avatars.githubusercontent.com/u/2?v=4",
    "bio": "🍔",
    "blog": "http://chriswanstrath.com/",
    "company": null,
    "created_at": "2007-10-20T05:24:19Z",
    "email": null,
    "events_url": "https://api.github.com/users/defunkt/events{/privacy}",
    "followers": 21322,
    "followers_url": "https://api.github.com/users/defunkt/followers",
    "following": 210,
    "following_url": "https://api.github.com/users/defunkt/following{/other_user}",
    "gists_url": "https://api.github.com/users/defunkt/gists{/gist_id}",
    "gravatar_id": "",
    "hireable": null,
    "html_url": "https://github.com/defunkt",
    "id": 2,
    "location": null,
    "login": "defunkt",
    "name": "Chris Wanstrath",
    "node_id": "MDQ6VXNlcjI=",
    "organizations_url": "https://api.github.com/users/defunkt/orgs",
    "public_gists": 273,
    "public_repos": 107,
    "received_events_url": "https://api.github.com/users/defunkt/received_events",
    "repos_url": "https://api.github.com/users/defunkt/repos",
    "site_admin": false,
    "starred_url": "https://api.github.com/users/defunkt/starred{/owner}{/repo}",
    "subscriptions_url": "https://api.github.com/users/defunkt/subscriptions",
    "twitter_username": null,
    "type": "User",
    "updated_at": "2021-07-29T11:10:23Z",
    "url": "https://api.github.com/users/defunkt"
}

GETとかPOSTは省略可能みたい.

$ http pie.dev/post hello=offline
HTTP/1.1 200 OK
CF-Cache-Status: DYNAMIC
CF-RAY: 6bd800091c8834e7-NRT
Connection: keep-alive
Content-Encoding: gzip
Content-Type: application/json
Date: Tue, 14 Dec 2021 14:07:43 GMT
NEL: {"success_fraction":0,"report_to":"cf-nel","max_age":604800}
Report-To: {"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=4JWbRqN8jnftB1yNrKSifkrZ0FKYMI4Jqgs%2BsbWQGpcv4scuKBsP6xVFvKJRVmUocJEbPqy4BVf1Vo%2FQ4Mu2xDKHkFggRbOoio5Ze3GjI21rnbDYFVlNWz7ApPSYMkjew94I1kK9"}],"group":"cf-nel","max_age":604800}
Server: cloudflare
Transfer-Encoding: chunked
access-control-allow-credentials: true
access-control-allow-origin: *
alt-svc: h3=":443"; ma=86400, h3-29=":443"; ma=86400, h3-28=":443"; ma=86400, h3-27=":443"; ma=86400

{
    "args": {},
    "data": "{\"hello\": \"offline\"}",
    "files": {},
    "form": {},
    "headers": {
        "Accept": "application/json, */*;q=0.5",
        "Accept-Encoding": "gzip",
        "Cdn-Loop": "cloudflare",
        "Cf-Connecting-Ip": "240d:1a:cc8:ca00:914:bfe3:c96c:bb67",
        "Cf-Ipcountry": "JP",
        "Cf-Ray": "6bd800091c8834e7-FRA",
        "Cf-Visitor": "{\"scheme\":\"http\"}",
        "Connection": "Keep-Alive",
        "Content-Length": "20",
        "Content-Type": "application/json",
        "Host": "pie.dev",
        "User-Agent": "HTTPie/2.6.0"
    },
    "json": {
        "hello": "offline"
    },
    "origin": "240d:1a:cc8:ca00:914:bfe3:c96c:bb67",
    "url": "http://pie.dev/post"
}

-v でRequestHeaderも見れるようだ.
defaultでapplication/jsonのpostになってるのは便利!

$ http -v pie.dev/post hello=offline                                                                                                                  ~/github/mattak/blog [master|mattak|largeforest.local|23:07:43]
POST /post HTTP/1.1
Accept: application/json, */*;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Length: 20
Content-Type: application/json
Host: pie.dev
User-Agent: HTTPie/2.6.0

{
    "hello": "offline"
}


HTTP/1.1 200 OK
CF-Cache-Status: DYNAMIC
CF-RAY: 6bd8010ff91a80d5-NRT
Connection: keep-alive
Content-Encoding: gzip
Content-Type: application/json
Date: Tue, 14 Dec 2021 14:08:25 GMT
NEL: {"success_fraction":0,"report_to":"cf-nel","max_age":604800}
Report-To: {"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=QhcVNP02aLK8MKFz08X33FL%2B63UBGHv71rwfbLfbp%2BQdD47n6AVJA4oL28xMnWZqI2Nagfg9VoK%2BXQh2htSCVz98n6MG3Q0BIZXpjADe53zxE6uu4pXEGxG%2FCivhHTLCELcyjb%2F4"}],"group":"cf-nel","max_age":604800}
Server: cloudflare
Transfer-Encoding: chunked
access-control-allow-credentials: true
access-control-allow-origin: *
alt-svc: h3=":443"; ma=86400, h3-29=":443"; ma=86400, h3-28=":443"; ma=86400, h3-27=":443"; ma=86400

{
    "args": {},
    "data": "{\"hello\": \"offline\"}",
    "files": {},
    "form": {},
    "headers": {
        "Accept": "application/json, */*;q=0.5",
        "Accept-Encoding": "gzip",
        "Cdn-Loop": "cloudflare",
        "Cf-Connecting-Ip": "240d:1a:cc8:ca00:914:bfe3:c96c:bb67",
        "Cf-Ipcountry": "JP",
        "Cf-Ray": "6bd8010ff91a80d5-FRA",
        "Cf-Visitor": "{\"scheme\":\"http\"}",
        "Connection": "Keep-Alive",
        "Content-Length": "20",
        "Content-Type": "application/json",
        "Host": "pie.dev",
        "User-Agent": "HTTPie/2.6.0"
    },
    "json": {
        "hello": "offline"
    },
    "origin": "240d:1a:cc8:ca00:914:bfe3:c96c:bb67",
    "url": "http://pie.dev/post"
}

入力パイプからbody取れるのは地味にいいよね

$ http -v pie.dev/post < /tmp/post.json
POST /post HTTP/1.1
Accept: application/json, */*;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Length: 27
Content-Type: application/json
Host: pie.dev
User-Agent: HTTPie/2.6.0

{
    "hello": "offline"
}


HTTP/1.1 200 OK
CF-Cache-Status: DYNAMIC
CF-RAY: 6bd8038d8acbf8bb-NRT
Connection: keep-alive
Content-Encoding: gzip
Content-Type: application/json
Date: Tue, 14 Dec 2021 14:10:07 GMT
NEL: {"success_fraction":0,"report_to":"cf-nel","max_age":604800}
Report-To: {"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=ZiU0fLeDa%2FwaQAgWM9sJ4LfQwr%2Bg63zflgIT8EfLv9uICrgcJH7Wq%2Bf39bpFOEXyFI%2B%2FYsQ8XuMdyuIMdF%2BXkfuA0rr3f8WP%2B28qKuXRpAMEAMISA5%2BKWX0PVvTADDpl8b%2FMFaNd"}],"group":"cf-nel","max_age":604800}
Server: cloudflare
Transfer-Encoding: chunked
access-control-allow-credentials: true
access-control-allow-origin: *
alt-svc: h3=":443"; ma=86400, h3-29=":443"; ma=86400, h3-28=":443"; ma=86400, h3-27=":443"; ma=86400

{
    "args": {},
    "data": "{\n    \"hello\": \"offline\"\n}\n",
    "files": {},
    "form": {},
    "headers": {
        "Accept": "application/json, */*;q=0.5",
        "Accept-Encoding": "gzip",
        "Cdn-Loop": "cloudflare",
        "Cf-Connecting-Ip": "240d:1a:cc8:ca00:914:bfe3:c96c:bb67",
        "Cf-Ipcountry": "JP",
        "Cf-Ray": "6bd8038d8acbf8bb-FRA",
        "Cf-Visitor": "{\"scheme\":\"http\"}",
        "Connection": "Keep-Alive",
        "Content-Length": "27",
        "Content-Type": "application/json",
        "Host": "pie.dev",
        "User-Agent": "HTTPie/2.6.0"
    },
    "json": {
        "hello": "offline"
    },
    "origin": "240d:1a:cc8:ca00:914:bfe3:c96c:bb67",
    "url": "http://pie.dev/post"
}

X-Sample-Versionっていうヘッダも適当につけてみた.
= でよしなに解釈してくれるのは結構楽でいい!

$ http -v pie.dev/post hello=offline X-Sample-Version:1
POST /post HTTP/1.1
Accept: application/json, */*;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Length: 20
Content-Type: application/json
Host: pie.dev
User-Agent: HTTPie/2.6.0
X-Sample-Version: 1

{
    "hello": "offline"
}

...

感想

curlは細かい操作がなんでもできるけど、記述が冗長で現代のusageにfitしてない.
httpieはよくやる操作がシンプルで心地いいI/Fだと感じた.
普段使いはこれからhttpieにしていこう

Discussion

ログインするとコメントできます