You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

远程服务器测试应用时HTTP请求报405错误的排查与Nginx配置

预发布环境POST请求返回405错误,本地正常的排查与解决

我正在排查预发布(staging)环境中发送HTTP POST请求到/connect/token时出现405错误的问题,但本地相同场景下请求返回200。


相关配置与代码

proxy.conf.json(本地代理配置)

{
  "/connect/*": {
    "target": "http://portal.test.com/backend",
    "secure": false,
    "logLevel": "debug",
    "changeOrigin": true
  }
}

login.service.ts(前端请求代码)

@Injectable({
  providedIn: 'root',
})
export class LoginService {
  private readonly ENDPOINT = '/connect/token';

  constructor(private readonly httpClient: HttpClient) {}

  login(credentials: CredentialsModel): Observable<SuccessfulLoginModel> {
    const { username, password } = credentials;
    const body = new URLSearchParams();
    body.set('grant_type', 'password');
    body.set('username', username);
    body.set('password', password);
    body.set('scope', 'offline_access openid profile');
    const options = this.getHTTPOptions();

    return this.httpClient.post<any>(this.ENDPOINT, body.toString(), options);
  }

  refreshToken(token: string): Observable<SuccessfulLoginModel> {
    // ...
  }

  private getHTTPOptions() {
    return {
      headers: new HttpHeaders()
        .set('Content-Type', 'application/x-www-form-urlencoded')
        .set(
          'Authorization',
          'Basic ' +
            btoa(`${environment.client_id}:${environment.client_secret}`)
        ),
    };
  }
}

请求响应对比

本地调用/connect/token的响应

HTTP/1.1 200 OK
x-powered-by: OrchardCore
Access-Control-Allow-Origin: *
server: nginx/1.23.1
date: Sun, 13 Nov 2022 01:46:27 GMT
content-type: application/json;charset=UTF-8
content-length: 12337
cache-control: no-store
expires: Thu, 01 Jan 1970 00:00:00 GMT
pragma: no-cache
set-cookie: .AspNetCore.Mvc.CookieTempDataProvider=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/backend; samesite=lax; httponly
x-content-type-options: nosniff
referrer-policy: no-referrer
connection: close

预发布环境调用/connect/token的响应

HTTP/1.1 405 Not Allowed
server: nginx/1.23.1
date: Sun, 13 Nov 2022 01:48:19 GMT
content-type: text/html
content-length: 157

更新1:远程服务器复现问题

我在远程服务器用Docker部署Nginx实例复现了该问题,启动命令如下:

docker run --name habanos -v /home/mario/projects/spa/dist/app-name:/usr/share/nginx/html/:ro -d -p 8080:80 nginx:latest

按照Angular前端控制器模式配置了Nginx:

try_files $uri $uri/ /index.html;

该配置让应用可以正常访问,但POST请求仍返回405错误。添加error_page 405 =200 $uri;后状态码变为200,但返回的是HTML内容而非预期的接口响应。请问如何正确配置Nginx处理POST请求?


问题原因与解决方法

核心原因

预发布环境的Nginx没有配置反向代理规则,导致/connect/token的POST请求被Nginx当作静态资源处理——静态资源默认不支持POST方法,因此返回405错误。本地环境依赖proxy.conf.json的代理配置将请求转发到后端,但预发布环境的Nginx没有同步这个规则。

另外,error_page 405 =200 $uri;只是强制修改状态码,并没有真正转发请求,所以返回的是index.html内容。

正确的Nginx配置方案

需要在Nginx配置中添加针对/connect/*的反向代理规则,同时保留前端路由的fallback配置。修改后的Nginx配置示例如下:

server {
    listen 80;
    root /usr/share/nginx/html;
    index index.html;

    # 代理所有/connect开头的请求到后端服务
    location /connect/ {
        proxy_pass http://portal.test.com/backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        # 兼容POST等请求方法
        proxy_http_version 1.1;
        proxy_set_header Connection "";
    }

    # 处理前端路由的fallback
    location / {
        try_files $uri $uri/ /index.html;
    }
}

配置说明

  1. 反向代理规则:通过location /connect/匹配所有以/connect/开头的请求,转发到后端服务,同时设置必要请求头保证后端能正确识别请求来源。
  2. 前端路由兼容:location /中的try_files配置保留了Angular单页应用的路由规则,确保页面刷新、直接访问路由等场景正常工作。
  3. 方法支持:proxy_http_version 1.1和proxy_set_header Connection ""避免长连接相关问题,确保POST等方法能被正确转发。

验证步骤

  1. 将上述配置替换Docker容器内的Nginx默认配置(路径:/etc/nginx/conf.d/default.conf)。
  2. 重启Nginx容器:docker restart habanos。
  3. 测试POST请求到/connect/token,确认返回200并获取正确的JSON响应。

内容的提问来源于stack exchange,提问作者Mario

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 09:01:44