LoginSignup
0
0

More than 1 year has passed since last update.

nginxでクライアントがリクエストした元のURLを取得する

Last updated at Posted at 2022-09-25

概要

Webサーバのフロントエンドとしてnginxを使った際に、バックエンドのWebアプリでもクライアントがリクエストした元のURLの情報(プロトコル、ホスト名、パス)を取得する方法を紹介する。

環境情報

構成

  • リバースプロキシ : nginx
    • ホスト名 : hogehoge.com
    • プロトコル : https
    • ポート : 443
  • Webアプリ
    • ホスト名 : 192.168.1.4
    • プロトコル : http
    • ポート : 5000

nginx.confの設定

以下はserver部分のみ抜粋したもの。

nginx.conf
    server {
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        listen 443 ssl;
        listen  [::]:443;
        # (中略。サーバ証明書のファイルパス等の指定が実際は必要)

        location / {
            proxy_pass http://192.168.1.4:5000/;
        }
    }

動作例

nginxに届いた以下のクライアントからのリクエスト
https://hogehoge.com/some-path?value=1
を、次のURLに変換して内部のWebアプリにリクエストする。
http://192.168.1.4:5000/some-path?value=1

やりたいこと

Webアプリでクライアントがリクエストした元のURLを取得したい。
上に示した「動作例」では以下が取得したいものに相当。
https://hogehoge.com/some-path?value=1

解決策

バックエンドにリバプロする際、ヘッダーにクライアントがリクエストした元のURLの情報を付加可能。
具体的にはnginx.conf のserverまたはlocationのスコープに、次のproxy_set_headerディレクティブを以下のように追加する。

nginx.conf
        proxy_set_header X-Forwarded-For   $host;        # ホスト名
        proxy_set_header X-Forwarded-Proto $scheme;      # プロトコル
        proxy_set_header Request-Path      $request_uri; # リクエストURLのパス部分

先の例で、クライアントがhttps://hogehoge.com/some-path?value=1をリクエストしている場合、nginxの変数には以下のような値が格納される。

変数
$host hogehoge.com
$scheme https
$request_uri /some-path?value=1

補足

  • proxy_set_headerの第一引数にはヘッダーのフィールド名を指定する。こちらは用途別に推奨されるフィールド名があるようだが、筆者はこの辺に精通していないので適切な名前になっていない可能性がありご注意を。
  • $host(=hogehoge.com)に関して。筆者が試した環境では$remote_addr$proxy_add_x_forwarded_forも同様にhogehoge.comが格納されていた。

Webアプリで実際に取得してみる

PythonのFlaskを使うと、例えば次のようにFlaskのRequestクラスから取得できる。

from flask import Flask, request
app = Flask(__name__)

@app.route("/some-path")
def some_path():

  # 元のURLの情報を取得
  host = request.headers.getlist("X-Forwarded-For")      # $hostを取得
  scheme = request.headers.getlist("X-Forwarded-Proto")  # $schemeを取得
  request_uri = request.headers.getlist("Request-Path")  # $request_uriを取得

  return ""

if __name__ == "__main__":
  app.run(host='0.0.0.0')

どういう時に使える?

Webサーバでユーザ認証する場合などに、クライアントからのリクエストをAuth0等の外部サイトに誘導する場合がある。認証が済んだ後にもともとリクエストしたページに直でリダイレクトさせたい場合、WebサーバでそのURLを覚えておく必要がある。本記事の内容はこのようなケースで活用できるはず。

参考情報

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0