HTTPie を Cloudflare API / GraphQL 用に設定する

# HTTPie とは

- Web, Desktop App, CLI から使える便利ツール

> [HTTPie – API testing client that flows with you](https://httpie.io/)

- curl の代替として最適

> [curlに変わる便利コマンドHTTPieを使ってみた - Qiita](https://qiita.com/ytabuchi/items/02fa15ac209823a4d19f)
>
> [httpie 使い方メモ](https://zenn.dev/mattak/articles/9276bd171a2b4b)

- GraphQL も叩ける

> [HTTPie で GraphQL を使う - Qiita](https://qiita.com/ekzemplaro/items/2134259a4c6bfa7817ce)

# HTTPie インストール
コマンドが `http` なので、わかりやすいですね。

```shell
brew install httpie
```

```shell
% http --version
3.2.1
```

# Credential store plugin インストール
API key を実行時に毎回記述する手間を省くために、プラグインを導入します。

> [ikalnytskyi/httpie-credential-store: Credential store plugin for HTTPie, attaches auth to ongoing request.](https://github.com/ikalnytskyi/httpie-credential-store)

https://httpie.io/docs/cli/httpie-cli-plugins-install

```shell
python3 -m pip install httpie-credential-store
httpie cli plugins install httpie-credential-store
```

```shell
% httpie cli plugins list      
httpie-credential-store (3.0.0)
  credential-store (httpie.plugins.auth.v1)
  creds (httpie.plugins.auth.v1)
```

# Credential ファイル設定
Cloudflare API / GraphQL をコールするための認証情報をファイルで設定します。

```shell
export EMAIL='YOUR_EMAIL'
export APIKEY='YOUR_APIKEY'
```

```shell
mkdir ~/.httpie
cat << EOS > ~/.httpie/credentials.json
[
  {
    "url": "api.cloudflare.com",
    "auth": {
      "provider": "multiple",
      "providers": [
        {
      	  "provider": "header",
          "name": "X-Auth-Email",
          "value": "${EMAIL}"
        },
        {
      	  "provider": "header",
          "name": "X-Auth-Key",
          "value": "${APIKEY}"
        }
      ]
    }
  }
]
EOS
chmod 400 ~/.httpie/credentials.json
```

# Cloudflare API コール

`-A creds` のオプションを付けて実行すればよい。

```shell
http -A creds GET https://api.cloudflare.com/client/v4/zones
```

ダッシュボードにある API ガイドに `http -A creds` をつければ、そのまま使えるので便利です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/334848c3-99ee-1e8e-c330-e9d6e0ca7531.png)

サンプルコール：ゾーンの設定値一覧を取得

```shell
export ZONE_ID='YOUR_ZONE_ID'

% http -A creds GET https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/settings | jq -r '.result[] | [.editable,.id,.modified_on,.value|tostring]|@csv'
"true","0rtt","null","off"
"false","advanced_ddos","null","on"
"true","always_online","2021-07-01T15:11:49.794076Z","on"
"true","always_use_https","2022-09-06T18:17:13.844163Z","on"
"true","automatic_https_rewrites","null","off"
"true","brotli","2021-09-06T05:35:03.436837Z","on"
"true","browser_cache_ttl","null","14400"
"true","browser_check","2021-08-23T13:56:31.228728Z","off"
"true","cache_level","null","aggressive"
"true","challenge_ttl","null","1800"
"true","ciphers","null","[""ECDHE-ECDSA-AES128-GCM-SHA256""]"
"true","cname_flattening","null","flatten_all"
"true","development_mode","null","off"
"true","early_hints","null","on"
"true","edge_cache_ttl","null","7200"
"true","email_obfuscation","null","on"
"true","filter_logs_to_cloudflare","null","off"
"true","hotlink_protection","2022-02-21T02:59:48.431747Z","on"
"true","http2","null","on"
"true","http3","2021-08-23T07:21:11.227618Z","on"
"true","ip_geolocation","null","on"
"true","ipv6","2022-02-21T02:33:24.638689Z","on"
"true","log_to_cloudflare","null","on"
"true","long_lived_grpc","null","off"
"true","max_upload","2022-02-21T02:33:43.971329Z","500"
"true","min_tls_version","null","1.0"
"true","minify","2021-09-06T05:35:43.295595Z","{""js"":""on"",""css"":""on"",""html"":""on""}"
"true","mirage","2021-08-10T05:16:21.602454Z","on"
"true","mobile_redirect","null","{""status"":""off"",""mobile_subdomain"":null,""strip_uri"":false}"
"true","opportunistic_encryption","null","off"
"true","opportunistic_onion","null","on"
"true","orange_to_orange","null","off"
"true","origin_error_page_pass_thru","null","off"
"true","polish","2021-09-03T02:26:58.070012Z","lossy"
"true","pq_keyex","null","on"
"true","prefetch_preload","null","off"
"true","privacy_pass","null","on"
"true","proxy_read_timeout","null","100"
"true","pseudo_ipv4","2021-07-29T04:15:51.230691Z","add_header"
"true","response_buffering","null","off"
"true","rocket_loader","2021-08-24T01:40:37.546320Z","on"
"true","security_header","null","{""strict_transport_security"":{""enabled"":false,""max_age"":0,""include_subdomains"":false,""preload"":false,""nosniff"":false}}"
"true","security_level","2022-09-21T05:30:49.140228Z","off"
"true","server_side_exclude","null","on"
"true","sort_query_string_for_cache","null","off"
"true","ssl","2022-08-05T16:12:36.533013Z","full"
"true","tls_1_2_only","null","off"
"true","tls_1_3","null","on"
"true","tls_client_auth","2021-10-14T07:34:31.711373Z","on"
"true","true_client_ip_header","null","off"
"true","visitor_ip","null","on"
"true","waf","2021-08-04T05:45:29.377270Z","off"
"true","webp","2021-09-03T02:21:10.978032Z","on"
"true","websockets","null","on"
```

# Cloudflare GraphQL コール

> [Querying basics · Cloudflare Analytics docs](https://developers.cloudflare.com/analytics/graphql-api/getting-started/querying-basics/#example-query)

```shell
export GQL_ENDPOINT='https://api.cloudflare.com/client/v4/graphql'

http -A creds $GQL_ENDPOINT query='query
{
  viewer
  {
    zones(filter: { zoneTag: "'$ZONE_ID'"})
    {
      firewallEventsAdaptive(
          filter: {
            datetime_gt: "2022-09-03T02:07:05Z",
            datetime_lt: "2022-09-03T17:07:05Z"
          },
          limit: 2,
          orderBy: [datetime_DESC, rayName_DESC])
      {
        action
        datetime
        rayName
        clientRequestHTTPHost
        userAgent
      }
    }
  }
}
'
```