【问题标题】:Proxy_pass ignoring portProxy_pass 忽略端口
【发布时间】:2018-11-23 16:26:36
【问题描述】:

我有一个运行 NGINX 的 CentOS 服务器来监听 80,还有一个 DB 为 8080 上的应用程序提供服务器服务。我希望能够输入

http://example.com/dev/abc

并让它实际访问

http://example.com:8080/apex/abchttp://localhost:8080/apex/abc

我用过这个位置配置

location /dev {
       proxy_pass http://example.com:8080/apex;
    }

但是,当我尝试时,显示的网址是

http://example.com/apex/apex

找不到页面,日志显示:

2018/06/14 12:51:33 [error] 7209#0: *2067 open()
"/usr/share/nginx/html/apex/apex" failed (2: No such file or directory), 
client: 124.157.113.187, server: _, request: "GET /apex/apex HTTP/1.1", host: "example.com"

好像发生了两件奇怪的事情

1) 尽管使用了 proxy_pass,但使用的是端口 80 而不是 8080

2)为什么apex是两次“/apex/apex/”

请帮忙:)

从配置文件中添加整个服务器块:

server {
    listen       80 default_server;
    listen       [::]:80 default_server;
    server_name  example.com;
    root         /usr/share/nginx/html;

    # Load configuration files for the default server block.
    include /etc/nginx/default.d/*.conf;

   location /dev {
       proxy_pass http://example.com:8080/apex;
    }

    error_page 404 /404.html;
        location = /40x.html {
    }

    error_page 500 502 503 504 /50x.html;
        location = /50x.html {
    }
}

更新 - 更多关于可能有帮助的应用的信息

该应用是 Oracle Application Express (APEX),它侦听端口 8080。 URL 的工作原理如下:

HTTP://example.com:8080/apex/f?p=[APP]:[Page]:[Session] etc

其中[APP]、[Page]和[Session]都是对应的数字

开发环境url其实是:

http://example.com:8080/apex/f?p=4550

这是默认设置,所以如果我尝试http://example.com:8080/apex/,它默认为http://example.com:8080/apex/f?p=4550 并带您进入登录页面

应用编号之后的所有内容都不会改变,所以我想用 /dev/ http://example.com:8080/apex/f?p=4550:1 -> http://example.com/dev/:1 替换它

了解了它的工作原理后,我打算设置三个 proxy_pass

example.com/dev -> http://example.com:8080/apex/f?p=4550

example.com/desktop -> http://example.com:8080/apex/f?p=1001

example.com/mobile -> http://example.com:8080/apex/f?p=201

唯一改变的是应用程序编号。

重写对所有三个都工作正常,但我不希望重写在 URL 中可见

以下是重写:

   location ~ /dev {
       rewrite ^/dev(.*) http://smallblockpro.com:8080/apex$1 last;
    }
   location ~ /desktop/ {
       rewrite ^/desktop/(.*) http://smallblockpro.com:8080/apex/f?p=1001:$1 last;
    }

    location ~ /desktop {
       rewrite ^/desktop(.*) http://smallblockpro.com:8080/apex/f?p=1001:$1 last;
    }

    location ~ /mobile/ {
       rewrite ^/mobile/(.*) http://smallblockpro.com:8080/apex/f?p=201:$1 last;
    }

    location ~ /mobile {
       rewrite ^/mobile(.*) http://smallblockpro.com:8080/apex/f?p=201:$1 last;
    }

【问题讨论】:

  • 使用听 80; server_name example.com;location /dev {proxy_pass example.com:8080/apec;}
  • 谢谢,但没有修复它我没有 server_name 部分,它仍然删除 :8080 并添加一个额外的 apex/即 example.com/apex/apex 我将放置整个服务器阻止以防其他地方出现问题。
  • 嗯,这令人失望,花了几个小时,尝试了所有建议,没有得到解决,但仍然失去了赏金。然后看起来每个尝试过的人都对我的问题投了反对票,没有给出任何理由。甚至有人用它来尝试工作。将赏金分配给克里斯,因为他尽最大努力提供帮助。
  • @AndrewT,当您没有规范时,您无法解决规范的问题。您的问题需要 nginx(编写配置)和 Oracle ApEx(了解其工作原理并提出 nginx 规范)的高级知识。您无法获得解决方案并被否决,这并不奇怪,TBH,因为您要求的是 nginx 配置,但无法在伪代码中解释此类配置必须考虑的操作。
  • @cnst 如果我有上述知识,我不会问这个问题。我正在尝试做的事情我认为使用 NGINX 或 apache 将 url 映射到用于数百万互联网应用程序的 Apex 并不罕见。我希望以前做过这件事的人可以提供帮助,我没想到有人会根据我的设计规范来构建东西。我做了很多更新,并每天多次尝试所有建议来尽我所能,因为是的,我自己没有知识去做。当您解决部分问题在应用程序端时,我什至赞成您的评论。我尽力了

标签: nginx url-rewriting oracle-apex nginx-location ngx-http-rewrite-module


【解决方案1】:
location ~ /desktop/ {
    rewrite ^/desktop/(.*) http://smallblockpro.com:8080/apex/f?p=1001:$1 last;
 }

您向用户显示:8080 端口号的原因是因为您在重写指令中使用绝对URL,这导致NGINX 直接向用户生成301 Moved 响应——您假设它是' 仍然会经过proxy_pass 这样的重写是不正确的,请参阅http://nginx.org/r/rewrite

如果替换字符串以“http://”、“https://”或“$scheme”开头,则处理停止并将重定向返回给客户端。

如果您只想在 Oracle Application Express (APEX) 的前端创建 /desktop/$1 和后端 /apex/f?p=1001:$1 之间的映射,那么最好的方法是使用以下代码你的 nginx 前端服务器:

location /desktop/ {
    rewrite ^/desktop/?(.*)$ /apex/f?p=1001:$1 break;
    return 400;
    proxy_pass http://smallblockpro.com:8080;
}

我建议为/dev//mobile//desktop/ 中的每一个复制粘贴它;另外,我不建议根据ServerFault's nginx-reverse-proxy-url-rewritehow-to-remove-the-path-with-an-nginx-proxy-pass 保留无斜杠版本,因为在您使用上面建议的代码的情况下,nginx 已经处理了没有斜杠的请求。

【讨论】:

  • 进度但不工作,它显示了一个应该工作的网址smallblockpro.com/foo/f?p=1001:1:::::: 但它必须再次循环并尝试找到页面'F',这意味着它必须抓住' f' 从 f?p 映射到无效的 smallblockpro.com/foo/f?p=1001:f。进展是 8080 和顶点已经被映射。
  • @AndrewT 那么您是否尝试过将f 放入重写中?您可以将f? 用作可选的f,例如rewrite ^/desktop/?f?(.*)$ /apex/f?p=1001:$1 break;
  • “?” as optional 很有帮助,但它不仅仅是 'f' 是可选的并且应该匹配。我试过这个: location /foo/ { rewrite ^/foo/?(f?p=1001:)?(.*)$ /apex/f?p=1001:$1 break; #rewrite ^/foo/?(.*)$ /apex/f?p=1001:$1 break;返回 400; proxy_pass smallblockpro.com:8080;但是得到错误太多重定向和url显示smallblockpro.com/foo/f?p=1001:1:::::: not smallblockpro.com/foo/1:::::
【解决方案2】:

这是我在我们的 ORDS / SDW (sqldev-web) 开发服务器上使用的复制粘贴。

这是一个用于 REST 端的 ORDS 的基本示例。

访问权限是:

 https://xyz.oraclecorp.com/sdw/klrice/metadata-catalog/

然后它被代理到:

 https://xyz.oraclecorp.com:8083/ords/klrice/metadata-catalog/

有了这个配置。除了不重写为绝对 URI,因为这将执行完整的浏览器重定向,而不是仅重写代理传递的 url。

   location /sdw/ {
       rewrite /sdw/(.*) /ords/$1 break;
       proxy_pass https://xyz.oraclecorp.com:8083/ords/;
       proxy_redirect    off;
       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;

    }

你将面临的问题是这样的

   rewrite ^/desktop/(.*) http://smallblockpro.com:8080/apex/f?p=1001:$1 last;

APEX 将看到并写入链接/重定向/包含 (javascript/css/...) 作为 .../apex/XYZ,它将访问 nginx 服务器并且不知道如何处理 /apex/

这是基于我上述设置的示例。请注意,我对 /sdw/ 的请求变成了对 /ords/ 的位置重定向

 wget  -S https://xyz.oraclecorp.com/sdw/
--2018-06-21 17:10:28--  https://xyz.oraclecorp.com/sdw/
Resolving xyz.oraclecorp.com... 123.456.789.123
Connecting to xyz.oraclecorp.com|123.456.789.123|:443... connected.
HTTP request sent, awaiting response... 
  HTTP/1.1 302 Found
  Server: nginx/1.12.1


  Location: https://xyz.oraclecorp.com/ords/f?p=4550:1:375440000433:::::
Location: https://xyz.oraclecorp.com/ords/f?p=4550:1:375440000433::::: [following]

因此,最简单的做法是将 ords 部署 ( /apex/ ) 与重写/重定向的内容相匹配,并使用代理传递来内部化 :8080 内容。所以

location ~ /desktop/ {
       rewrite ^/desktop/(.*) http://smallblockpro.com/apex/f?p=1001:$1 last;
    }
location ~ /apex/ {
       proxy_pass http://smallblockpro.com:8080/apex/;
       proxy_redirect    off;
       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;
    }

此选项将使您的用户有一个很好的 /desktop/ 入口点,但随后会为应用程序本身重定向 /apex/。

ORDS url-mappings.xml 有另一个选项来保留 /desktop/,也可以像这样将映射添加到 ords,以便它知道 /desktop/。然后 nginx 可以为每个入口 url 做相同的代理传递。

url-mapping.xml 文件内容

 <pool-config xmlns="http://xmlns.oracle.com/apex/pool-config">
    <pool name="mypool" base-path="/desktop" />
   </pool-config>

然后在 nginx 中

location ~ /desktop/ {
       proxy_pass http://smallblockpro.com:8080/desktop/;
       proxy_redirect    off;
       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;
    }

【讨论】:

  • 对不起,克里斯,从我所看到的你正在做一个端口和 uri 变化如此相似的情况来看,我并没有真正理解这一点。为什么 /ords/ 在 rewrite 和 proxy_pass 中与所有其他示例不同。
  • 我看到您已添加到问题中。顶点的好 URL 是目标
  • 是的,但不是在顶部,只是想隐藏:8080/apex/f?p=1001:页面/会话等将随之而来,所以smallblockpro.com:8080/apex/f?p=1001:1:132886511937::::: 看起来像smallblockpro.com/desktop/1:132886511937 ::::: /desktop/ 将始终替换为后面的 ':8080/apex/f?p=1001:'
  • 尝试了你的第一个选项: location ~ /desktop/ { rewrite ^/desktop/(.*) smallblockpro.com/apex/f?p=1001:$1 last; } 位置 ~ /apex/ { proxy_pass smallblockpro.com:8080/apex;代理重定向关闭; proxy_set_header 主机 $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;这不保留网址(我想你是这么说的)我已经在我的原始问题中进行了重写。
  • 现在试试 mypool 选项
【解决方案3】:

在您进一步阅读之前,请阅读下面的 SO 线程,该线程解释了额外的 /apex/

Nginx proxy_pass only works partially

你的配置中有两个问题

  1. 您需要将正确的 URL 传递给后端服务
  2. 您需要确保处理所有重定向并正确替换网址

以下是我认为应该适合你的配置

server {
    listen       80 default_server;
    listen       [::]:80 default_server;
    server_name  example.com;
    root         /usr/share/nginx/html;

    # Load configuration files for the default server block.
    include /etc/nginx/default.d/*.conf;

   location /dev/ {
       proxy_pass http://example.com:8080/apex/;
       proxy_redirect http://example.com:8080/apex/ $scheme://$host/dev/;
    }

    error_page 404 /404.html;
        location = /40x.html {
    }

    error_page 500 502 503 504 /50x.html;
        location = /50x.html {
    }
}

【讨论】:

  • 代码示例不起作用。当我尝试example.com/dev “没有这样的文件或目录失败”时,当我尝试example.com/dev 时说没有定义解析器...
  • 会做你建议的阅读以及我以前从未听说过的proxy_redirect,然后再摆弄一下。
  • 现在试试
  • 仍然在 url 中的错误端口上寻找 /apex/apex 还尝试了 curl 命令:curl -i example.com/foo HTTP/1.1 301 永久移动服务器:nginx/1.12.2 日期:6 月 19 日星期二2018 00:40:48 GMT Content-Type: text/html Content-Length: 185 Location: example.com/foo Connection: keep-alive 301 永久移动

    301 永久移动


    nginx/1.12.2
猜你喜欢
  • 1970-01-01
  • 2021-02-24
  • 1970-01-01
  • 2016-01-12
  • 1970-01-01
  • 2019-02-11
  • 2019-04-01
  • 2013-07-20
  • 2013-10-25
相关资源
最近更新 更多