OpenResty Edge でブラウザの言語に基づいてリダイレクトするには、リクエスト URI / クライアントが送信する Accept-Language リクエストヘッダーの両方にマッチするページルールを作成し、対応する言語パス(例:/fr/)へのリダイレクトアクションを付与します。これをトップルールとしてマークして最初に実行させ、さらに他のすべての言語を /en/ へ振り分けるフォールバックルールを追加します。設定はサーバーのリロード・再起動・バイナリのアップグレードなしで各ゲートウェイノードに配信されます。

以下では、OpenResty Edge の Admin コンソールでこの 2 つのルールを順に作成し、curl とブラウザで検証します。より簡単なルールをお探しの場合は、まず301 ページルールで HTTP を HTTPS へリダイレクトする方法をご覧ください。

図:OpenResty Edge が Accept-Language ヘッダーに基づいて訪問者を対応する言語の URI へリダイレクト

パスごとに多言語を配信するオリジンサーバー

異なるパスで異なる言語を表示するオリジンサーバーがあるとします。例えば、これは /en/ パスです。

$ curl 'http://test-edge.com/en/'
Hello, world!

ここでは英語で「Hello, world!」と表示されています。

/fr/ パスにはフランス語版もあります。

$ curl 'http://test-edge.com/fr/'
Bonjour, le monde!

ここではフランス語で表示されています。

Accept-Language でリダイレクトするページルールの作成

今日の目標は、クライアントがルートパス / にアクセスした際に、その言語設定に基づいて特定の言語パスに自動的にリダイレクトすることです。クライアントが送信する Accept-Language リクエストヘッダーを使用します。

OpenResty Edge が Accept-Language ヘッダーに基づいてルートパスを対応する言語パスへリダイレクト

いつものように、OpenResty Edge の Admin Web コンソールにアクセスしましょう。これはサンプルデプロイメントのコンソールです。各ユーザーには独自のローカルデプロイメントがあります。

今回も test-edge.com ドメインのサンプルアプリケーションを使用します。

このアプリケーションに入ります。

OpenResty Edge Admin コンソールで test-edge.com アプリケーションを開く

すでにアップストリームが定義されています。

アプリケーションに定義済みの my_backend アップストリーム

この my backend アップストリームには 1 つのバックエンドサーバーしかありません。これは動画の冒頭で使用したオリジンサーバーです。

オリジンサーバーを指す単一のバックエンドを持つ my_backend アップストリーム

また、すでに定義済みのページルールもあります。

アプリケーションの既存のページルール一覧

このページルールは、先ほど見た my backend アップストリームへのリバースプロキシを設定しています。

my_backend アップストリームへのリバースプロキシとして設定された既存のページルール

新しいページルールを作成しましょう。

OpenResty Edge コンソールで新しいページルールを作成

URI / をチェックするルール条件を有効にします。

リクエスト URI にマッチするルール条件を有効化

このドロップダウンボックスには、選択可能なすべての変数が表示されています。

ページルール条件で選択できる変数の一覧

変数 URI を選択します。

条件に URI 変数を選択

演算子には文字列等号を選択します。

URI 条件に文字列等号演算子を選択

URI 条件に文字列等号演算子が選択された状態

値として / を入力し、ルートパスのみにマッチするようにします。

ルートパスのみにマッチするよう値 / を入力

2 つ目の条件は言語をチェックするためのものです。

リクエストの言語をチェックする 2 つ目の条件を追加

言語条件の変数を選択

変数として Request header を選択します。

言語条件の変数として Request header を選択

リクエストヘッダー名として Accept-Language を入力します。

マッチさせるリクエストヘッダー名 Accept-Language を入力

演算子については、

Accept-Language 条件の演算子リストを開く

「プレフィックス」を選択します。

Accept-Language ヘッダーにプレフィックス演算子を選択

これは、複数の言語が指定されている場合、最初の言語のみを考慮することを意味します。

マッチング値の正規表現タイプとして Regex を選択します。

Accept-Language の値に Regex 正規表現マッチタイプを選択

Accept-Language の値に Regex マッチタイプが選択された状態

正規表現の値として fr\b を入力します。

fr や fr-CA などのフランス語タグにマッチする正規表現 fr\b を入力

\b は単語の境界にマッチすることを意味します。これにより、frfr-CA の両方がマッチします。

ここでは、大文字小文字を区別しないマッチングを行うために「大文字小文字を無視」にチェックを入れます。

大文字小文字を無視して Accept-Language をマッチさせるオプションを有効化

