以下是本日 nginx 的小記錄:

問題

最近開始要做一個新的 web app, 狀態如下:

  • 一個 rails server, serve API (可能是mock api)
  • 一個用 yeoman generate 出來的 web app, 所以可以用 grunt serve 就在 localhost:9000 找到 app
  • 這兩個是分開的 project

我遇到的問題是, 在 local 開發的時候,API 是從 localhost:3000 來的,但 web app 卻是從 localhost:9000, 於是就 cross domain 惹。可是我

  • 不想把 server 的 CORS 打開,
  • 又想要讓 yeoman 幫我 serve web app
  • 還想要把 rails server 開在 development mode, 這樣如果要改來改去比較快

解法

總之我找到一個解法,大意就是用 nginx reverse proxy:

  • 選定一個 port, 好比說 7000
  • 叫 nginx 把 localhost:7000 proxy 到 localhost:9000, 所以說 localhost:7000/hello/world 就會指到 localhost:9000/hello/world
  • 再叫 nginx 把 localhost:7000/api proxy 到 localhost:3000, 所以說 localhost:7000/api/users/login 就會指到 localhost:3000/users/login

如此這般,以 login api 為例,在 webapp 就可以發 ajax 叫 /api/users/login 然後就不會 corss domain 惹。

下面是我的 nginx 設定:

    # map localhost:7000 to localhost:9000
    # map localhost:7000/api to localhost:3000
    # to solve cross-domain issue on local dev
    server {
      listen 7000;
      server_name localhost;

      location / {
        proxy_pass http://localhost:9000;
      }

      location ~* ^/api/(.*) {
        rewrite ^/api/(.*) /$1 break;
        proxy_pass http://localhost:3000;
      }
    }  

其中有一個 rewrite 的 directive, 作用是把 url 的 /api 去掉。

心得與感想

我覺得 nginx 設定起來似乎比 apache 簡單明暸阿,doc 和語法都比較友善喔!

還有

其實類似的問題做法,應該也可以用來解決 web app deployment 的問題:

  • server 可能是一個 rails/django/php 等等的 project
  • front end 是 web app
  • 不想開 CORS
  • 希望把 web app deploy 到 domain root (例如說 domain.com 而不是 domain.com/path)

TODO: SEO

在上面的做法裡面,理論上可以根據不同的 user-agent, proxy 到不同的地方
這樣應該就可以把 SEO 相關的東西獨立出來。
就是說,如果 user-agent 是 bot 的話,就叫它去找 SEO 的 server