详解proxy_pass根据path路径转发时的"/"问题记录

在nginx中配置proxy_pass时,如果是按照^~匹配路径时,要注意proxy_pass后的url最后的/。当加上了/,相当于是绝对根路径,则nginx不会把location中匹配的路径部分代理走;如果没有/,则会把匹配的路径部分也给代理走。

比如下面设置:

location ^~ /wangshibo/
{
proxy_cache js_cache;
proxy_set_header Host js.test.com;
proxy_pass http://js.test.com/;
}

如上面的配置,如果请求的url是http://servername/wangshibo/test.html会被代理成http://js.test.com/test.html

而如果这么配置

location ^~ /wangshibo/
{
proxy_cache js_cache;
proxy_set_header Host js.test.com;
proxy_pass http://js.test.com;
}

则请求的url是http://servername/wangshibo/test.html会被代理到http://js.test.com/wangshibo/test.html

当然,可以用如下的rewrite来实现/的功能

location ^~ /wangshibo/
{
proxy_cache js_cache;
proxy_set_header Host js.test.com;
rewrite /wangshibo/(.+)$ /$1 break;
proxy_pass http://js.test.com;
}

列举下面一例

1)第一种配置

[root@BJLX_16_202_V vhosts]# cat ssl-wangshibo.conf
upstream at {
  server 192.168.1.202:8080 max_fails=3 fail_timeout=30s;
}

server {
  listen 443;
  server_name www.wangshibo.com;
  ssl on;

  ### SSL log files ###
  access_log logs/wangshibo_access.log;
  error_log logs/wangshibo_error.log;

### SSL cert files ###
  ssl_certificate ssl/wang.cer;
  ssl_certificate_key ssl/wang.key;

  location /attendance/ {
  proxy_pass http://at;                             //不需要加上"/"
  proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;
  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-Forwarded-Proto https;
  proxy_redirect off;
    }

}

访问https://www.wangshibo.com/attendance/和http://192.168.1.202:8080/attendance结果是一致的。

2)第二种配置

[root@BJLX_16_202_V vhosts]# cat ssl-wangshibo.conf
upstream at {
  server 192.168.1.202:8080 max_fails=3 fail_timeout=30s;
}

server {
  listen 443;
  server_name www.wangshibo.com;
  ssl on;

  ### SSL log files ###
  access_log logs/wangshibo_access.log;
  error_log logs/wangshibo_error.log;

### SSL cert files ###
  ssl_certificate ssl/wang.cer;
  ssl_certificate_key ssl/wang.key;

  location / {
  proxy_pass http://at/attendance/;                         //一定要加上"/"
  proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;
  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-Forwarded-Proto https;
  proxy_redirect off;
    }
}

访问https://www.wangshibo.com和http://192.168.1.202:8080/attendance结果是一致的。

如下配置,想要实现的需求:

192.168.1.27是后端的real server,8080端口是公司的ehr人事系统端口。

又由于该系统涉及到微信接口访问,即http://ehr.wang.com/attendance和http://ehr.wang.com/app

由于是内部系统,安全考虑,所以要求:

1)登录ehr人事系统的时候要求使用内网登录,即http://192.168.1.27:8080,访问前要先登录公司VPN
2)登录微信接口http://ehr.wang.com/attendance和http://ehr.wang.com/app使用外网登录,即使用解析后域名登录。
3)访问http://ehr.wang.com,强制跳转为https://ehr.wang.com/attendance

[root@BJLX_4_21_P vhosts]# cat ehr.conf
server {
  listen 80;
  server_name ehr.wang.com;

  access_log logs/ehr_access.log;
  error_log  logs/ehr_error.log;

  return   301 https://$server_name$request_uri;
}

[root@BJLX_4_21_P vhosts]# cat ssl-ehr.conf
upstream ehr {
  server 192.168.1.27:8080 max_fails=3 fail_timeout=30s;
}

server {
  listen 443;
  server_name ehr.wang.com;
  ssl on;

  ### SSL log files ###
  access_log logs/ehr_access.log;
  error_log logs/ehr_error.log;

### SSL cert files ###
  ssl_certificate ssl/wang.cer;
  ssl_certificate_key ssl/wang.key;
  #ssl_session_timeout 5m;

  location / {
    return 301 https://ehr.wang.com/attendance;
  }

  location /attendance/ {
  proxy_pass http://ehr;
  proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;
  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-Forwarded-Proto https;
  #proxy_set_header X-Forwarded-Proto https;
  proxy_redirect off;
  }

  location /app/ {
  proxy_pass http://ehr;
  proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;
  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-Forwarded-Proto https;
  #proxy_set_header X-Forwarded-Proto https;
  proxy_redirect off;
  }
 }

注意:

由于从浏览器访问(http)到源站的real server之间要经过Nginx反向代理层(https)