これで、AND で接続された2つの条件ができました。つまり、両方の条件を同時に満たす必要があり、その場合にのみ以下のアクションが実行されます。条件の記述は完了しました。

次に、新しいアクションを追加します。

ページルールに新しいアクションを追加

「リダイレクト」アクションを検索します。

アクションタイプとして「リダイレクト」を選択します。

リダイレクトアクションタイプを選択

次に、リダイレクト先の URI を設定します

リダイレクトアクションのターゲット URI を設定

「カスタム」を選択します。URI を自分で入力します。

リダイレクトのカスタムターゲット URI を選択

/fr/ と入力します。

フランス語訪問者のリダイレクト先として /fr/ を入力

他のフィールドはそのままにしておきます。

残りのリダイレクトフィールドはデフォルトのまま

このルールにマッチした場合、残りのすべてのページルールをスキップします。

マッチ時に後続ルールをスキップを有効化

このルールが他のルールよりも先に実行されるようにする必要があります。これをトップルールとしてマークします。トップルールは通常のルールではありません。

通常のルールより先に実行されるようルールをトップルールとしてマーク

このルールを保存します。

フランス語 Accept-Language リダイレクトルールを保存

新しく追加されたページルールが実際にルールリストの最上部にあることが確認できます。

新しいリダイレクトルールがページルール一覧の最上部に表示

以前のプロキシルールの前に表示されています。

いつものように、このルールを有効にするにはリリースする必要があります。

新しい設定をリリースしてページルールを配信

新しい設定を各ゲートウェイクラスターへリリース

リリースします!

設定リリースが全ゲートウェイクラスターに同期

同期が完了したことが確認できます。

新しいページルールが全ゲートウェイクラスターとサーバーへプッシュ

これで、新しいページルールがすべてのゲートウェイクラスターとサーバーにプッシュされました。

設定の変更にはサーバーのリロード、再起動、バイナリのアップグレードは必要ありません。そのため、非常に効率的でスケーラブルです。

OpenResty Edge がリロード・再起動・バイナリのアップグレードなしで設定をゲートウェイノードへ同期

curl でフランス語の Accept-Language リダイレクトをテスト

ターミナルで、curl を使用して HTTP リクエストを送信できます。

curl -I -H 'Accept-Language: fr-CA, fr, en' http://test-edge.com/

ここでは3つの言語を指定しています:fr-CA、fr、en。したがって、このリクエストでは、フランス語が英語よりも優先されます。

Accept-Language: fr-CA, fr, en を付けた curl リクエストでリダイレクトをテスト

このコマンドを実行します。

ここで /fr/ にリダイレクトされていることに注目してください。

フランス語 Accept-Language ヘッダーに対して /fr/ へリダイレクトするレスポンス

curl コマンドにリダイレクトを自動的に追跡させることができます。

curl -L -H 'Accept-Language: fr, en' http://test-edge.com/

ここでは -L オプションを使用しています。

curl -L で言語リダイレクトを自動的に追跡

このコマンドを実行します。

フランス語のテキストが返されていることが確認できます。

リダイレクトを追跡した後に返されるフランス語ページの内容

他の言語を英語へ振り分けるフォールバックページルールの追加

次に、クライアントが他の言語のリクエストヘッダーを送信した場合に英語ページにリダイレクトする汎用的なページルールを追加します。

英語フォールバック用に 2 つ目のページルールを作成

新しいページルールを作成します。

フォールバックルールに URI 条件を有効化

URI / をチェックするルール条件を有効にします。

フォールバック条件に URI 変数を選択

フォールバック条件に URI 変数が選択された状態

URI を選択します。

フォールバック条件に文字列等号演算子を選択

文字列等号を選択します。

フォールバック条件の URI 値を入力する準備

フォールバックルールでルートパスにマッチするよう / を入力

前回と同様に値 / を入力します。

言語をチェックせずルート URI のみにマッチするフォールバック条件

条件の記述が完了しました。今回はリクエストヘッダーをチェックする必要はありません。

前回と同様に、新しいリダイレクトアクションを追加します。

フォールバックルールにリダイレクトアクションを追加

フォールバックルールのリダイレクトアクションタイプを選択

フォールバックルールのリダイレクト先を設定

フォールバックリダイレクトのカスタムターゲット URI を選択し /en/ を入力

今回は、ターゲット URI として /en/ を入力します。

フォールバックルールにマッチ時の後続ルールスキップを有効化

このルールにマッチした場合、残りのすべてのページルールをスキップします。

フォールバックルールも他の通常ルールより先に実行させる

このルールが他の「通常のルール」よりも先に実行されるようにする必要があります。

英語フォールバックリダイレクトルールを保存

