一、问题背景

在测试web应用的时候,前端需要进行跨域访问后端接口,由于服务端跨域访问功能不完善,所以打算通过反向代理临时解决跨域问题,但是反向代理配置成功后,访问时浏览器端返回404,在nginx的访问日志中也提示404,Nginx配置如下。

1.1 Nginx反向代理配置

server {
    listen     80;
    server_name h5-verify.mpoom.cn;
    location / {
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        proxy_pass http://127.0.0.1:8000;
    }
}

server {
    listen       8000;
    server_name  127.0.0.1 localhost;

    set $root_path "/home/ytx/jiyan-h5";

    #charset koi8-r;

    location / {
        root   $root_path;
        index  index.html index.htm;
        try_files $uri $uri/ /index.html;
    }

    location /ytx-api/ {
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        proxy_buffering off;
        proxy_connect_timeout 300s;
        proxy_send_timeout 300s;
        proxy_read_timeout 300s;
        client_max_body_size 100M;

        proxy_pass  https://www.139130.com;
    }
}

1.2 浏览器请求及响应

(1)headers

General

Request URL: http://h5-verify.mpoom.cn/ytx-api/v1.0.0/phone/carrier-info
Request Method: GET
Status Code: 404 Not Found
Remote Address: 106.54.197.193:80
Referrer Policy: no-referrer-when-downgrade

Response Headers

Connection: keep-alive
Content-Length: 315
Content-Type: text/html; charset=iso-8859-1
Date: Mon, 13 Jul 2020 09:24:37 GMT
Server: nginx/1.9.9

Request Headers

Accept: /
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cache-Control: no-cache
Connection: keep-alive
Content-Type: application/json;charset=UTF-8
Host: h5-verify.mpoom.cn
Pragma: no-cache
Referer: http://h5-verify.mpoom.cn/phone-verify
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36

(2)preview

Not Found
The requested URL /ytx-api/v1.0.0/phone/carrier-info was not found on this server.

Apache/2.2.15 (CentOS) Server at h5-verify.mpoom.cn Port 80

1.3 Nginx access.log日志

127.0.0.1 - - [13/Jul/2020:17:32:33 +0800] "GET /ytx-api/v1.0.0/phone/carrier-info HTTP/1.0" 404 315 "http://h5-verify.mpoom.cn/phone-verify" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36" "183.238.58.120"

二、问题原因

在服务器上有类似反向代理配置,但都是可以正常访问的,唯一与上述配置有区别的是,能正常访问的被反向代理的应用和Nginx部署在同一台机器,而上述被反向代理的应用部署在一台公网服务器。
该问的主要原因在于配置反向代理时proxy_set_header Host的配置.

2.1 Host定义

Host 请求头指明了请求将要发送到的服务器主机名和端口号。
组成:域名+端口号
例子:test.com:1998
如果没有包含端口号,会自动使用被请求服务的默认端口(比如HTTPS URL使用443端口,HTTP URL使用80端口)
所有HTTP/1.1 请求报文中必须包含一个Host头字段。对于缺少Host头或者含有超过一个Host头的HTTP/1.1 请求,可能会收到400(Bad Request)状态码。

http1.1中不能缺失host字段,但host字段可以是空值
上述问题是由于web前端使用二级域名h5-verify.mpoom.cn去访问,被反向代理的应用接口部署在另外一台服务器并且使用了www.139130.com域名进行访问,上述反向代理配置将Host设置为了h5-verify.mpoom.cn,去访问远程应用接口时服务器时无法解析h5-verify.mpoom.cn返回404。

三、解决方案

(1)解决方法一
修改反向代理中的Host配置

proxy_set_header Host "www.139130.com";

(2)解决方法二
注释掉nginx配置文件中的Host配置

参考文章:

https://zh.wikipedia.org/zh-hans/HTTP%E5%A4%B4%E5%AD%97%E6%AE%B5
https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.23
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Host