需要将proxy_set_header X-Forwarded-Proto https;这一行注释掉,否则上面的配置无效。

如果中间没有代理层,直接是在real server本机进行nginx的反向代理(即本机nginx反代到本机的8080端口),则这个参数无效注释(已经过验证)

HTTP头域(proxy_set_header)列表与解释

HTTP 头域是HTTP协议中请求(request)和响应(response)中的头部信息,其实就是HTTP通信的操作参数,告诉web服务器和浏览器怎样处理这个通信。

HTTP头从一个请求信息或者响应信息的第二行开始(第一行是请求行或者响应行),以两个CR-LF字符组结束(CR:回车符,\r,LF:换行符\n)

而每个HTTP头是字符串形式的,用冒号分割的键值对,多个HTTP头之间用CR-LF字符组隔开。

某些http头可以有注释,例如user-agent,server,via。但这些注释会被服务器或者浏览器忽略IETF组织已经将一些核心的HTTP头定义在RFC2616规范中,
这些HTTP头是每个基于HTTP协议的软件必须实现的,而其他一些更新和扩展的头域也必须被基于HTTP的软件实现。当然,各个软件也可以定义自己的头域。

另一方面,RFC2616规范中并没有限制每个HTTP头的长度,或者限制HTTP头的数量,但出于性能和安全的考虑,多数服务器都会自己作规定,例如apache2.3
就规定每个HTTP头不能超过8190个字节,每个请求不能超过100个HTTP头。

以下来看看发送一个请求(request)时候,可能包含的各个HTTP头和它的解释。

标准的请求头--

Accept: 浏览器(或者其他基于HTTP的客户端程序)可以接收的内容类型(Content-types),例如 Accept: text/plain

Accept-Charset:浏览器能识别的字符集,例如 Accept-Charset: utf-8

Accept-Encoding:浏览器可以处理的编码方式,注意这里的编码方式有别于字符集,这里的编码方式通常指gzip,deflate等。例如 Accept-Encoding: gzip, deflate

Accept-Language:浏览器接收的语言,其实也就是用户在什么语言地区,例如简体中文的就是 Accept-Language: zh-CN

Authorization:在HTTP中,服务器可以对一些资源进行认证保护,如果你要访问这些资源,就要提供用户名和密码,这个用户名和密码就是在Authorization头中附带的,格式是“username:password”字符串的base64编码,例如:Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==中,basic指使用basic认证方式, QWxhZGRpbjpvcGVuIHNlc2FtZQ==使用base64解码就是“Aladdin:open sesame”

Cache-Control:这个指令在request和response中都有,用来指示缓存系统(服务器上的,或者浏览器上的)应该怎样处理缓存,因为这个头域比较重要,特别是希望使用缓 存改善性能的时候,内容也较多,所以我想在下一篇博文中主要介绍一下。

Connection:告诉服务器这个user agent(通常就是浏览器)想要使用怎样的连接方式。值有keep-alive和close。http1.1默认是keep-alive。keep-alive就是浏览器和服务器 的通信连接会被持续保存,不会马上关闭,而close就会在response后马上关闭。但这里要注意一点,我们说HTTP是无状态的,跟这个是否keep-alive没有关系,不要认为keep-alive是对HTTP无状态的特性的改进。

Cookie:浏览器向服务器发送请求时发送cookie,或者服务器向浏览器附加cookie,就是将cookie附近在这里的。例如:Cookie:user=admin

Content-Length:一个请求的请求体的内存长度,单位为字节(byte)。请求体是指在HTTP头结束后,两个CR-LF字符组之后的内容,常见的有POST提交的表单数据,这个Content-Length并不包含请求行和HTTP头的数据长度。

Content-MD5:使用base64进行了编码的请求体的MD5校验和。例如:Content-MD5: Q2hlY2sgSW50ZWdyaXR5IQ==

Content-Type:请求体中的内容的mime类型。通常只会用在POST和PUT方法的请求中。例如:Content-Type: application/x-www-form-urlencoded

Date:发送请求时的GMT时间。例如:Date: Tue, 15 Nov 1994 08:12:31 GMT

Expect:指示需要使用服务器某些特殊的功能。(这个我不是很清楚)

From:发送这个请求的用户的email地址。例如:From: user@example.com

Host:被服务器的域名或IP地址,如果不是通用端口,还包含该端口号,例如:Host: www.some.com:182

If-Match:通常用在使用PUT方法对服务器资源进行更新的请求中,意思就是,询问服务器,现在正在请求的资源的tag和这个If-Match的tag相不相同,如果相同,则证明服务器上的这个资源还是旧的,现在可以被更新,如果不相同,则证明该资源被更新过,现在就不用再更新了(否则有可能覆盖掉其他人所做的更改)。

