/ Nginx

#Nginx proxy_pass反向代理笔记

关于proxy_pass模块

http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass

proxy_pass模块通常用来做反向代理,既将客户端发送的请求转发到目标服务器。

语法

Syntax:    proxy_pass URL;
Default:    —
Context:    location, if in location, limit_except

Sets the protocol and address of a proxied server and an optional URI to which a location should be mapped. As a protocol, “http” or “https” can be specified. The address can be specified as a domain name or IP address, and an optional port:

proxy_pass http://localhost:8000/uri/;

or as a UNIX-domain socket path specified after the word “unix” and enclosed in colons:

proxy_pass http://unix:/tmp/backend.socket:/uri/;

关于域名

If a domain name resolves to several addresses, all of them will be used in a round-robin fashion. In addition, an address can be specified as a server group.
Parameter value can contain variables. In this case, if an address is specified as a domain name, the name is searched among the described server groups, and, if not found, is determined using a resolver.

proxy_pass中的域名会被解析,如果解析为一组服务器,则会轮流访问。

关于请求URI如何传递给服务器

A request URI is passed to the server as follows:

1). 如果proxy_pass指令中包含URI

If the proxy_pass directive is specified with a URI, then when a request is passed to the server, the part of a normalized request URI matching the location is replaced by a URI specified in the directive:

location /name/ {
    proxy_pass http://127.0.0.1/remote/;
}

那么,进行以下处理:

  • i). 标准化请求的URI
  • ii). 将标准化后的URI中与location相同的部分移除
  • iii). 剩下的URI片段,拼接到proxy_pass指令中的URI

2). 如果proxy_pass指令中不包含URI

If proxy_pass is specified without a URI, the request URI is passed to the server in the same form as sent by a client when the original request is processed, or the full normalized request URI is passed when processing the changed URI:

location /some/path/ {
    proxy_pass http://127.0.0.1;
}

那么,按照以下两种情况处理:

  • i). 如果原始请求被处理过(所谓的处理,应该是指对URI进行标准化处理),则原始请求URI被发送给服务器
  • ii). 在处理改变后的URI时,完整的标准化后的请求URI被发送给服务器。

问题
什么叫 processing the changed URI: 处理改变后的URI时?
可能是指在proxy_pass之前有其他指令在处理URI,或者进行标准化?
所以,也就是说,如果proxy_pass中不包含任何URI,则传递标准化后的URI给服务器。

旧版本1.1.12以前

Before version 1.1.12, if proxy_pass is specified without a URI, the original request URI might be passed instead of the changed URI in some cases.

3). 一些特例

在一些特殊情况下,无法判断要如何替换请求URI

In some cases, the part of a request URI to be replaced cannot be determined:

3.1). location中使用了正则表达式,且同时在命名location中

那么,这时候,proxy_pass不应该设置URI。

When location is specified using a regular expression, and also inside named locations.
In these cases, proxy_pass should be specified without a URI.

问题
如果设置了怎么办?

3.2). 如果URI被rewrite指令修改了

那么,在proxy_pass中指定的URI被忽略,改变后的请求URI整个传给服务器。

When the URI is changed inside a proxied location using the rewrite directive, and this same configuration will be used to process a request (break):

location /name/ {
    rewrite    /name/([^/]+) /users?name=$1 break;
    proxy_pass http://127.0.0.1;
}

In this case, the URI specified in the directive is ignored and the full changed request URI is passed to the server.

注意
也就是说,使用了rewrite以后,再设置任何URI是没有意义的,除非是设置变量(参考下一节)。

3.3). 如果proxy_pass中使用了变量

那么,原始请求的URI被忽略,proxy_pass中的URI被传给服务器。

When variables are used in proxy_pass:

location /name/ {
    proxy_pass http://127.0.0.1$request_uri;
}

In this case, if URI is specified in the directive, it is passed to the server as is, replacing the original request URI.

注意
也就是说,如果proxy_pass中使用了变量,则原始请求URI就不再直接传给服务器,通常是对原始请求URI进行修改,并保存到proxy_pass的变量里。

原始请求与标准化请求

  • 原始请求,为客户端发送的请求,未经过任何处理
  • 标准化请求,按照一定规则进行解码和替换得到的标准URI

https://en.wikipedia.org/wiki/URI_normalization