首页 > 解决方案 > 无法使用 DRF APIClient() 更改标头

问题描述

APIClient()用于我的测试。我使用 Token auth,所以我需要使用THIS

如果我们深入研究源代码,我们将在接下来看到:

# rest_framework/test.py
class APIClient(APIRequestFactory, DjangoClient):
    def __init__(self, enforce_csrf_checks=False, **defaults):
        super().__init__(**defaults)
        self.handler = ForceAuthClientHandler(enforce_csrf_checks)
        self._credentials = {}

    def credentials(self, **kwargs):
        """
        Sets headers that will be used on every outgoing request.
        """
        self._credentials = kwarg

APIClient()还在我的代码中用作 pytest 夹具:

@pytest.fixture(scope="function")
def _api():
    """API factory for anonymous and auth requests"""

    def __api(token=None, field=None):
        api_client = APIClient()
        headers = {}

        if token:
            headers["HTTP_AUTHORIZATION"] = f"Token {token}"
        if field:
            headers["X-CUSTOM-HEADER"] = field

        api_client.credentials(**headers)

        return api_client
    return __api

但是,如果我们创建 TestMiddleware 来查找标头,我们会看到以下内容:

lass TestMiddleware:
    def __init__(self, get_response):
        self._get_response = get_response

    def __call__(self, request):
        header = request.headers.get("X-CUSTOM-HEADER") # None
        header = request.META.get("X-CUSTOM-HEADER") # Works fine!
        ...

        # Response processing
        response = self._get_response(request)

        return response

问题是:我们有什么方法可以访问X-CUSTOM-HEADERwithAPIClient()吗?另外,如果我使用 Postman,它显然可以正常工作request.headers.get()

标签: pythondjangounit-testingdjango-rest-frameworkpytest

解决方案


传递给该credentials()方法的 kwargs最终直接输入到a 的构造函数中WSGIRequest。这意味着它接受的 kwargs 不是 HTTP 标头,而是 WSGI 环境变量。并且作为 WSGI 环境变量传递的 HTTP 标头总是带有前缀HTTP_——例如,Authorization标头配置为HTTP_AUTHORIZATION. 此外,下划线用于代替破折号。

要让您的X-Custom-Header标头出现在另一侧request.headers(不是request.META,它是 WSGI 环境变量的副本),请传递HTTP_X_CUSTOM_HEADER而不是X-CUSTOM-HEADER.


推荐阅读