APIクライアント開発時のモックに使えるhttpbinの紹介

# 今すぐ使えるAPIサーバーのモックがほしい
 
自分でAPIサーバーのモック作るのはちょっとめんどいなぁ。。
と思った時にいつもお世話になっているhttpbinをご紹介します。

# 使い方

https://httpbin.org/
こちらを読んでいただければわかるのですが、`A simple HTTP Request & Response Service.` と書かれている通り、シンプルなHTTPリクエストとレスポンスを返してくれるサービスです。

例えば、こんな感じでレスポンスを返してくれます。

```
$ curl -G "https://httpbin.org/get"
{
  "args": {},
  "headers": {
    "Accept": "*/*",
    "Connection": "close",
    "Host": "httpbin.org",
    "User-Agent": "curl/7.54.0"
  },
  "origin": "XXX.XXX.XXX.XXX",
  "url": "https://httpbin.org/get"
}
```
※originにはアクセス元のIPアドレスが返されますので、マスクしときました。

これだけだと何が嬉しいのかわからないかと思いますが、
自分が送ったパラメータやヘッダー情報をレスポンスしてくれるため、正しくリクエストされているかどうかを簡易的に確認するのに最適なのです。
さらにGETメソッドだけではなくPOSTメソッドやPATCH,DELETEといったメソッドにも対応しているのでRESTful APIのモックとしても使うことができます。

全てではありませんが、有用そうな機能をいくつかご紹介します。

## 送信したパラメータとヘッダーを確認できる

テストにおいてパラメータおよびヘッダーが正しく送られているか確認するのは地味に面倒だったのですが、httpbinを使うと簡単に確認できます。
エンドポイントを`https://httpbin.org/get`に向ければいいのです。

例えばGETメソッドでパラメータを付けて送ると、このようなレスポンスが得られます。

```
$ curl -G "https://httpbin.org/get?param1=ABC&param2=DEF"
{
  "args": {
    "param1": "ABC",
    "param2": "DEF"
  },
  "headers": {
    "Accept": "*/*",
    "Connection": "close",
    "Host": "httpbin.org",
    "User-Agent": "curl/7.54.0"
  },
  "origin": "XXX.XXX.XXX.XXX",
  "url": "https://httpbin.org/get?param1=ABC&param2=DEF"
}
```

GET以外のメソッドでも可能です。
ただし、HTTPのメソッドごとにURLが違うため以下のようにエンドポイントを変える必要がありますので注意してください。

|HTTPメソッド|エンドポイント|
|---|---|
|GET|https://httpbin.org/get|
|POST|https://httpbin.org/post|
|PATCH|https://httpbin.org/patch|
|PUT|https://httpbin.org/put|
|DELETE|https://httpbin.org/delete|

なお、`http://`でも接続可能です。

## BASIC認証での接続をテストできる

BASIC認証（Digest認証も可能）で接続する場合のテストも簡単に行えます。

|エンドポイント|
|---|
|https://httpbin.org/basic-auth/{user}/{password}|

エンドポイントの`{user}`と`{password}`を任意に書き換えて、認証プロセスを試すことができます。

例えば、認証ヘッダーを送信せずにエンドポイントにアクセスすると以下のような401レスポンスが返ります。

```
curl -i -G "https://httpbin.org/basic-auth/testuser/testpassword"
HTTP/1.1 401 UNAUTHORIZED
Connection: keep-alive
Server: gunicorn/19.9.0
Date: Fri, 23 Nov 2018 05:34:46 GMT
Www-Authenticate: Basic realm="Fake Realm"
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Content-Length: 0
Via: 1.1 vegur

```

きちんとBASIC認証のヘッダーに正しいユーザー・パスワードをのせてリクエストするとこのような応答になります。

```
$ curl -i -G -u "testuser" --basic "https://httpbin.org/basic-auth/testuser/testpassword"
Enter host password for user 'testuser': 
HTTP/1.1 200 OK
Connection: keep-alive
Server: gunicorn/19.9.0
Date: Fri, 23 Nov 2018 05:44:02 GMT
Content-Type: application/json
Content-Length: 51
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Via: 1.1 vegur

{
  "authenticated": true,
  "user": "testuser"
}
```

## 任意のステータスコードをテストできる

|エンドポイント|
|---|
|https://httpbin.org/status/{codes}|

200以外のステータスコードがレスポンスされることをテストすることも可能です。
`{codes}`を任意のステータスコードに変えてリクエストするだけです。

