Nginx反向代理子目录为Sourcegraph重写

时间:2018-07-07 12:34:30

标签: nginx url-rewriting reverse-proxy sourcegraph

我正在尝试使用反向代理添加SSL证书在域的子目录中提供自托管源图服务器。

目标是让http://example.org/source为源图服务器提供服务

我的重写和反向代理如下:

var d = new Date()+"";

我遇到的问题是,致电http://example.org/source后,我被重定向到http://example.org/sign-in?returnTo=%2F

是否可以将Sourcegraph的响应重写为正确的子目录?

此外,在哪里可以调试重写指令?我想了解所做的更改,以便更好地理解它。

-编辑:

我知道我的方法使用重写可能是错误的,并且我现在正在尝试sub_filter模块。

我使用tcpdump捕获了源图的响应,并使用wirehark进行了分析,所以我在:

  location /source {
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Scheme $scheme;

    rewrite ^/source/?(.*) /$1 break;
    proxy_pass http://localhost:8108;
  }

2 个答案:

答案 0 :(得分:1)

在此处使用重写会导致额外的处理开销,并且完全没有必要。

proxy_pass的工作方式如下:

proxy_pass到一个裸露的url,即在domain / ip / port和完整的客户端请求uri之后都没有添加到末尾并传递给代理。

添加任何内容,甚至在proxy_pass处添加一个斜线,添加的内容都会替换与该位置块的uri相匹配的客户端请求uri的一部分。

因此,如果您想丢失客户端请求的源部分,则需要如下所示:

location /source/ {
    proxy_pass http://localhost:8108/;
    .....
}

现在将以这样的方式代理请求:

example.com/source/-> localhost:8108/

example.com/source/files/file.txt-> localhost:8108/files/file.txt

需要指出的是,Nginx不仅从请求中删除了/source/,而且还替换了我的整个proxy_pass uri,尚不清楚何时只是尾随斜杠,因此为了更好地说明一下如果我们将proxy_pass更改为此:

proxy_pass http://localhost:8108/graph/;,然后按如下方式处理请求:

example.com/source/-> localhost:8108/graph/

example.com/source/files/file.txt-> localhost:8108/graph/files/file.txt

如果您想知道有人请求example.com/source有什么好处,前提是您没有将merge_slashes指令设置为off,因为Nginx会将尾随/添加到代理请求中。

答案 1 :(得分:1)

如果Nginx位于运行在端口8108上的另一个Web服务器的前面,并通过proxy_pass来提供子目录中所有内容的内容,例如/subdir,那么您可能会遇到以下问题:端口8108处的服务基于绝对URL为包含资源的HTML页面,调用其自己的API等提供服务。这些调用将省略/subdir前缀,因此nginx不会将它们路由到端口8108上的服务。

一种解决方案是使端口8108上的网络服务器提供包含基本href属性的HTML,例如

<head>
  <base href="https://example.com/subdir">
</head>

告诉客户端所有链接都相对于该路径(请参见https://www.w3schools.com/tags/att_base_href.asp

有时候,这不是一个选择-也许您只是通过外部docker映像提供了Web服务器,或者您只是看不到为什么需要篡改可完美运行的服务的原因一个独立的。仅需要更改前面的nginx的解决方案是使用Referer标头来确定请求是否由位于/subdir的资源发起。在这种情况下,您可以重写以/subdir为前缀的请求,然后将客户端重定向到该位置:

location / {
    if ($http_referer = "https://example.com/subdir/") {
        rewrite ^/(.*) https://example.com/subdir/$1 redirect;
    }

    ...
}

location /subdir/ {
    proxy_pass http://localhost:8108/;
}

或者类似这样,如果您希望使用正则表达式来省略主机名:

if ($http_referer ~ "^https?://[^/]+/subdir/") {
    rewrite ^/(.*) https://$http_host/subdir/$1 redirect;
}