Nginx location匹配规则
url匹配规则
location [=|~|~*|^~|@] /uri/ {
...
}
- = : 表示精确匹配后面的url
- ~ : 表示正则匹配,但是区分大小写
- ~* : 正则匹配,不区分大小写
- ^~ : 表示普通字符匹配,如果该选项匹配,只匹配该选项,不匹配别的选项,一般用来匹配目录
- @ : "@" 定义一个命名的 location,使用在内部定向时,例如 error_page
上述匹配规则的优先匹配顺序:
- = 前缀的指令严格匹配这个查询。如果找到,停止搜索;
- 所有剩下的常规字符串,最长的匹配。如果这个匹配使用 ^~ 前缀,搜索停止;
- 正则表达式,在配置文件中定义的顺序;
- 如果第 3 条规则产生匹配的话,结果被使用。否则,使用第 2 条规则的结果。
目标地址处理规则
匹配到uri后,接下来要代理到目标服务地址。
upstream api_server {
server 10.0.101.62:8081;
server 10.0.101.61:8082;
}
location / {
rewrite ^(.*)$ http://10.0.101.62:8000/my-module$1 break;
}
location ^~ /my-module/ {
root /data/my-module/dist;
rewrite ^/my-module/(.*)$ /$1 break;
index index.html index.htm;
}
location /my-module/api {
proxy_pass http://api_server;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header your-custome-header "myHeader";
proxy_set_header X-NginX-Proxy true;
}
上述配置,默认访问/
会重定向到/my-module
, 然后直接返回/data/my-module/dist
下的html等静态文件。
访问/my-module/api
则会代理到我们api服务器地址,是一个默认的round-robin负载均衡配置。
下面是访问localhost的日志, 访问首页一共进行了2次重定向。
Request URL: http://10.0.101.62:8000/
Request Method: GET
Status Code: 302 Moved Temporarily
Location: http://10.0.101.62:8000/flash/
Request URL: http://10.0.101.62:8000/flash/
Request Method: GET
Status Code: 302 Moved Temporarily
Location: http://10.0.101.62:8000/flash/index.html
Request URL: http://10.0.101.62:8000/flash/index.html
Request Method: GET
Status Code: 304 Not Modified
alias与root的区别
root 实际访问文件路径会拼接URL中的路径 alias 实际访问文件路径不会拼接URL中的路径
示例如下:
location ^~ /sta/ {
alias /usr/local/nginx/html/static/;
}
请求:http://test.com/sta/sta1.html
实际访问:/usr/local/nginx/html/static/sta1.html
文件
location ^~ /tea/ {
root /usr/local/nginx/html/;
}
请求:http://test.com/tea/tea1.html
实际访问:/usr/local/nginx/html/tea/tea1.html
文件
显然,第二次重定向是不需要的,本意是访问/flash/的时候,直接访问对应目录下的html静态文件。 但因为root拼接flash导致找不到对应文件,要重写url,去掉flash这个模块前缀,使用了rewrite
, 而rewrite
会返回302重定向。
接下来,我们修改root
为alias
location ^~ /flash/ {
alias /data/flash/dist/;
#rewrite ^/flash/(.*)$ /$1 break;
index index.html index.htm;
}
直接重定向1次后返回html
Request URL: http://10.0.101.62:8000/
Request Method: GET
Status Code: 302 Moved Temporarily
Request URL: http://10.0.101.62:8000/flash/
Request Method: GET
Status Code: 200 OK (from disk cache)
last 和 break关键字的区别
只用到了break,即匹配到此处后不会继续跳。
permanent 和 redirect关键字的区别
- rewrite … permanent 永久性重定向,请求日志中的状态码为301
- rewrite … redirect 临时重定向,请求日志中的状态码为302
我们常用的80端口转443,即http转https的一种配置方案为:
server {
listen 80;
server_name demo.com;
rewrite ^(.*)$ https://${server_name}$1 permanent;
}
会返回301永久重定向到对应的https:
Request URL: http://demo.com/flash/index.html
Request Method: GET
Status Code: 301 Moved Permanently
Location: https://demo/flash/index.html
一些使用场景
上述demo差不多就是我平时用的前后端分离的代理配置方案。下面是一些遇到过的场景。
配置一个静态文件下载服务,我们下面软件会经常看到index /的页面。
server {
listen 8888; #端口
server_name _; #服务名
charset utf-8,gbk;
root /data/download; #显示的根索引目录
autoindex on; #开启索引功能
autoindex_exact_size off; # 关闭计算文件确切大小(单位bytes),只显示大概大小(单位kb、mb、gb)
autoindex_localtime on; # 显示本机时间而非 GMT 时间
}
配置http重定向到https
server {
listen 80;
server_name demo.com;
rewrite ^(.*)$ https://${server_name}$1 permanent;
}
server {
listen 443;
server_name demo.com;
charset utf-8;
location / {
alias /data/web;
index index.html index.htm;
}
}
配置静态前端页面
location / {
alias /data/web;
index index.html index.htm;
}
配置反向代理, 比如我们访问http://demo.com/api/aaa/bbb,我们想要代理到http://api.com/api/aaa/bbb, 只切换了域名,uri相同。
upstream api_server {
server 10.0.101.62:8081;
server 10.0.101.61:8082;
}
location /api {
proxy_pass http://api_server;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header your-custome-header "myHeader";
proxy_set_header X-NginX-Proxy true;
}
配置反向代理时,移除前缀。比如我们的服务http://demo.com/users/aaa/bbb, 我们想要代理到http://users.com/aaa/bbb,即切换域名的同时,去掉users前缀。区别是解为的/
.
location ^~/users/ {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://users.com/;
}
反向代理时,想要自定义修改uri。使用rewrite正则修改。
# 修改uri,去掉了flash的前缀,$1表示正则匹配到的字符串内容。
location ^~ /flash/ {
root /data/flash/dist/;
rewrite ^/flash/(.*)$ /$1 break;
index index.html index.htm;
}
# 修改uri, 重新代理到新的地址
location ^~/order/ {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-NginX-Proxy true;
rewrite ^/order/(.*)$ /$1 break;
proxy_pass http://order;
}
代理跨域, 比如bing每日一图,不支持我们ajax获取图片地址,我们可以自己写一个支持的接口。
http://101.200.218.760/proxy/bing/HPImageArchive.aspx?format=js&idx=0&n=1
代理对象为: https://cn.bing.com/HPImageArchive.aspx?format=js&idx=0&n=1
location ^~/proxy/bing/ {
add_header 'Access-Control-Allow-Origin' 'http://localhost:8088';
add_header 'Cache-Control' 'public, max-age=604800';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
rewrite ^/proxy/bing/(.*)$ /$1 break;
proxy_pass https://cn.bing.com/;
}
- (50) 剖析EnumMap / 计算机程序的思维逻辑
- 认识九大经典sql模式
- 构建一个pip安装的车辆路径显示的Python包
- 如何编写复杂sql
- Python机器学习工具:Scikit-Learn介绍与实践
- (51) 剖析EnumSet / 计算机程序的思维逻辑
- mysql性能优化的几条重要建议
- Python爬虫抓取知乎所有用户信息
- Eclipse远程调试出现“JDWP Transport dt_socket failed to initialize”的解决方案
- Django 博客教程:前言和环境安装(连载一)
- (52) 抽象容器类 / 计算机程序的思维逻辑
- mysql的查询、子查询及连接查询
- 简陋的分布式爬虫(附项目代码地址)
- 使用PowerShell简化我的工作
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- laravel 使用事件系统统计浏览量的实现
- PHP之多条件混合筛选功能的实现方法
- PHP多进程简单实例小结
- 解决laravel5中auth用户登录其他页面获取不到登录信息的问题
- Yii框架学习笔记之应用组件操作示例
- laravel 之 Eloquent 模型修改器和序列化示例
- TP5框架请求响应参数实例分析
- laravel 模型查询按照whereIn排序的示例
- 解决在laravel中auth建立时候遇到的问题
- php array 转json及java 转换 json数据格式操作示例
- Thinkphp5 如何隐藏入口文件index.php(URL重写)
- 在Laravel中使用GuzzleHttp调用第三方服务的API接口代码
- thinkphp5使html5实现动态跳转的例子
- php 自定义函数实现将数据 以excel 表格形式导出示例
- 解决tp5在nginx下修改配置访问的问题