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

Django REST Framework自定义X-API-Version头触发CORS错误

自定义请求头X-API-Version引发CORS错误的解决方法

问题背景

尝试通过自定义请求头X-API-Version校验前端版本,但配置django-cors-headers后仍触发CORS错误,错误信息如下:

Access to XMLHttpRequest at 'http://192.168.5.39:8001/api/host/login/'
from origin 'http://localhost:9000' has been blocked by CORS policy:
Request header field x-api-version is not allowed by Access-Control-Allow-Headers
in preflight response.

已完成以下配置但无效:

  • 安装并注册django-cors-headers到INSTALLED_APPS
  • 中间件中添加corsheaders.middleware.CorsMiddleware和django.middleware.common.CommonMiddleware
  • 将x-api-version加入CORS_ALLOW_HEADERS
  • 设置CORS_ORIGIN_ALLOW_ALL = True

核心问题分析

从提供的配置文件看,两个关键问题导致了错误:

  1. 中间件顺序错误:corsheaders.middleware.CorsMiddleware必须放在所有其他中间件之前,否则自定义中间件会在CORS预检校验前拦截请求,导致响应头中未包含允许的自定义头。
  2. 版本校验中间件未跳过预检请求:OPTIONS预检请求未被版本校验逻辑跳过,直接返回401,导致CORS校验失败。
  3. 中间件初始化方法语法错误:原VersionAPIMiddleware中的_init_和_call_是单下划线,不符合Python类特殊方法的双下划线规范,导致中间件无法正常工作。

解决方案

1. 调整中间件顺序

修改MIDDLEWARE列表,将CORS中间件移至最顶部,确保它优先处理所有请求:

MIDDLEWARE = [
    'corsheaders.middleware.CorsMiddleware',  # 优先处理CORS逻辑
    'django.middleware.common.CommonMiddleware',
    'api.middleware.VersionAPIMiddleware',
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

2. 修复版本校验中间件

修改VersionAPIMiddleware,修复语法错误并跳过OPTIONS预检请求:

from nome_api.settings import VERSION
from django.http import JsonResponse

class VersionAPIMiddleware:
    def __init__(self, get_response):  # 修正为双下划线的特殊方法
        self.get_response = get_response

    def __call__(self, request):  # 修正为双下划线的特殊方法
        # 跳过OPTIONS预检请求,让CORS中间件处理
        if request.method == 'OPTIONS':
            return self.get_response(request)

        ver_request = int(request.META.get('HTTP_X_API_VERSION', 0))

        # 加载swagger和admin页面时跳过校验
        if len(request.path) == 1 or '/admin/' in request.path or '/swagger/' in request.path:
            response = self.get_response(request)
            return response

        # 校验API版本
        if ver_request == VERSION:
            response = self.get_response(request)
            return response
        else:
            # swagger请求跳过校验
            if 'HTTP_X_CSRFTOKEN' in request.META:
                response = self.get_response(request)
                return response
            else:
                return JsonResponse({'msg': 'favor atualizar o aplicativo'}, status=401)

3. 简化CORS_ALLOW_HEADERS配置

只需要添加小写的x-api-version即可,无需重复添加不同格式的版本:

from corsheaders.defaults import default_headers

CORS_ALLOWED_HEADERS = list(default_headers) + ['x-api-version']

验证步骤

  1. 重启Django服务
  2. 发送带X-API-Version头的请求,检查是否仍有CORS错误
  3. 查看OPTIONS预检请求的响应头,确认Access-Control-Allow-Headers中包含x-api-version

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 16:37:52