暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

nginx rewrite与proxy_pass配置问题分享

开发架构二三事 2019-11-07
999

websocket服务器在用http://localhost:8888/bbbb/websocket请求时总是报错,经过分析发现是nginx的问题,于是有了这篇文章。

nginx 的配置一

  1. location /bbbb/websocket{

  2. rewrite ^/bbbb/websocket/(.*)$ /websocket/$1 break ;

  3. proxy_pass http://websocketbbbb/;

  4. proxy_connect_timeout 60;

  5. proxy_send_timeout 60;

  6. proxy_read_timeout 3000;

  7. proxy_set_header Host $host;

  8. proxy_set_header X-Real-IP $remote_addr;

  9. proxy_set_header REMOTE-HOST $remote_addr;

  10. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

  11. proxy_http_version 1.1;

  12. proxy_set_header Upgrade $http_upgrade;

  13. proxy_set_header Connection 'Upgrade';


  14. }

请求一

  • 路径:https://abc.ddd.cn/bbbb/websocket

  • 请求方式:post

  • nginx 日志:

  1. 1.1.1.1 - - [07/Nov/2019:15:58:42 +0800] "POST /bbbb/websocket HTTP/2.0" 404 13 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.87 Safari/537.36"

  • 抓包信息:

  1. POST / HTTP/1.1

  2. Host: abc.ddd.cn

  3. X-Real-IP: 1.1.1.1

  4. REMOTE-HOST: 1.1.1.1

  5. X-Forwarded-For: 1.1.1.1

  6. Connection: Upgrade

  7. Content-Length: 10

  8. user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.87 Safari/537.36

  9. cache-control: no-cache

  10. origin: chrome-extension://fhbjgbiflinjbdggehcddcbncdddomop

  11. x-requested-with: XMLHttpRequest

  12. accept-language: zh-CN,zh;q=0.9,en;q=0.8

  13. postman-token: 17daff12-3bcc-4c1c-4c9f-2f5aebaa3cd5

  14. content-type: application/x-www-form-urlencoded

  15. accept: */*

  16. sec-fetch-site: cross-site

  17. sec-fetch-mode: cors

  18. accept-encoding: gzip, deflate, br


  19. 6666666666HTTP/1.1 404 Not Found

  20. content-length: 13


  21. 404 Not Found

  • 服务器输出:


结果为:

  1. before request method is:POST req uri is:/-[]

其他请求(请求方式不变)

  1. 请求路径:http://localhost:8888/bbbb/websocket/ 服务器输出:

  1. before request method is:POST req uri is://-[]

  1. 请求路径:http://localhost:8888/bbbb/websocket/aaa 服务器输出:

  1. before request method is:POST req uri is://aaaa-[]

分析

原因是 rewrite 规则没生效,因为把rewrite那一行去掉,重启nginx之后,各种请求呈现的结果无殊。同时我们需要注意的是proxy_pass的规则,当rewrite不生效时:

  • https://abc.ddd.cn/bbbb/websocket进入proxy_pass后会请求http://websocketbbbb/;

  • http://localhost:8888/bbbb/websocket/会请求http://websocketbbbb//

  • http://localhost:8888/bbbb/websocket/aaa会请求http://websocketbbbb//aaa

也就是与location匹配上之后多出的那一段都会加到proxy_pass后面。

关于proxy_pass更多的说明,参考下这篇文章:https://blog.csdn.net/ainuser/article/details/80260144

说明,这种情况下不会与rewrite规则匹配上,所以路径直接与proxy_pass匹配。

nginx 的配置二

  1. location /bbbb/websocket/{

  2. rewrite ^/bbbb/websocket/(.*)$ /websocket/$1 break ;

  3. proxy_pass http://websocketbbbb/;

  4. proxy_connect_timeout 60;

  5. proxy_send_timeout 60;

  6. proxy_read_timeout 3000;

  7. proxy_set_header Host $host;

  8. proxy_set_header X-Real-IP $remote_addr;

  9. proxy_set_header REMOTE-HOST $remote_addr;

  10. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

  11. proxy_http_version 1.1;

  12. proxy_set_header Upgrade $http_upgrade;

  13. proxy_set_header Connection 'Upgrade';


  14. }

第一种情况:


  • 请求路径:https://abc.ddd.cn/bbbb/websocket



  • 请求方式:POST



  • nginx 日志:


  1. 1.1.1.1 - - [07/Nov/2019:14:43:27 +0800] "POST /bbbb/websocket/ HTTP/2.0" 302 154 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.87 Safari/537.36"


  2. 1.1.1.1 - - [07/Nov/2019:14:43:27 +0800] "GET /404.html HTTP/2.0" 200 754 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.87 Safari/537.36"

第二种情况:


  • 请求路径:https://abc.ddd.cn/bbbb/websocket/



  • 请求方式:POST



  • nginx 日志:


  1. 1.1.1.1 - - [07/Nov/2019:14:44:19 +0800] "POST /bbbb/websocket HTTP/2.0" 301 178 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.87 Safari/537.36"


  2. 1.1.1.1 - - [07/Nov/2019:14:44:23 +0800] "GET /bbbb/websocket/ HTTP/2.0" 302 154 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.87 Safari/537.36"

  3. 1.1.1.1 - - [07/Nov/2019:14:44:23 +0800] "GET /404.html HTTP/2.0" 200 754 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.87 Safari/537.36"

问题分析

两种情况下均为 post 请求,可以看出,在第一种情况下请求被转换成了 GET,从而导致后台 websocket 服务报错。第二种情况正常工作。

原因在于location的路径为/bbbb/websocket/,而实际发送请求的路径为/bbbb/websocket,当请求匹配上时nginx会自动在后面添加一个目录/,然后进行重定向,关于这个问题,可以参考:https://www.cnblogs.com/zeoblog/p/6046144.html。也就是说这种情况下的匹配会有两步,先添加一层目录进行301重定向,然后再次匹配时路径是正确的,但是请求方式由post改成了get,从而导致后台服务报错。

注意,这个301不是rewrite引起的,break操作下的rewrite是不会重定向的。添加目录的操作是在location路径的最后一层匹配时发生的。对于get和post请求如果路径不正确时都会出现重定向的情况,只是post方式重定向后会变成get。

说明,这种情况下都会与rewrite规则匹配上,所以会先进行rewrite之后再将rewrite的结果加在proxy_pass上。

解决办法

配置修改为:

  1. location /bbbb/{

  2. rewrite ^/bbbb/websocket/(.*)$ /websocket/$1 break ;

  3. proxy_pass http://websocketbbbb/;

  4. proxy_connect_timeout 60;

  5. proxy_send_timeout 60;

  6. proxy_read_timeout 3000;

  7. proxy_set_header Host $host;

  8. proxy_set_header X-Real-IP $remote_addr;

  9. proxy_set_header REMOTE-HOST $remote_addr;

  10. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

  11. proxy_http_version 1.1;

  12. proxy_set_header Upgrade $http_upgrade;

  13. proxy_set_header Connection 'Upgrade';


  14. }

这种情况下,请求路径为/bbbb/websocket时会完全匹配location,不会再往路径后面添加/,不会先进行301重定向。

说明,这种情况下rewrite和proxy_pass都能正常工作,而且不会出现nginx自动添加一层目录的问题。

参考

  • http://nginx.org/en/docs/http/ngxhttpcoremodule.html#servernameinredirect


文章转载自开发架构二三事,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论