Nginxで$argsや$request_uriの情報をサブリクエストに渡したい
今日したこと
- nginxと眠い頭で格闘. 結局負けました. 今日はその話を書きます
- rubyとか色々書いた
- 卒論発表スライドアウトラインバトル
Nginxでサブリクエスト
http_auth_requestモジュールを用いると,サブリクエストを行ってその結果でアクセス制御が実現できる.
{ server_name: hoge.com; listen 443; location / { auth_request /auth; error_page 401 = @login_page; proxy_pass http://app.hoge.com; } location /auth { proxy_pass http://login.hoge.com/auth; } location @login_page { return 302 https://login.hoge.com/login; } }
こんな具合に. 便利なもん.
ここで、http://hoge.com/?type=hoge
のようなアクセスを考える,
また認証エンドポイントであるlogin.hoge.com
はtype
を内部で利用し401or200を決定する.
この場合サブリクエストにtypeの値をなんとかして付与しなければならない.
以下試したこと
proxy_passに$argsを含める
proxy_pass http://login.hoge.com/auth$is_arg$args;
こう設定する. $argsはリクエストのクエリパラメータが入るnginxの変数,なのでこれで渡るのではないだろうか?
=> 無理 $argsは空となり, http://login.hoge.com/auth に単なるGetが送られる.
$argsを一度適当な変数に代入しておきそれをHTTPヘッダに付与させ送ろう
set $original_arg $args; location /auth { proxy_set_header X-Originl-Args $original_arg; proxy_pass http://login.hoge.com/auth; }
これでlogin側ではHTTPヘッダから$argを取り出せるのではないか??
=> 無理 $original_argは空となり,HTTPヘッダ付与は行われない.
惨敗
そもそもサブリクエスト時にコンテキストが切り替わり、$argとか$request_uriとかはすべてサブリクエスト時の値に切り替わっているっぽいことがわかった. なのでいつもの変数ではもともとの値を引くことができない?. そこそこ調べてもこうしてやった例を見つけることが出来なかった. Lua拡張を用いればおそらく引くことができるとは思うがデフォルトのNginxは変えたくない.
結局,色々とごにょって今回の問題には対処した時間もなかったし...
しかし以下のような解決策っぽいのを発見, 思いついた.
そもそも$request_uriなら取れるよ!
調べているうちに,argsは無理だが,request_uriなら引きずり出す方法を発見した.
つまり. locationを正規表現でマッチさせ,そこでキャプチャを行う. キャプチャしたものを変数にsetする. あとは良しなにやる なるほど思いつかなかった....
proxyを2段階にすればいいじゃない
ブラウザ => nginx(1段) => nginx(2段) => (login , app) という構成にすることでも対応できることに気づいた.
nginxの1段目では$argを適当なHTTPヘッダにセットする,そして上で2段目へproxyする. 2段目はいつもどおりauth_requestを行った後APPへProxyする.
サブリクエスト時にHTTPヘッダは引き継がれるので,loginには(特に落とさなければ)HTTPヘッダとして1段目でセットしたHTTPヘッダが飛んでいくし, サブリクエスト時に参照できなくなる変数は$argとか$request_uriとかだけなので,2段目のnginxのコンフィグではサブリクエストの時の設定で1段目でセットしたヘッダを参照することができる.
どうでもいいはなし
運用中のサービスのDBの根本的変更をやるためにDBのデータとか,各所の設定値とかをすべて変更するスクリプトとか書いててめんどいなーっておもった. もっとちゃんとしっかり考えて作れよーという反省.
ボスがなんか、なまずくんに上げるよー!!っていってくれた.
これは君がほしそうだから!!! って... まぁ机の上や某所の壁にけもみみタペストリーとかグッズ大量においてればそうなるか... ふたりともかわいい>_<!tgさんがくれた pic.twitter.com/chMBB6M737
— namazu (@namazu510) 2018年1月25日