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
相关产品推荐
相关产品推荐

