【问题标题】:how to configure nginx as a forward proxy that correctly handles POST requests?-- GETs work, but POSTs result in 404s如何将 nginx 配置为正确处理 POST 请求的转发代理?-- GET 可以工作,但 POST 会导致 404
【发布时间】:2016-03-23 20:24:54
【问题描述】:

我是 nginx 新手,并尝试按照本教程进行操作 -- https://ef.gy/using-nginx-as-a-proxy-server -- 设置转发代理,它有点工作,但仅适用于 GET 请求,而不适用于 POST。如果你有码头工人 我可以通过下面的 SETUP_NGINX 脚本提供一个可重现的测试用例。 (我已经在 Linux 上测试过脚本, 但除非您在 /Users 下找到 nginx.conf,否则卷挂载可能无法在 Mac 上运行)

该脚本使用与我上面引用的文章中相同的 nginx.conf。 POST 问题仅在我尝试向正在运行的服务进行 POST 时出现 在本地主机上。到远程服务的 POST 工作正常。但我真的很想设置 nginx 所以它 可以代理到本地运行的服务(用于测试目的。)

要重现该问题,您可以将 mongodb 设置为在 Docker 中本地运行,如下所示。 我选择 mongodb 的唯一原因是它可以快速设置为在本地运行,而且它 开箱即用地接受 POST 请求。

docker run -p 27017:27017 -p 28017:28017 --name some-mongo   -e AUTH=no -d mongo  --rest --httpinterface
# verify you can send a POST
curl   -v -d '{ "A1" : 201 }' -H "Content-Type: application/json" http://localhost:28017/local/example1
# the above command will return {"OK": true }  when NOT run via proxy.

接下来,您可以像我一样通过在 SETUP_NGINX 中复制粘贴脚本来设置代理。 在 9999 上设置代理后,您可以代理 GET 就好了。比如这个命令:

curl --proxy localhost:9999   http://httpbin.org/get   

与我们不指定 --proxy localhost:9999 时的结果几乎相同(它确实包含一个额外的标头,显示 它被代理)。

您也可以将 POST 请求代理到 httpbin.org,如下所示:

curl  --proxy localhost:9999   --data "param1=value1" http://httpbin.org/post

但是现在,假设我想将一个 POST 请求代理到我本地运行的 mongodb。
我执行的 curl 命令几乎与第一个 curl 命令相同(上图):

curl  --proxy localhost:9999   -v -d '{ "A1" : 201 }' -H "Content-Type: application/json" http://localhost:28017/local/example2

但是这次我会得到一个 404 not found。如果您删除 --proxy 开关 它会正常工作。非常感谢任何帮助!

SETUP_NGINX

cat  >nginx.conf <<'END'
user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}

http {
    include       /etc/nginx/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  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;
    keepalive_timeout  65;
    #gzip  on;

    server {
        listen       9999;
        location / {
            resolver 8.8.8.8;
            proxy_pass http://$http_host$uri$is_args$args;
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
    include /etc/nginx/conf.d/*.conf;
}
END

docker run -d  --name nginxproxy -p 9999:9999 -p 80:80    -v `pwd`/nginx.conf:/etc/nginx/nginx.conf  nginx

【问题讨论】:

    标签: post nginx proxy


    【解决方案1】:

    在我的同事 Vignesh 的帮助下,我们想出了一个关于这里发生了什么的答案。在向 mongo 发出请求时,我们使用 URL“http://localhost:28017/local/example1”作为 REST 端点。这个 URL 被传递给在它自己的 docker 容器中运行的代理服务器(nginx)。从代理服务器的角度来看,docker 容器中没有运行 mongodb 服务器,所以它放弃了,并发回 404。

    这个问题可以通过以下方式避免:

    • 保持 nginx 配置不变。
    • 将 $IP 设置为要启动 docker 的机器的 IP 地址。

    然后,当您通过代理 POST 到 mongo 时,请执行以下操作:
    curl --proxy localhost:9999 -v -d '{ "A1" : 201 }' -H "Content-Type: application/json" http://$IP:28017/local/example2

    请注意,我们在上面的 URL 中将 $IP 替换为 localhost。

    使用显式 IP 而不是 localhost 可以解决问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-05-14
      • 1970-01-01
      • 2013-01-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多