如何在Django中获取所有请求标头?

问题:如何在Django中获取所有请求标头?

我需要获取所有Django请求标头。根据我的阅读,Django只是将所有内容request.META与大量其他数据一起转储到变量中。获取客户端发送到我的Django应用程序的所有标头的最佳方法是什么?

我将使用这些来构建httplib请求。

I need to get all the Django request headers. From what i’ve read, Django simply dumps everything into the request.META variable along with a lot aof other data. What would be the best way to get all the headers that the client sent to my Django application?

I’m going use these to build a httplib request.


回答 0

根据文档,这 request.META是“包含所有可用HTTP标头的标准Python词典”。如果要获取所有标头,则可以简单地遍历字典。

代码的哪一部分执行此操作取决于您的确切要求。有权访问的任何地方都request应该这样做。

更新资料

我需要在Middleware类中访问它,但是当我对其进行迭代时,除了HTTP标头之外,我还获得了很多其他值。

从文档中:

除了CONTENT_LENGTH和之外CONTENT_TYPE,如上所述,通过将所有字符HTTP都转换META为大写字母,用下划线替换所有连字符并将名称添加HTTP_前缀,将请求中的所有标头都转换为键。

(添加了强调)

HTTP单独获取标题,只需按前缀为的键进行过滤HTTP_

更新2

您能否告诉我如何通过从request.META变量中滤除所有以HTTP_开头并除去开头的HTTP_部分的键来构建标头字典。

当然。这是一种方法。

import re
regex = re.compile('^HTTP_')
dict((regex.sub('', header), value) for (header, value) 
       in request.META.items() if header.startswith('HTTP_'))

According to the documentation request.META is a “standard Python dictionary containing all available HTTP headers”. If you want to get all the headers you can simply iterate through the dictionary.

Which part of your code to do this depends on your exact requirement. Anyplace that has access to request should do.

Update

I need to access it in a Middleware class but when i iterate over it, I get a lot of values apart from HTTP headers.

From the documentation:

With the exception of CONTENT_LENGTH and CONTENT_TYPE, as given above, any HTTP headers in the request are converted to META keys by converting all characters to uppercase, replacing any hyphens with underscores and adding an HTTP_ prefix to the name.

(Emphasis added)

To get the HTTP headers alone, just filter by keys prefixed with HTTP_.

Update 2

could you show me how I could build a dictionary of headers by filtering out all the keys from the request.META variable which begin with a HTTP_ and strip out the leading HTTP_ part.

Sure. Here is one way to do it.

import re
regex = re.compile('^HTTP_')
dict((regex.sub('', header), value) for (header, value) 
       in request.META.items() if header.startswith('HTTP_'))

回答 1

从Django 2.2开始,您可以使用request.headers访问HTTP标头。从HttpRequest.headers文档中

不区分大小写,类似于dict的对象,该对象提供对请求中所有HTTP前缀的标头(加上Content-Length和Content-Type)的访问。

每个标题的名称在显示时都带有标题框(例如User-Agent)。您可以不区分大小写地访问标头:

>>> request.headers
{'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6', ...}

>>> 'User-Agent' in request.headers
True
>>> 'user-agent' in request.headers
True

>>> request.headers['User-Agent']
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6)
>>> request.headers['user-agent']
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6)

>>> request.headers.get('User-Agent')
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6)
>>> request.headers.get('user-agent')
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6)

要获取所有标题,可以使用request.headers.keys()request.headers.items()

Starting from Django 2.2, you can use request.headers to access the HTTP headers. From the documentation on HttpRequest.headers:

A case insensitive, dict-like object that provides access to all HTTP-prefixed headers (plus Content-Length and Content-Type) from the request.

The name of each header is stylized with title-casing (e.g. User-Agent) when it’s displayed. You can access headers case-insensitively:

>>> request.headers
{'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6', ...}

>>> 'User-Agent' in request.headers
True
>>> 'user-agent' in request.headers
True

>>> request.headers['User-Agent']
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6)
>>> request.headers['user-agent']
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6)

>>> request.headers.get('User-Agent')
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6)
>>> request.headers.get('user-agent')
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6)

To get all headers, you can use request.headers.keys() or request.headers.items().


回答 2

这是另一种实现方法,与上面的Manoj Govindan的答案非常相似:

import re
regex_http_          = re.compile(r'^HTTP_.+$')
regex_content_type   = re.compile(r'^CONTENT_TYPE$')
regex_content_length = re.compile(r'^CONTENT_LENGTH$')

request_headers = {}
for header in request.META:
    if regex_http_.match(header) or regex_content_type.match(header) or regex_content_length.match(header):
        request_headers[header] = request.META[header]

