Nginx 助力前端开发环境

2012-10-20 07:43

Nginx 助力前端开发环境

by 破锣锅

at 2012-10-19 23:43:25

original http://www.benben.cc/blog/?p=393

nginx [engine x]是Igor Sysoev编写的一个HTTP和反向代理服务器,另外它也可以作为邮件代理服务器。

众所周知,`Nginx` 是一个高效的HTTP和反向代理服务器,在服务器端应用甚广。而恰如今,前端开发早已不是简单的切图写页面,乃至再随便加点动画,诸如此类。前端早已是一个兼容并包,推陈出新的大前端了。

正因为如今的前端可以秀出各种新鲜应用,而这些应用背后的开发环境可能千变万化。比如一个应用背后是 `Node` 服务,而另一个应用背后是 `Apache` 或者 `Python`,尤其是开发过程中多项目并行的情况也觉非少数,这种情况下,多个应用就会发生80端口冲突的情况。为了避免冲突,最简单的方法就是每次只启动一个服务,这样做就会在开发过程中多次反复切换环境,甚是讨人之厌。

以上多个80端口的服务并存为场景之一,有时候我们为了调试线上接口或者功能还可能需要对某些HTTP请求做本地映射,比如将线上的 `http://taobao.com/jsonp` 映射到 `http://127.0.0.1/jsonp`,而且可能还需要模拟该接口超时5s的效果,此为场景二。

还有场景三,倘若笔者同时还在开发手机端 `HTML5` 的项目,就不免需要一种方式可以在上线前,通过手机真实的模拟访问效果。

Fiddler is a Web Debugging Proxy which logs all HTTP(S) traffic between your computer and the Internet. Fiddler allows you to inspect traffic, set breakpoints, and “fiddle” with incoming or outgoing data. Fiddler includes a powerful event-based scripting subsystem, and can be extended using any .NET language.

于是我们可以借助一个前端利器 – `Fiddler`(性感的小吉他), `Fiddler` 是一个优秀的 Web 调试代理,毋庸置疑,笔者的需求通过 `Fiddler` 均可以满足。

场景一:多个80端口的服务并存

`Fiddler` 的 `hosts` 功能可以带端口绑定 `host`,从而解决了场景一的问题。

场景二:线上接口映射和延时

`Fiddler` 的 `AutoResponse` 功能可以实现请求映射,而且支持设置 `latency` 参数达到延时的效果,而且支持正则,在匹配JSONP请求时候很有用(因为JSONP请求的Callback参数可能是变化的,比如YUI生成的JSONP请求)。

场景三:手机、其它非本机终端联调

`Fiddler` 有一个勾选项 `Allow remote computers to connect`,并可以指定 `listen port` 可以使得手机/其它终端通过将本机设为代理而访问本机环境,同 `hosts` 配合会很实用。

但是不幸的是 `Fiddler` 是基于 `.NET` 语言而开发,一旦离开了 `Windows` 的土壤就无法生存了。倘若你正在用 `Mac OS`/`Linux`/`Unix`,那么想用 `Fiddler` 就只能通过浏览器设置代理到虚拟机中的 `Fiddler` 才行,如此一来每天都要开一个虚拟机,既浪费资源又不优雅。

于是笔者自然就想到了 `Nginx` 这一强大的代理服务器,通过摸索,上述三个常用的场景都能很方便的通过 `Nginx` 得到解决。

场景一的 Nginx 解决方案

前端(此前端非彼前端)通过多个 `Nginx` `server` 同时监听80端口并根据 `servername` 的不同分发到不同的后端服务端口。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
    server {
        listen       80;
        server_name  a.tbcdn.cn;
 
        location / {
            proxy_set_header Host $host;
            proxy_set_header X-Real-Ip $remote_addr;
            proxy_set_header X-Forwarded-For $remote_addr;
            proxy_pass http://127.0.0.1:8080/;
        }
    }
 
    server {
        listen       80;
        server_name  triph5.m.taobao.com;
 
        location / {
            proxy_set_header Host $host;
            proxy_set_header X-Real-Ip $remote_addr;
            proxy_set_header X-Forwarded-For $remote_addr;
            proxy_pass http://127.0.0.1:9091/;
        }
    }

场景二的 Nginx 解决方案

匹配 `http://taobao.com/jsonp.php` 接口请求并映射到本地的模拟接口,参数自动附带到最后。因为 `JSONP` 是支持302跳转的,所以对于 `JSONP` 的接口可以使用 `rewrite` 方式进行映射,而 `Ajax` 请求由于无法捕获302跳转,所以 `Ajax` 接口只能通过 `proxy_pass` 的方式映射。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    server {
        listen       80;
        server_name  taobao.com www.taobao.com;
        location ~ /jsonp.php {
            rewrite ^(.*)$ http://127.0.0.1:8080/jsonp.php last;
        }
 
        location ~ /ajax.php {
            proxy_pass http://127.0.0.1:8080;
        }
 
        location / {
            proxy_pass http://www.taobao.com;
        }
    }

场景三的 Nginx 解决方案

通过 `default_server` 作为代理,手机终端通过设置网络代理为本机IP和相应的 `listen port`,从而可以访问本机的 Web 服务。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
    server {
        listen       80 default_server;
        server_name  localhost;
        resolver 8.8.8.8;
 
        location / {
            proxy_set_header Host $host;
            proxy_set_header X-Real-Ip $remote_addr;
            proxy_set_header X-Forwarded-For $remote_addr;
            proxy_pass http://$host;
        }
    }
 
    server {
        listen       80;
        server_name  triph5.m.taobao.com;
 
        location / {
            proxy_set_header Host $host;
            proxy_set_header X-Real-Ip $remote_addr;
            proxy_set_header X-Forwarded-For $remote_addr;
            proxy_pass http://127.0.0.1:9091/;
        }
    }

中立的讲,通过 `Nginx` 代理的方式实现我们的开发环境共存和调试似乎看起来没有 `Fiddler` 直观易用,但是这种方式更底层,可以灵活组合,实际应用中应当按需选择。

以上,权当抛砖引玉,欢迎提出更多的开发调试场景,共同探讨。工欲善其事,必先利其器,笔者只希望为让开发效率更高,不再把精力耗费在环境的模拟和切换上。