Nginx 从入门到实践,万字详解!
原文链接:https://mp.weixin.qq.com/s/JUOyAe1oEs-WwmEmsHRn8w
下面是我的一些经验总结
转发解决跨域问题
1 | server { |
always 可加可不加
Access-Control-Allow-Headers
根据自己的情况添加允许的请求头,示例里面为了以防遗漏就列了很多。非生产环境可以直接如下写法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 server {
listen 2077; # 开启端口
server_name 0.0.0.0;
location / {
if ($request_method = 'OPTIONS') {
add_header Access-Control-Allow-Origin '*';
add_header Access-Control-Allow-Methods '*';
add_header Access-Control-Allow-Headers '*';
add_header Access-Control-Allow-Credentials true;
return 204;
}
rewrite ^/api_v1/(.*)$ /$1 break;
proxy_pass https://xxx.xxx.xxx;
}
}
设置web访问密码
采用 ngx_http_auth_basic_module
模块实现,详见:https://blog.csdn.net/weixin_44427181/article/details/123021721
docker安装nginx
1 | # 获取nginx镜像列表 |
nginx核心模块配置
http://nginx.org/en/docs/http/ngx_http_core_module.html#ignore_invalid_headers
nginx伪造ua头
1 | location ~* /api/v1/ { |
nginx禁止其他应用访问
1 | # CMFBK-24569 |
nginx缓存策略
nginx默认是使用协商缓存,响应头带 Etag
和 Last-Modified
、Date
可以通过
etag off;
配置关闭Etag这里涉及一个坑点,根据 RFC7234 标准,没有设置强缓存的请求头但是有
Last-Modified
和Date
,会采用启发式算法时间作为强制缓存。
1 缓存时间 = (Date - Last-Modified) / 10所以如果希望请求都走协商缓存还需要设置
Cache-Control "no-cache"
作为单页面应用,通常我们的静态资源文件都是通过webpack的contenthash来避免缓存的,但是无法避免入口不缓存。通常有2种方法解决入口被缓存问题。
方法1:通过http协议控制缓存
1 | etag: on; |
方法2:设置中间页面
中间页面通过给目标页面添加动态参数的方式(如时间戳)来绕过缓存
值得注意的是中间页面也可能被缓存,因此中间页面应尽可能不更新
亦或者中间页面做成接口访问后302重定向到目标页面
nginx配置Cookie转发
第一种配置方法
1 | server { |
第二种配置方法
1 | server { |
nginx的HTTP Code444和307设置
444
在nginx中添加一个default server,并在default server中设置return 444;
。此时Nginx就不会响应请求,除非请求的Host是配置的。
1 | server { |
此时请求服务器,在Chrome中显示的页面如下:
和499类似,444不是标准的HTTP status code,而是Nginx自己设立的状态码,参见444 CONNECTION CLOSED WITHOUT RESPONSE
设置了444过后,nginx收到不匹配的Host请求的话,不会有任何响应。比起404之类,另外一个好处就是可以节省一点点的带宽。
307
随着网络安全越发重要,越来越多的网站都从http迁移到了https。但迁移到https之前分发出去的链接都是http,为了兼容以前的链接,就需要做一个redirect,将http的请求redirect到https中。
最常见的redirect方式就是301 Moved Permanently或者302 Found, 将http重定向到https中。
对于普通的GET请求,这种方式是完全可以的。但当请求是POST的时候,由于一些历史原因,一些浏览器和库收到301或302的时候,会将原本的POST请求转为GET请求发送。此时POST的body会丢失,导致请求出问题。
如果要redirect POST请求,则需要使用307 Temporary Redirect来进行redirect。RFC 7231中对于307的一个描述”Note: This status code is similar to 302 (Found), except that it does not allow changing the request method from POST to GET. “
一个GET是301, POST是307的nginx配置例子
1 | server { |
400错误处理
首先,该问题会记录到nginx的error日志中(info级别),首先排查根据nginx的错误日志确定具体原因,下面列举一些常见导致原因:
请求头过大
通常是由于cookie中写入了较大的值所引起。在nginx.conf中,调整
client_header_buffer_size
和large_client_header_buffer
参数大小可以解决问题网络传输丢包
-
Valid names are composed of English letters, digits, hyphens, and possibly underscores (as controlled by the underscores_in_headers directive).
简单来说,请求头只能是字母,数字,连字符(-)和下划线(_, 需要配置
underscores_in_headers on;
),其他请求头都是非法请求头,可以配置ignore_invalid_headers on;
丢弃错误的请求头补充:如果header的key里面带空格,ignore_invalid_headers无效
413错误处理
Nginx服务器
打开nginx主配置文件nginx.conf,找到http{}段,添加client_max_body_size 20M;
client_max_body_size这个参数限制了上传文件的大小,默认是1M,我在上面的修改中给了20M的限制。
修改之后一定要重新载入 nginx (service nginx reload)。
php服务器
php默认上传文件大小限制为2M,如果超出2M你需要修改php配置文件php.ini里面的参数。
post_max_size = 8M(表单提交的最大限制,此项不是限制上传单个文件的大小,而是针对整个表单提交的数据进行限制。)
upload_max_filesize = 2M (上传的单个文件的最大限制)
需要保证 post_max_size >= upload_max_filesize ,也就是前者不小于后者。
修改之后一定要重启 php-fpm 。
tomcat服务器
修改tomcat的配置文件C:/MinyooCMS/tomcat/conf/server.xml(或者安装在D盘文件路径是D: /MinyooCMS/tomcat/conf/server.xml),找到里面的<Connector>
标签,在该标签中添加”maxPostSize”属性,将该属性值设置成你想要的最大值,单位是字节,或者把这个值设置为 0(maxPostSize=”0”),tomcat将不再检查POST的大小。
IIS服务器(Windows Server 2003系统IIS6)
先停止IIS Admin Service服务,然后找到windows/system32/inesrv/下的metabase.xml,打开,找到ASPMaxRequestEntityAllowed 修改为需要的值,然后重启IIS Admin Service服务
1、在web服务扩展 允许active server pages和在服务器端的包含文档
2、修改各站点的属性 主目录-配置-选项-启用父路径
3、使之可以上传大文档(修改成您想要的大小就可以了,以字节为单位)
c:/WINDOWS/system32/inetsrv/MetaBase.xml
!企业版的windows2003在第592行
默认的预设置值 AspMaxRequestEntityAllowed=”204800” 即200K
将其加两个0,即改为,现在最大就可以上传20M了。
AspMaxRequestEntityAllowed=”20480000”
301重定向
场景:
我有一个(大)网站迁移中的URL列表,需要匹配整个URL +查询字符串并重定向到另一个URL.
据我所知,以下仅匹配/mens
,而不匹配其余的查询字符串.
1 | rewrite "^/mens?brand%5B%5D=27§ion%5B%5D=5&price-min=0&price-max=2000&sort=newest" "/t/gender/men" permanent; |
重要的原因是我有一堆类似的URL,但查询字符串略有不同,需要重定向,类似于下面的内容,但实际上可以工作….
1 | rewrite "^/mens/shop?q=road+map+polo" "/t/category/golf-knits" permanent; |
解决方法:
$request_uri
变量包含整个URL.您可以使用map将其转换为重定向.
1 | map $request_uri $target { |
转发请求
1 | server { |
问题记录
invalid PID number “” in “xxx/nginx.pid”
具体原因见:https://www.liuhaolin.com/linux/134.html
解决办法:
1
2
3
4
5
6
7
8
9
10# 查看当前80端口被谁占用,已经占用者的PID
lsof -i:80
# 关闭所有占用者为nginx的进程
kill -9 [PID1、PID2、PID3……]
# 重启nginx
/home/coremail/bin/coremail restart nginx
# 校验配置是否正确(返回success)
/home/coremail/sbin/nginx -t
# 重载配置
/home/coremail/sbin/nginx -s reloadnginx的 $request_uri 无法记录#后面的内容
#
号不是HTTP协议中规定的元素,只能前端处理访问路径多个斜杆也可以正常访问
1
2
3
4
5
6
7
8
9
10
11# nginx配置
server {
listen 6001;
server_name localhost;
location / {
root /var/www/nginx;
index index.html;
autoindex on;
}
}启动nginx后,浏览器访问
http://localhost:6001/////
居然可以正常访问,如下图,暂未找到解决方案。window下无法彻底关闭nginx
window中任务管理器和命令
nginx -s stop
发现都无法关闭nginx
。目前通过taskkill命令关闭1
taskkill /f /t /im nginx.exe
参考文献
解决Nginx 400 Bad Request问题的一些思路
本文链接: http://www.ionluo.cn/blog/posts/87c539aa.html
版权声明: 本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。转载请注明出处!