网管把PUT请求禁掉非说是我们接口的问题---nginx 请求转发就完了?各种奇技淫巧等你来

开发是项目的成型的第一步,项目内部、外部统一话接口还得借助nginx 这种请求转发工具,因为你无法保证项目的单一性,我们整个项目可能用到各种各样的技术。

Nginx配置proxy_pass转发的/路径问题

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

ini 复制代码
location ^~ /static_js/ 
{ 
proxy_cache js_cache; 
proxy_set_header Host js.test.com; 
proxy_pass http://js.test.com/; 
}

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

而如果这么配置

nginx 复制代码
location ^~ /static_js/ 
{ 
proxy_cache js_cache; 
proxy_set_header Host js.test.com; 
proxy_pass http://js.test.com; 
}

则会被代理到js.test.com/static_js/t...

root alias 区别

nginx 复制代码
location /test/{
    root /home/china/areas/;
}

访问 localhost***/test/hello.html实际访问的是 /home/china/areas/test/hello.html

nginx 复制代码
location /tets/{
    alias /home/china/areas/;
}

访问 localhost***/test/hello.html实际访问的是 /home/china/areas/hello.html

server_name 的使用

  • 之前我一直认为这里的 server_name 就是方便我们访问的域名。其实并不是这么回事。不信你配置好之后在浏览器中访问根本是访问不同的。

  • 首先我们得明白我们请求的域名是需要经过 DNS 解析的。和 nginx 是无关的。本地的 DNS 解析就是本地的 /etc/hosts 文件。

ini 复制代码
server {
  listen 88;
  listen [::]:88;

  server_name www.zxhtom.com;

  root /var/www/html;
  index index.html;

  location / {
    try_files $uri $uri/ =404;
  }
}

server {
  listen 88;
  listen [::]:88;

  server_name www.zxhtom.cn;

  root /var/www/example.com;
  index index.html;

  location / {
    try_files $uri $uri/ =404;
  }
}
  • 上面我配置了两个 server 可能你会觉得奇怪,为什么两个 server 都是监听88端口呢?仔细观察你会发现他们的 server_name 不同。

  • 接下来我们在本地配置这两个域名的解析

    127.0.0.1 www.zxhtom.com
    127.0.0.1 www.zxhtom.cn

  • 访问两个域名对应的 88端口,我们能够发现对应的是不同的页面。到这里你应该明白 server_name 的作用的吧。

  • 上述的配置同时对 127.0.0.1 的使用也没啥影响。
  • 配置了专属域名如果此时 hosts 文件中配置了另外一个域名 www.zxhtom.store 那么是否还需要在另行配置呢?答案是否定的。
  • 当出现新的域名访问 nginx 的时候,nginx 会去寻找配置了 default_server 的 server 。如上我们两个 server 都没有配置 default_server . nginx 会按照顺序选取第一个。换句话说我们 www.zxhtom.store 对应的是 www.zxhtom.com server_name 的配置。如果我们想让 www.zxhtom.cn 作为默认的,我们可以将他配置在地一个。或者修改成如下配置
nginx 复制代码
server {
  listen 80 default_server;
  listen [::]:80 default_server;

  server_name www.zxhtom.cn;
  charset utf-8;
  root /home/zxhtom/temp/html;
  index index.html;
}

中文乱码

  • 上面我们能够发现,我们自定义的页面显示的是乱码。

SSL

  • google 浏览器带头限制 http 请求,关于网站 SSL 证书的配置尤为重要。下面我们通过 nginx 来配置下 SSL
  • 阿里云域名服务地方可以申请免费的 SSL 证书。申请之后可以按照阿里官方的教程配置
config 复制代码
server {
	# SSL configuration
	#
	listen 443 ssl ;
	listen [::]:443 ssl ;
  server_name www.zxhtom.cn;
  #填写证书文件名称
  ssl_certificate cert/<domain_name>.pem;
  #填写证书私钥文件名称
  ssl_certificate_key cert/<domain_name>.key;

  ssl_session_cache shared:SSL:1m;
  ssl_session_timeout 5m;

  #默认加密套件
  ssl_ciphers HIGH:!aNULL:!MD5;

  #自定义设置使用的TLS协议的类型以及加密套件(以下为配置示例,请您自行评估是否需要配置)
  #TLS协议版本越高,HTTPS通信的安全性越高,但是相较于低版本TLS协议,高版本TLS协议对浏览器的兼容性较差。
  #ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
  #ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;

  #表示优先使用服务端加密套件。默认开启
  ssl_prefer_server_ciphers on;

  location / {

    default_type application/json;
    return 200 '{"status":"success","result":"welcom https cn"}';
    # try_files $uri $uri/ =404;
    # proxy_pass http://192.168.0.190;
  }
}
  • 结合上面我们描述的 server_name 的功能,我们上述的配置就是支持 https://www.zxhtom.cn 的请求访问。当我们访问该地址就会返回 welcom https cn 等信息。

