一、项目基础路径相关配置导致转发404
经常我们可以碰到的转发无非是nginx转发到前端项目,nginx转发到后端项目两种情况。
1.1、后端项目
比如java项目为例,server.servlet.context-path定义了应用的上下文路径,它是构成url地址的一部分,一般在配置文件中定义。
不配置时,默认为/,如:localhost:8080/xxxxxx;
当server.servlet.context-path有配置时,比如 /demo,此时的访问方式为localhost:8080/demo/xxxxxx
1.2、前端项目
例:vue.config.js文件
const config = {
publicPath: '',
outputDir:'dist/api/doc/rmn/',
productionSourceMap: false,
};
module.exports = config;
outputDir官网描述为设置项目打包生成的文件的存储目录,可以是静态路径也可以是相对路径。如果将outputDir设置为 dist/api/doc/rmn/ ,则执行完npm run build后,生成的包存放在dist/api/doc/rmn/ 下面。也就是说项目入口文件存放在rmn目录下。
介绍了上面两种基础路径情况,下面来说,nginx转发到项目时,会造成404的情况。
通常我们使用类似下面的配置来转发到其他项目,这个时候不管基础路径是否配置,都可以转发到项目。
location /api {
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_pass http://sandbox.rop.pro;
}
如果我们使用如下多级路径转发,那么就会造成404的情况,这个时候我们就需要将java项目的基础路径server.servlet.context-path配置为/api/rts,对于前端项目则需要修改outputDir:’dist/api/rts’,才能转发到目标项目。
location /api/rts {
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_pass http://sandbox.rop.pro;
}
二、alias 和root使用不当引起404
server {
listen 80;
server_name abc.huawei.com
location /test {
root /data/rts/;
index aa.html aa.htm;
}
}
静态网站资源index.html,aa.html放置于/data/rts/目录下,当我们使用abc.huawei.com/test/访问项目的时候就会出现404的情况。
nginx的官方手册中例子
若用alias的话,则访问127.0.0.1/img/目录里面的文件时,ningx会自去/var/www/image/目录找文件
location /img/ { alias /var/www/image/; }
若用root的话,则访问/127.0.0.1/img/目录下的文件时,nginx会自动去/var/www/image/img/目录下找文件
location /img/ { root /var/www/image; }
因此为了正确访问项目,我们可以在/data/rts目录下创建test文件,并且将静态资源放置于test文件里。
三、转发过程中斜线“/”引起的404
在Nginx location通用匹配规则中配置proxy_pass转发时,假设有如下location配置:
location /test {
proxy_pass http://localhost:8080/test;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Forwarded-Proto "https";
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Real-IP $remote_addr;
}
如果我请求 http://localhost/test/detect,则会将url根据匹配规则“/test”截取,然后将“/test”后面的内容(此处为“/detect”)拼接到proxy_pass的后面,然后转发,也就是最后实际请求地址为:proxy_pass http://localhost:8080/test/detect。
所以,如果location的匹配规则最后不加斜线’/‘,则proxy_pass的最后也不要加斜线,或者都加上斜线,不然就不能正确访问实际地址,导致404 not found错误。