このルールを保存します。

フォールバックルールがプロキシルールの前、フランス語ルールの後に配置

新しく追加されたページルールがプロキシルールの前にあり、前回追加したフランス語ルールの後にあることが確認できます。

新しい設定を再度リリース

新しい設定のリリースをもう一度行います。

更新した設定をリリース

設定を再び全ゲートウェイクラスターへリリース

再度リリースします!

設定の同期が再び完了

同期が再び完了しました。

ブラウザで英語フォールバックのリダイレクトをテスト

今回はブラウザを使用して / パスをテストします。ブラウザの言語設定は英語です。

ここでは英語のテキスト「Hello, world」が返されていることが確認できます。

ブラウザが英語ページを表示し、アドレスバーの URL が /en/ に書き換わる

アドレスバーから、URI が /en/ に変更されていることも確認できます。

よくある質問

OpenResty Edge はどのように訪問者の言語を判定しますか?

クライアントがリクエストごとに送信する Accept-Language リクエストヘッダーを読み取ります。ページルールはプレフィックス演算子と正規表現(例:fr\b)でこのヘッダーをマッチさせるため、frfr-CA のような地域バリアントの両方がヒットします。Accept-Language を設定するクライアントであれば、curl を含めて同じリダイレクトがトリガーされます。

nginx.conf を編集せずにブラウザの言語でリダイレクトできますか?

できます。ルール全体は OpenResty Edge の Admin コンソール内で構築します——URI 条件、Accept-Language ヘッダー条件、そしてリダイレクトアクションです。設定を一度リリースすれば、ルールはサーバーのリロード・再起動・バイナリのアップグレードなしで全ゲートウェイクラスターに配信されます。

デフォルト言語のフォールバックはどう設定しますか?

ルート URI / のみにマッチし、Accept-Language をチェックせず、/en/ へリダイレクトするページルールをもう 1 つ追加します。言語固有のルールをその上に並べ、フォールバックルールを最後に実行させます。本チュートリアルではフランス語ルールがフランス語クライアントを先にマッチし、その他すべての言語は英語ページに落ちます。

言語リダイレクトをトップルールにするのはなぜですか?

トップルールは常に通常のルールより先に実行されるため、言語リダイレクトはルートパスを配信するリバースプロキシルールの前に評価されます。「マッチ時に後続ルールをスキップ」と組み合わせることで、他のどのルールが応答するよりも前に、クライアントを正しい言語パスへ確実に送れます。

クライアントが複数の言語を同時に送信した場合はどうなりますか?

Accept-Language ヘッダーは fr-CA, fr, en のように複数の言語を列挙できます。プレフィックスマッチを使うため、最初の(最も優先度の高い)言語のみが考慮されます。この例ではフランス語が英語より優先されるため、リクエストは /fr/ へリダイレクトされます。

著者について

章亦春(Zhang Yichun)は、オープンソースの OpenResty® プロジェクトの創始者であり、OpenResty Inc. の CEO および創業者です。

章亦春(GitHub ID: agentzh)は中国江蘇省生まれで、現在は米国ベイエリアに在住しております。彼は中国における初期のオープンソース技術と文化の提唱者およびリーダーの一人であり、Cloudflare、Yahoo!、Alibaba など、国際的に有名なハイテク企業に勤務した経験があります。「エッジコンピューティング」、「動的トレーシング」、「機械プログラミング」 の先駆者であり、22 年以上のプログラミング経験と 16 年以上のオープンソース経験を持っております。世界中で 4000 万以上のドメイン名を持つユーザーを抱えるオープンソースプロジェクトのリーダーとして、彼は OpenResty® オープンソースプロジェクトをベースに、米国シリコンバレーの中心部にハイテク企業 OpenResty Inc. を設立いたしました。同社の主力製品である OpenResty XRay動的トレーシング技術を利用した非侵入型の障害分析・排除ツール)と OpenResty Edge(マイクロサービスおよび分散トラフィックに最適化された多機能ゲートウェイソフトウェア)は、世界中の多くの上場企業および大企業から高い評価を得ております。OpenResty 以外にも、章亦春は Linux カーネル、Nginx、LuaJITGDBSystemTapLLVM、Perl など、複数のオープンソースプロジェクトに累計 100 万行以上のコードを寄与し、60 以上のオープンソースソフトウェアライブラリを執筆しております。

翻訳

英文版の原文と日本語訳版(本文)をご用意しております。読者の皆様による他の言語への翻訳版も歓迎いたします。全文翻訳で省略がなければ、採用を検討させていただきます。心より感謝申し上げます!