开发是项目的成型的第一步,项目内部、外部统一话接口还得借助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'