```
$ curl -i -G "https://httpbin.org/status/404"
HTTP/1.1 404 NOT FOUND
Connection: keep-alive
Server: gunicorn/19.9.0
Date: Fri, 23 Nov 2018 05:47:10 GMT
Content-Type: text/html; charset=utf-8
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Content-Length: 0
Via: 1.1 vegur
```

500応答もこんな感じでテスト可能です。

```
$ curl -i -G "https://httpbin.org/status/500"
HTTP/1.1 500 INTERNAL SERVER ERROR
Connection: keep-alive
Server: gunicorn/19.9.0
Date: Fri, 23 Nov 2018 05:47:17 GMT
Content-Type: text/html; charset=utf-8
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Content-Length: 0
Via: 1.1 vegur

```

## Set-CookieによるCookieのセットをテストできる

Cookieをブラウザに保存する場合にはSet-Cookieヘッダーが送信されてきますが、それをテストすることも可能です。

|エンドポイント|
|---|
|https://httpbin.org/cookies/set/{name}/{value}|

`{name}`にCookieの名前、`{value}`にCookieの値をセットするとその通りにSet-Cookieヘッダーがレスポンスされます。

```
$ curl -i -G "https://httpbin.org/cookies/set/testcookie/12345"
HTTP/1.1 302 FOUND
Connection: keep-alive
Server: gunicorn/19.9.0
Date: Fri, 23 Nov 2018 12:14:47 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 223
Location: /cookies
Set-Cookie: testcookie=12345; Secure; Path=/
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Via: 1.1 vegur

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<title>Redirecting...</title>
<h1>Redirecting...</h1>
<p>You should be redirected automatically to target URL: <a href="/cookies">/cookies</a>.  If not click the link.
```

上のレスポンスボディにもある通り、ブラウザ（HTTPクライアント）に保存されているCookie情報を取得することもできます。

|エンドポイント|
|---|
|https://httpbin.org/cookies|

```
$ curl -i -G "https://httpbin.org/cookies" -H "Cookie: testcookie=1"
HTTP/1.1 200 OK
Connection: keep-alive
Server: gunicorn/19.9.0
Date: Fri, 23 Nov 2018 05:52:42 GMT
Content-Type: application/json
Content-Length: 45
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Via: 1.1 vegur

{
  "cookies": {
    "testcookie": "1"
  }
}
```

なお、こちらから送信したCookieヘッダーを確認するには`https://httpbin.org/cookies`にリクエストすれば確認できます。

## 遅延レスポンスをテストできる

HTTPリクエストを送信する際にはタイムアウトを設定することが通常だと思いますが、遅延レスポンスさせることによってタイムアウト値が適切に設定されているかどうかをテストすることができます。

|エンドポイント|
|---|
|https://httpbin.org/delay/{in_sec}|

`{in_sec}`のURLの`{in_sec}`に遅延させたい秒数を指定することで遅延レスポンスしてくれます。

```
$ curl -G "https://httpbin.org/delay/5" --max-time 2
curl: (28) Operation timed out after 2001 milliseconds with 0 bytes received
```

ただし、ここでは接続タイムアウトではなく、読み込みタイムアウトが確認できるということに注意してください。

## これらのテストをローカルで行える

と、ここまででも有用さが伝わっていると思うのですが、
httpbinの素晴らしいところはdockerコンテナも提供されていることです。

わざわざ外部にリクエストしなくてもdockerコンテナを立ち上げれば、ローカルでテストが可能です。

```
$ docker run -d -p 80:80 kennethreitz/httpbin
```

あとはローカルに向けるだけで同じテストが可能になります。

```
$ curl -G "http://localhost/get"
{
  "args": {},
  "headers": {
    "Accept": "*/*",
    "Host": "localhost",
    "User-Agent": "curl/7.54.0"
  },
  "origin": "172.17.0.1",
  "url": "http://localhost/get"
}
```

# まとめ

httpbin自体は結構前からあったのですが、最近になって便利さに気づいたのでまとめました。

紹介していない機能以外にもランダムなデータをレスポンスしたり、UUIDを生成したりするなど便利な機能は他にもあるので見てもらえればと思います。
が、やはり簡易的にモックとして使うのが良いかなと思います。
（そりゃちゃんとしたモックを自分で作るのが一番いい気もしますが、めんどくさいので。。。）

是非はあると思いますが、dockerコンテナが使えるのでCIに組み込んでテスト自動化に用いるのもアリかもしれません。