用 nginx 来反向代理 macOS 80 端口

前言

我们在做 web 服务开发时,经常会遇到需要测试的需求,需要完全模拟线上的环境,如 80 端口。但局限于 macOS 限制非 root 用户不能监听 1024 以下的端口(Windows 用户表示很淡定 😎),网上多数教程是使用 pfctl 做端口转发。这个方法重启后还得重新执行命令,有些麻烦,而且没有用 nginx 转发灵活性高,于是便有了这篇文章。

安装 nginx

当然是用 brew 了:

$ brew install nginx

# ...
# blablabla...

Docroot is: /usr/local/var/www

The default port has been set in /usr/local/etc/nginx/nginx.conf to 8080 so that  
nginx can run without sudo.

nginx will load all files in /usr/local/etc/nginx/servers/.

To have launchd start nginx now and restart at login:  
  brew services start nginx
Or, if you don't want/need a background service you can just run:  
  nginx
==> Summary
🍺  /usr/local/Cellar/nginx/1.12.0_1: 23 files, 1MB

从最后的安装信息中可知:

  • 放 html 的地方在:/usr/local/var/www
  • nginx.conf 在:/usr/local/etc/nginx/nginx.conf
  • 多服务 conf 文件可以放在:/usr/local/etc/nginx/servers/
  • 运行后台服务,并保持自启动:brew services start nginx
Bouns
  • 服务启动可以用 sudo 前缀,这样便可以代理 80 端口了;
  • 关闭服务:brew services stop nginx
  • 更新 nginx:brew upgrade nginx

配置 80 端口代理

我这里只有 8888 端口的服务,因此只修改了 nginx.conf,配置如下:

user  nobody;  
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

# pid        logs/nginx.pid;


events {  
    worker_connections  1024;
    accept_mutex        on;
    multi_accept        on;
    # use                 epoll;
}


http {  
    include       mime.types;
    default_type  application/octet-stream;

    # log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                   '$status $body_bytes_sent "$http_referer" '
    #                   '"$http_user_agent" "$http_x_forwarded_for"';

    # access_log  logs/access.log  main;

    sendfile        on;
    tcp_nopush      on;
    tcp_nodelay     on;

    keepalive_timeout   65;
    types_hash_max_size 2048;

    # gzip
    gzip on;
    gzip_vary           on;

    gzip_comp_level     6;
    gzip_buffers        16 8k;

    gzip_min_length     1k;
    gzip_proxied        any;
    gzip_disable        "msie6";

    gzip_http_version   1.0;

    gzip_types  text/plain text/css aplication/x-javascript text/javascript application/javascript text/xml application/xml application/xml+rss image/svg+xml application/vnd.ms-fontobject application/x-font-ttf application/pdf;

    # http_proxy
    client_max_body_size        128m;
    client_body_buffer_size     128k;
    proxy_connect_timeout       256;
    proxy_send_timeout          120;
    proxy_read_timeout          256;
    proxy_buffer_size           4k;
    proxy_buffers               4 32k;
    proxy_busy_buffers_size     64k;

    map $http_upgrade $connection_upgrade {
        default upgrade;
        ''      close;
    }

    server {
        listen       80;
        server_name  localhost;
        charset      utf-8;

        # access_log  logs/host.access.log  main;

        location / {
            proxy_set_header        Host $http_host;
            proxy_set_header        X-Real-IP $remote_addr;
            proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;

            proxy_pass      http://127.0.0.1:8888;
            proxy_redirect  off;
        }

        #error_page  404              /404.html;

        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }

    include servers/*;
}

(log 对于本地开发没什么用,我就都注释了。)

不过,要注意两点:

  • pid logs/nginx.pid; 不能启用;
  • use epoll; 不能启用。

否则无法访问 http://localhost,原因:

  • pid 的问题是若没有文件 /usr/local/Cellar/nginx/1.12.0/logs/nginx.pid,nginx 无法启动;
  • epoll 是 Linux 内核系统的事件通知程序,用来实现异步网络 IO,nginx 就是用它来实现高性能的。当然,macOS 没有这个功能 🙃。

引用

这篇文章没有引用,因为以上内容都是我编的。

正在加载 Disqus 评论组件...