Nginx における ProxyPass upstream と CORS 設定

Docker の設定

以前、PredictionIODocker 化を試みたことがあります。Apache HBaseSpark など多くのコンポーネントが設定に含まれていたため、プロトタイプを稼働させるのに一週間以上もかかりました。 これらの PredictionIO のコンポーネントのほかに、PIOイベントと予測サーバーをランする二つのコンテナのリバースプロキシとして Nginx コンテナも追加しました。イベントサーバーには REST Event API があるので、HTTP POST リクエストを通じてリアルタイムのユーザーイベントをイベントサーバーに送信することができました。フロントエンドのJavascriptからイベントを収集するために NginxCORS を有効にする必要があります。以下がそのデータフローです。

概要

概要

わたしたちは、同じドメインからのリクエスト(この場合は _*.pio.com_)に対して CORS を有効にできるようにしたいと考えています。

Nginx コンテナポート 80 は PIO サービスを接続するための唯一のルートである Docker サーバーにマップされ、リクエストをホスト名に基づいて異なるアップストリームにルーティングします。 以下の二つは Nginx 設定ファイルです。

upstream.conf

1
2
3
4
5
6
7
upstream pio-event-server {
  server pio-event-server:7070;
}

upstream pio-prediction-server {
  server pio-prediction-server:8000;
}

pio-proxy.conf

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# PIO Event Server reverse proxy
server {
  listen 80;
  server_name event.pio.com;

  location / {
    # Check if the origin of th request
    set $cors '';

    if ($http_origin ~* (https?://.*\.pio\.com?(:[0-9]+)?$)) {
      set $cors 'on';
    }

    if ($request_method = OPTIONS) {
      set $cors "${cors}_options";
    }

    # Allow CORS on preflight request
    if ($cors = 'on_options') {
      add_header 'Content-Length' 0;
      add_header 'Content-Type' 'text/plain; charset=utf-8';
      add_header 'Access-Control-Allow-Origin' "$http_origin";
      add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
      add_header 'Access-Control-Allow-Headers' 'Origin, X-Requested-With, Content-Type, Accept';
      return 204;
    }

    # Proxy pass to upstream
    proxy_pass http://pio-event-server;
    proxy_redirect     off;
    proxy_set_header   Host $host;
    proxy_set_header   X-Real-IP $remote_addr;
    proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header   X-Forwarded-Host $server_name;

    # Allow CORS on other requests after returning from the upstreams
    if ($cors = 'on') {
      add_header 'Access-Control-Allow-Origin' "$http_origin";
      add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
      add_header 'Access-Control-Allow-Headers' 'Origin, X-Requested-With, Content-Type, Accept';
    }
  }
}

# PIO Prediction Server reverse proxy
server {
  listen 80;
  server_name query.pio.com;

  location / {
    # Loadbalance
    proxy_pass http://pio-prediction-server;
    proxy_redirect     off;
    proxy_set_header   Host $host;
    proxy_set_header   X-Real-IP $remote_addr;
    proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header   X-Forwarded-Host $server_name;
  }
}

proxy-pio.conf でハイライトされているように、add_header ディレクティブは proxy_passあとに記述する必要があるという点に注意が必要です。

そして最後に、Chrome Inspector を使用して CORS ヘッダーがレスポンスに追加されているかどうかを確認することができます。