在 Nginx 的 ProxyPass Upstream 設定 CORS (跨來源資源共享)
![](https://assets.matters.news/embed/ab793950-295d-4db2-9232-2f52df979fb7.jpeg)
設定 Docker
不久前嘗試 Docker 化整套 PredictionIO(PIO) 設置。當中包括 Apache HBase 和 Spark 的設定,令人非常頭痛。最後花了一個多星期才做到一個可以勉強運行的原型。除了這些 PredictionIO 組件外,我還添加了一個 Nginx 容器作為運行 PredictionIO Event(事件)和 Prediction(預測)服務器的兩個容器的 Reverse Proxy(反向代理)。事件服務器有一個 REST Event(事件) API,可以把實時的用戶事件通過 HTTP POST 請求發送到事件服務器。由於我們想從前端 Javascript 收集事件並發送到事件服務器,我們必須在 Nginx 中啟用 CORS(跨來源資源共享)。數據流如下圖所示。
![](https://assets.matters.news/embed/b24c38fe-b6ae-49c1-b8f3-da9b93eb1f5b.jpeg)
我們希望打開來自同一個域的 CORS 請求。(即本例中的* .pio.com)
Nginx 容器端口80被映射到 Docker 伺服器,它是連接兩國個 PIO 服務的唯一通路。然後根據主機名將請求路由到不同的上游。以下是兩個 Nginx 的配置文件。
upstream.conf
upstream pio-event-server { server pio-event-server:7070; } upstream pio-prediction-server { server pio-prediction-server:8000; }
pio-proxy.conf
# PIO Event Server reverse proxy server { listen 80; server_name event.pio.com; location / { # Check if the origin of th requestset $cors ''; if ($http_origin ~* (https?://.*\.pio\.com?(:[0-9]+)?$)) { set $cors 'on'; } if ($request_method = OPTIONS) { set $cors "${cors}_options"; } # Allow CORS on preflight requestif ($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 upstreamproxy_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 / { # Loadbalanceproxy_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; } }
請注意,add_header 指令必須寫在 proxy_pass 語句之後。
最後,我們可以利用 Chrome Inspector 來檢查是否在 Response header(回應標頭)中添加了 CORS 的頭欄位。