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

Nginx反向代理Strawberry GraphQL(Daphne)配置CORS解决Angular跨域

解决Angular 14 + Strawberry GraphQL + Nginx的CORS预检重定向问题

核心问题分析

错误提示Redirect is not allowed for a preflight request说明OPTIONS预检请求被重定向了,这是CORS失败的根本原因,而非单纯的CORS头缺失。浏览器不允许预检请求被重定向,必须直接返回200并携带正确的CORS头。


解决方案步骤

1. 修复Nginx的重定向规则

检查Nginx配置中是否存在强制HTTPS、www/非www跳转等重定向规则,确保这些规则排除OPTIONS请求:

# 示例:强制HTTPS但跳过OPTIONS请求
server {
    listen 80;
    server_name your-domain.com;

    # 仅对非OPTIONS请求执行重定向
    if ($request_method != OPTIONS) {
        return 301 https://$host$request_uri;
    }

    # 处理OPTIONS预检请求
    location /graphql {
        add_header Access-Control-Allow-Origin "$http_origin";
        add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";
        add_header Access-Control-Allow-Headers "Content-Type, Authorization";
        add_header Content-Length 0;
        add_header Content-Type text/plain;
        return 200;
    }
}

同时检查/graphql路径是否存在末尾斜杠不一致的问题(比如客户端请求/graphql,Nginx配置的是/graphql/),可通过以下规则避免自动重定向:

location ~ ^/graphql/?$ {
    # 后续配置...
}

2. 正确配置Nginx的CORS响应

在/graphql的location块中,单独处理OPTIONS预检请求,直接返回200并设置完整CORS头,同时确保正常请求也携带CORS头:

server {
    listen 443 ssl http2;
    server_name your-domain.com;
    # SSL证书配置...

    upstream backend {
        server 127.0.0.1:8000; # Daphne运行的地址
    }

    location /graphql {
        # 优先处理OPTIONS预检请求
        if ($request_method = OPTIONS) {
            add_header Access-Control-Allow-Origin "$http_origin" always;
            add_header Access-Control-Allow-Methods "GET, POST, OPTIONS" always;
            add_header Access-Control-Allow-Headers "Content-Type, Authorization, X-Requested-With" always;
            add_header Access-Control-Max-Age 3600 always;
            add_header Content-Length 0;
            add_header Content-Type text/plain;
            return 200;
        }

        # 给正常请求添加CORS头
        add_header Access-Control-Allow-Origin "$http_origin" always;
        add_header Access-Control-Allow-Credentials "true" always;

        # 反向代理到Daphne
        proxy_pass http://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;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
  • 用$http_origin动态匹配请求来源,若需限制特定域名,可替换为if ($http_origin ~* ^https://your-client-domain\.com$)
  • always关键字确保即使后端返回错误响应,CORS头也会被携带

3. 调整后端CORS中间件配置

如果Nginx已经处理了CORS,建议关闭Starlette的CORS中间件,避免重复设置CORS头导致浏览器报错。若需保留后端配置,确保规则和Nginx一致:

from starlette.middleware.cors import CORSMiddleware
from strawberry.asgi import GraphQL

# 你的Strawberry Schema定义
schema = ...

app = GraphQL(schema)

# 仅在Nginx未处理CORS时启用
app.add_middleware(
    CORSMiddleware,
    allow_origins=["https://your-client-domain.com"],
    allow_credentials=True,
    allow_methods=["GET", "POST", "OPTIONS"],
    allow_headers=["Content-Type", "Authorization"],
)

4. 验证预检请求

用curl测试OPTIONS请求,确认无重定向且CORS头正确:

curl -X OPTIONS https://your-server-domain/graphql \
-H "Origin: https://your-client-domain" \
-I

预期响应:

  • 状态码为200 OK
  • 包含Access-Control-Allow-Origin等CORS头
  • 无Location重定向头

5. Angular客户端配置检查

确保GraphQL客户端(如Apollo)的请求配置正确:

import { ApolloClient, InMemoryCache, createHttpLink } from '@apollo/client/core';

const httpLink = createHttpLink({
  uri: 'https://your-server-domain/graphql',
  credentials: 'include', // 若需携带Cookie
});

export const apolloClient = new ApolloClient({
  link: httpLink,
  cache: new InMemoryCache(),
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 17:01:18