If-Modified-Since:询问服务器现在正在请求的资源在某个时间以来有没有被修改过,如果没有,服务器则返回304状态来告诉浏览器使用浏览器自己本地的缓存,如果有修改过,则返回200,并发送新的资源(当然如果资源不存在,则返回404。)

If-None-Match:和If-Modified-Since用意差不多,不过不是根据时间来确定,而是根据一个叫ETag的东西来确定。关于etag我想在下一篇博客介绍一下。

If-Range:告诉服务器如果这个资源没有更改过(根据If-Range后面给出的Etag判断),就发送这个资源中在浏览器缺少了的某些部分给浏览器,如果该资源以及被修改过,则将整个资源重新发送一份给浏览器。

If-Unmodified-Since:询问服务器现在正在请求的资源在某个时刻以来是否没有被修改过。

Max-Forwards:限制请求信息在代理服务器或网关中向前传递的次数。

Pragma:好像只有一个值,就是:no-cache。Pragma:no-cache 与cache-control:no-cache相同,只不过cache-control:no-cache是http1.1专门指定的,而Pragma:no-cache可以在http1.0和1.1中使用

Proxy-Authorization:连接到某个代理时使用的身份认证信息,跟Authorization头差不多。例如:Proxy-Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

Range:在HTTP头中,"Range"字眼都表示“资源的byte形式数据的顺序排列,并且取其某一段数据”的意思。Range头就是表示请求资源的从某个数值到某个数值间的数据,例如:Range: bytes=500-999 就是表示请求资源从500到999byte的数据。数据的分段下载和多线程下载就是利用这个实现的。

Referer:指当前请求的URL是在什么地址引用的。例如在www.a.com/index.html页面中点击一个指向www.b.com的超链接,那么,这个www.b.com的请求中的Referer就是www.a.com/index.html。通常我们见到的图片防盗链就是用这个实现的。

Upgrade:请求服务器更新至另外一个协议,例如:Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11

User-Agent:通常就是用户的浏览器相关信息。例如:User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:12.0) Gecko/20100101 Firefox/12.0

Via:用来记录一个请求经过了哪些代理或网关才被送到目标服务器上。例如一个请求从浏览器出发(假设使用http/1.0),发送给名为 SomeProxy的内部代理,然后被转发至www.somenet.com的公共代理(使用http/1.1),最后被转发至目标服务器www.someweb.com,那么在someweb.com中收到的via 头应该是: via:1.0 someProxy 1.1 www.someweb.com(apache 1.1)

