やりたいこと
前回, Nginx で特定のパスにおいて固定のレスポンス (ステータスコード, ボディ) を返す為の設定についてメモったけど, 今回は, これを検証するにあたって Go の testing パッケージでテストコードを書いて検証したお話を少し.
諸注意
動作確認環境は以下の通り.
$ nginx -V nginx version: nginx/1.15.10 built by gcc 6.3.0 20170516 (Debian 6.3.0-18+deb9u1) built with OpenSSL 1.1.0j 20 Nov 2018 TLS SNI support enabled configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-g -O2 -fdebug-prefix-map=/data/builder/debuild/nginx-1.15.10/debian/debuild-base/nginx-1.15.10=. -fstack-protector-strong -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fPIC' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -Wl,--as-needed -pie' $ go version go version go1.13.6 linux/amd64
やったこと
Nginx の設定
前回の記事を参考にして, こんな感じで設定を書いて /etc/nginx/conf.d/
以下におくようにした.
server { listen 80; server_name localhost; server_tokens off; location /healthcheck { access_log off; } location ~ ^/(foo/*|bar/*|baz/*)/ { default_type text/plan; return 400 'Bad Request!!!'; } }
上記の場合, /foo/xxxxx
や /bar/xxxxx
等にアクセスした場合, レスポンスコード 400
で Bad Request!!!
というボディを返す! (はず)
Go コードによるテスト
以下にプッシュしております.
コアとなる部分は以下の箇所.
func runTests(urls []string, t *testing.T) { for _, url := range urls { t.Run("URL: "+url, func(t *testing.T) { // Build Request req, _ := http.NewRequest("GET", url, nil) // Execute Request res, err := executeRequest(req) if err != nil { t.Fatalf("http.Get: %v", err) } defer res.Body.Close() // Display Test Result testResults(res, t) }) } } func executeRequest(req *http.Request) (*http.Response, error) { (略) }
http.NewRequest
でリクエスト型のオブジェクトを生成して, 自分で作った executeRequest
関数に投げています. 例えば, リクエストヘッダに何かヘッダ情報を追加したい場合には, 以下のように書きます.
req.Header.Set("Content-Type", "application/json")
また, 本記事では詳しく触れませんが, リダイレクトの動作検証を行いたい場合, 自分はリダイレクト先まで転送されるかよりも, ステータスコードが 301
または 302
が返却されるか, Location
ヘッダにリダイレクト先の URL が設定されているかを検証したかったので以下のように書きました.
func executeRequest(req *http.Request) (*http.Response, error) { client := new(http.Client) // Disable redirect following client.CheckRedirect = func(req *http.Request, via []*http.Request) error { return http.ErrUseLastResponse } (略) func testRedirectsResults(res *http.Response, target string, t *testing.T) { // ステータスコードが 301 で返却されることを確認 if res.StatusCode != 301 { t.Errorf("got %d, want %d", res.StatusCode, 301) } // レスポンスヘッダの Location に指定した target が定義されていることを確認 if res.Header.Get("Location") != target { t.Errorf("got %s, want %s", res.Header.Get("Location"), target) } }
上記のように リダイレクトに追従しないコードを書いているのがミソです.
話はだいぶん脱線してしまったけど, 検証を CircleCI で回した結果は下図の通り.
いい感じ.
以上
Go の testing パッケージで Nginx 設定を検証してみた. testing パッケージをはじめ, http パッケージについてもかなり奥深いけど, Bash で動作確認コードを書く感覚で書くことが出来たのので満足. ちゃんとテストコードを書くと以後の変更等も安心して大胆な変更にも対応出来るので良い!
参考
(完)