接口 413 错误

  • 413 Request Entity Too Large 。根据提示第一反应就是请求体过大。但是我的报错是 GET 请求,仔细观察下 GET 请求没啥参数传递的。不管三七二十一先按照网上的进行修改下。
nginx 复制代码
413 Request Entity Too Large
nginx 复制代码
location /zxhtom/latest/{
	proxy_set_header Host $http_host;
	proxy_set_header X-Real-IP $remote_addr;
	proxy_set_header REMOTE-HOST $remote_addr;
	proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
	client_max_body_size 800m;
	proxy_pass http://www.zxhtom.com/;
}
  • 只需要添加 client_max_body_size 参数即可放开我们请求体的数据了。但是还是解决不了我的问题,而且 client_max_body_size 根绝名字猜测应该是请求数据大小的设置,应该主要使用的场景是文件上传才需要设置,正常数据怎么会有几百 M 呢?
  • 在分析下自己的数据发现因为接口需要登录请求头中 JWT 的 token 特别的长。于是搜索了下 nginx 是否可以调整请求头大小。
nginx 复制代码
client_header_buffer_size 16k;
large_client_header_buffers 4 16k;
  • 设置了之后还是不行,于是将焦点下放到网关层面上 http://www.zxhtom.com。于是我跳过 nginx 单独访问网管发现报错 400 。他的报错突然让我坚定了自己的猜想,我们的网关是通过 SpringCloud Gateway 实现的。
java 复制代码
server:
	max-http-header-size: 2MB
java 复制代码
@Component
public class NettyConfiguration implements WebServerFactoryCustomizer<NettyReactiveWebServerFactory> {

    @Override
    public void customize(NettyReactiveWebServerFactory container) {
        container.addServerCustomizers(
                httpServer -> httpServer.httpRequestDecoder(
                        httpRequestDecoderSpec -> httpRequestDecoderSpec.maxHeaderSize(1000485760)
                )
        );
    }

}
  • 在网关中添加如上配置即可解决 413 问题。

PUT/DELETE 接口 Empty reply

  • 由于政务系统对安全性的要求,在他们网络层面上将 PUT 、DELETE 这两种请求给禁掉了。而我们系统中存在大面积的这样的请求,如果改的话工作量巨大而且容易遗漏,后来找到一中通过 nginx 转发的方案来解决这个问题。
nginx 复制代码
set $method $request_method;
      if ($http_X_HTTP_Method_Override ~* 'DELETE'){
       set $method DELETE;

      }
      if ($http_X_HTTP_Method_Override ~* 'PUT'){
       set $method PUT;

      }
      proxy_method $method;
  • 加上上面这段配置后重启 nginx ,原本的 PUT 接口我们只需要修改为 POST,并且请求头中添加 X-HTTP-Method-Override:PUT 即可。
shell 复制代码
curl -XPUT 'http://www.zxhtom.com/pre/userList'
  • 只需要改为
shell 复制代码
curl -XPOST 'http://www.zxhtom.com/pre/userList' -H'X-HTTP-Method-Override:PUT'
相关推荐
是覆盖对于变化11 分钟前
ubuntu22.04 进入不了系统设置
linux·ubuntu
应以大橘为重18 分钟前
interrupt子系统中的数据结构
linux·数据结构·驱动开发
穷儒公羊18 分钟前
第一部分——Docker篇 第三章 构建自定义镜像
java·运维·后端·学习·docker·云原生·容器
kfepiza35 分钟前
硬盘分区格式方案之 MBR(Master Boot Record)主引导记录详解 笔记250407
linux·windows·笔记
mzak36 分钟前
已经安装了pip,出现pip command not found【解决方法】
linux·pip·python3
isfox1 小时前
速学!Java 原子操作,开启并发编程新境界
后端·程序员
南风与鱼1 小时前
Linux 线程池
linux·线程池
楽码1 小时前
只需一文!深入理解闭包的实现
后端·go·编程语言
cong_1 小时前
🌟摸鱼 TV 搭建属于自己的视频站
前端·后端·github
bobz9651 小时前
内网网络 rp_filter 参数配置
后端