Warning:记录一些警告信息。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • nginx proxy_pass指令’/’使用注意事项

    1. proxy_pass配置说明 不带/ 复制代码 代码如下: location /test/ { proxy_pass http://t6:8300;  } 带/ 复制代码 代码如下: location /test/  {                  proxy_pass http://t6:8300/;   } 上面两种配置,区别只在于proxy_pass转发的路径后是否带 "/" 针对情况1,如果访问url = http://server/test/test.jsp,则被

  • nginx proxy_pass反向代理配置中url后加不加/的区别介绍

    前言 nginx作为web服务器一个重要的功能就是反向代理.nginx反向代理的指令不需要新增额外的模块,默认自带proxy_pass指令,只需要修改配置文件就可以实现反向代理. 而在日常的web网站部署中,经常会用到nginx的proxy_pass反向代理,有一个配置需要弄清楚:配置proxy_pass时,当在后面的url加上了/,相当于是绝对根路径,则nginx不会把location中匹配的路径部分代理走;如果没有/,则会把匹配的路径部分也给代理走(这样配置可以参考这篇文章). 下面举个小实

  • Nginx服务器的反向代理proxy_pass配置方法讲解

    就普通的反向代理来讲 Nginx的配置还是比较简单的,如: location ~ /* { proxy_pass http://127.0.0.1:8008; } 或者可以 location / { proxy_pass http://127.0.0.1:8008; } Apache2的反向代理的配置是: ProxyPass /ysz/ http://localhost:8080/ 然而,如果要配置一个相对复杂的反向代理 Nginx相对Apache2就要麻烦一些了 比如,将url中以/wap/开

  • 记一次nginx中proxy_pass的使用问题

    最近排查一个web服务的问题,webserver使用的nginx,最终发现是踩了nginx中proxy_pass的一个坑,这里记录下来. 踩坑经过 一个线上的http服务,示例nginx关键配置如下: server { listen 80; server_name ligang.gdemo.com; server_tokens off; keepalive_timeout 5; charset utf-8; include /home/ligang/devspace/gobox-demo/con

  • 详解proxy_pass根据path路径转发时的"/"问题记录

    在nginx中配置proxy_pass时,如果是按照^~匹配路径时,要注意proxy_pass后的url最后的/.当加上了/,相当于是绝对根路径,则nginx不会把location中匹配的路径部分代理走;如果没有/,则会把匹配的路径部分也给代理走. 比如下面设置: location ^~ /wangshibo/ { proxy_cache js_cache; proxy_set_header Host js.test.com; proxy_pass http://js.test.com/; }

  • 详解Python中的路径问题

    1. 绝对路径引入 Python 在搜索模块时,依次搜索sys.path里的位置,直到找到模块为止.下面命令可以查看当前的搜索路径: import sys print(sys.path) sys.path的初始值来源于两个(其实还有一些更复杂但不常用的).一个是系统的PYTHONPATH变量,因此可通过设置该变量,来设置 Python 默认的搜索位置.比如: export PYTHONPATH=/opt/python:$PYTHONPATH echo $PYTHONPATH 将该命令放在系统初始

  • 详解查看Python解释器路径的两种方式

    进入python的安装目录, 查看python解释器 进入bin目录 # ls python(看一下是否有python解释器版本) # pwd (查看当前目录) 复制当前目录即可 1. 通过脚本查看 运行以下脚本,或者进入交互模式手动输入即可. import sys import os print('当前 Python 解释器路径:') print(sys.executable) r""" 当前 Python 解释器路径: C:\Users\jpch89\AppData\Lo

  • 详解python os.path.exists判断文件或文件夹是否存在

    os即operating system(操作系统),Python 的 os 模块封装了常见的文件和目录操作. os.path模块主要用于文件的属性获取,exists是"存在"的意思,所以顾名思义,os.path.exists()就是判断括号里的文件是否存在的意思,括号内的可以是文件路径. 举个栗子: import os #判断文件夹是否存在 dir = os.path.exists('C:\\Users\\Desktop') print('dir:', dir) #判断文件是否存在 f

  • python 标准库原理与用法详解之os.path篇

    os中的path 查看源码会看到,在os.py中有这样几行 if 'posix' in _names: name = 'posix' linesep = '\n' from posix import * #省略若干代码 elif 'nt' in _names: from nt import * try: from nt import _exit __all__.append('_exit') except ImportError: pass import ntpath as path #...

  • 详解IOS中文件路径判断是文件还是文件夹

    详解IOS中文件路径判断是文件还是文件夹 方法1 + (BOOL)isDirectory:(NSString *)filePath { BOOL isDirectory = NO; [[NSFileManager defaultManager] fileExistsAtPath:filePath isDirectory:&isDirectory]; return isDirectory; } 方法2 + (BOOL)isDirectory:(NSString *)filePath { NSNum

  • 详解java配置文件的路径问题

    详解java配置文件的路径问题 各种语言都有自己所支持的配置文件,配置文件中有很多变量是经常改变的.不将程序中的各种变量写死,这样能更方便地脱离程序本身去修改相关变量设置. 那么我们需要读取配置文件,是需要获取配置文件的路径.那么配置文件的路径怎么写呢? 1.绝对路径 绝对路径是指目录下的绝对位置,直接到达目标位置,通常是从盘符开始的路径.如果我们将配置文件的路径写成绝对路径的话,相对于各种计算机系统来说是不通用的. 2.相对路径 相对路径就是指由这个文件所在的路径引起的跟其它文件(或文件夹)的

  • 详解使用fetch发送post请求时的参数处理

    详解使用fetch发送post请求时的参数处理 不考虑古董浏览器之后,使用fetch来发送ajax请求,变得非常爽快和时尚. 但是,发送post请求的时候,把笔者卡了一下.后台如下获取参数时,总是为null String q = req.getParameter("q"); 研究了好久,总算写出正确的使用方式了.直接上代码. fetch("/search/project/", { method: "POST", headers: { 'Conte

  • 详解Android Webview加载网页时发送HTTP头信息

    详解Android Webview加载网页时发送HTTP头信息 当你点击一个超链接进行跳转时,WebView会自动将当前地址作为Referer(引荐)发给服务器,因此很多服务器端程序通过是否包含referer来控制盗链,所以有些时候,直接输入一个网络地址,可能有问题,那么怎么解决盗链控制问题呢,其实在webview加载时加入一个referer就可以了,如何添加呢? 从Android 2.2 (也就是API 8)开始,WebView新增加了一个接口方法,就是为了便于我们加载网页时又想发送其他的HT

  • 详解SpringBoot项目docker环境运行时无限重启问题

    可能是我开始处理问题的思路不对,现在描述问题可能也有点乱,但是里面可能的处理方式希望能帮到遇到我这个坑的人 描述:springboot项目,docker镜像里面运行,看docker的日志,项目启动成功后,隔了一分钟左右他就自动重新启动,然后造成网站接口访问的时候nginx报502 gateway啥的,有两台服务器,一个是文件服务器,运行了很简单的上传下载文件的代码以及验证token,另一台运行了java应用,两台服务器都在一次更新项目的镜像,运行过后遇到了这个问题,很奇怪. 然后我将项目弄成ja

随机推荐