这还将抓取CONTENT_TYPECONTENT_LENGTH请求标头以及HTTP_那些标头。request_headers['some_key]== request.META['some_key']

如果需要包括/省略某些标题,请进行相应的修改。Django在这里列出了一堆,但不是全部:https : //docs.djangoproject.com/en/dev/ref/request-response/#django.http.HttpRequest.META

Django请求标头的算法:

  1. -用下划线替换连字符_
  2. 转换为大写。
  3. 前置HTTP_到原请求的所有头,除了CONTENT_TYPECONTENT_LENGTH

每个标头的值都应保持不变。

This is another way to do it, very similar to Manoj Govindan‘s answer above:

import re
regex_http_          = re.compile(r'^HTTP_.+$')
regex_content_type   = re.compile(r'^CONTENT_TYPE$')
regex_content_length = re.compile(r'^CONTENT_LENGTH$')

request_headers = {}
for header in request.META:
    if regex_http_.match(header) or regex_content_type.match(header) or regex_content_length.match(header):
        request_headers[header] = request.META[header]

That will also grab the CONTENT_TYPE and CONTENT_LENGTH request headers, along with the HTTP_ ones. request_headers['some_key] == request.META['some_key'].

Modify accordingly if you need to include/omit certain headers. Django lists a bunch, but not all, of them here: https://docs.djangoproject.com/en/dev/ref/request-response/#django.http.HttpRequest.META

Django’s algorithm for request headers:

  1. Replace hyphen - with underscore _
  2. Convert to UPPERCASE.
  3. Prepend HTTP_ to all headers in original request, except for CONTENT_TYPE and CONTENT_LENGTH.

The values of each header should be unmodified.


回答 3

request.META.get(’HTTP_AUTHORIZATION’) /python3.6/site-packages/rest_framework/authentication.py

你可以从这个文件中得到…

request.META.get(‘HTTP_AUTHORIZATION’) /python3.6/site-packages/rest_framework/authentication.py

you can get that from this file though…


回答 4

我认为没有简单的方法可以仅获取HTTP标头。您必须遍历request.META字典以获得所需的所有内容。

django-debug-toolbar采用相同的方法显示标题信息。看一下负责检索头信息的文件

I don’t think there is any easy way to get only HTTP headers. You have to iterate through request.META dict to get what all you need.

django-debug-toolbar takes the same approach to show header information. Have a look at this file responsible for retrieving header information.


回答 5

如果要从请求标头获取客户端密钥,则可以尝试以下操作:

from rest_framework.authentication import BaseAuthentication
from rest_framework import exceptions
from apps.authentication.models import CerebroAuth

class CerebroAuthentication(BaseAuthentication):
def authenticate(self, request):
    client_id = request.META.get('HTTP_AUTHORIZATION')
    if not client_id:
        raise exceptions.AuthenticationFailed('Client key not provided')
    client_id = client_id.split()
    if len(client_id) == 1 or len(client_id) > 2:
        msg = ('Invalid secrer key header. No credentials provided.')
        raise exceptions.AuthenticationFailed(msg)
    try:
        client = CerebroAuth.objects.get(client_id=client_id[1])
    except CerebroAuth.DoesNotExist:
        raise exceptions.AuthenticationFailed('No such client')
    return (client, None)

If you want to get client key from request header, u can try following:

from rest_framework.authentication import BaseAuthentication
from rest_framework import exceptions
from apps.authentication.models import CerebroAuth

class CerebroAuthentication(BaseAuthentication):
def authenticate(self, request):
    client_id = request.META.get('HTTP_AUTHORIZATION')
    if not client_id:
        raise exceptions.AuthenticationFailed('Client key not provided')
    client_id = client_id.split()
    if len(client_id) == 1 or len(client_id) > 2:
        msg = ('Invalid secrer key header. No credentials provided.')
        raise exceptions.AuthenticationFailed(msg)
    try:
        client = CerebroAuth.objects.get(client_id=client_id[1])
    except CerebroAuth.DoesNotExist:
        raise exceptions.AuthenticationFailed('No such client')
    return (client, None)

回答 6

对于它的价值,看来您的意图是使用传入的HTTP请求来形成另一个HTTP请求。有点像网关。有一个出色的模块django-revproxy可以完成此任务。

资料来源很好地参考了如何完成您想做的事情。

For what it’s worth, it appears your intent is to use the incoming HTTP request to form another HTTP request. Sort of like a gateway. There is an excellent module django-revproxy that accomplishes exactly this.

The source is a pretty good reference on how to accomplish what you are trying to do.


回答 7

<b>request.META</b><br>
{% for k_meta, v_meta in request.META.items %}
  <code>{{ k_meta }}</code> : {{ v_meta }} <br>
{% endfor %}
<b>request.META</b><br>
{% for k_meta, v_meta in request.META.items %}
  <code>{{ k_meta }}</code> : {{ v_meta }} <br>
{% endfor %}

回答 8

只需从Django 2.2开始使用HttpRequest.headers。以下示例直接取自Django官方文档的请求和响应对象”部分。

>>> request.headers
{'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6', ...}

>>> 'User-Agent' in request.headers
True
>>> 'user-agent' in request.headers
True

>>> request.headers['User-Agent']
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6)
>>> request.headers['user-agent']
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6)

>>> request.headers.get('User-Agent')
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6)
>>> request.headers.get('user-agent')
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6)

Simply you can use HttpRequest.headers from Django 2.2 onward. Following example is directly taken from the official Django Documentation under Request and response objects section.

>>> request.headers
{'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6', ...}

>>> 'User-Agent' in request.headers
True
>>> 'user-agent' in request.headers
True

>>> request.headers['User-Agent']
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6)
>>> request.headers['user-agent']
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6)

>>> request.headers.get('User-Agent')
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6)
>>> request.headers.get('user-agent')
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6)