网管把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'
相关推荐
码农小旋风13 分钟前
详解K8S--声明式API
后端
Peter_chq14 分钟前
【操作系统】基于环形队列的生产消费模型
linux·c语言·开发语言·c++·后端
Yaml438 分钟前
Spring Boot 与 Vue 共筑二手书籍交易卓越平台
java·spring boot·后端·mysql·spring·vue·二手书籍
小小小妮子~39 分钟前
Spring Boot详解:从入门到精通
java·spring boot·后端
hong16168841 分钟前
Spring Boot中实现多数据源连接和切换的方案
java·spring boot·后端
一坨阿亮1 小时前
Linux 使用中的问题
linux·运维
睡觉谁叫~~~2 小时前
一文解秘Rust如何与Java互操作
java·开发语言·后端·rust
dsywws2 小时前
Linux学习笔记之vim入门
linux·笔记·学习
幺零九零零3 小时前
【C++】socket套接字编程
linux·服务器·网络·c++
2401_865854884 小时前
iOS应用想要下载到手机上只能苹果签名吗?
后端·ios·iphone