Как я могу получить все заголовки запросов в Django?

107

Мне нужно получить все заголовки запросов Django. Из того, что я прочитал, Django просто выгружает все в request.METAпеременную вместе с множеством других данных. Как лучше всего получить все заголовки, которые клиент отправил моему приложению Django?

Я собираюсь использовать их для создания httplibзапроса.

Мриданг Агарвалла
источник

Ответы:

139

Согласно документации request.META , это «стандартный словарь Python, содержащий все доступные заголовки HTTP». Если вы хотите получить все заголовки, вы можете просто просмотреть словарь.

Какая часть вашего кода это делать, зависит от ваших конкретных требований. Подойдет любое место, к которому есть доступ request.

Обновить

Мне нужно получить к нему доступ в классе промежуточного программного обеспечения, но когда я повторяю его, я получаю много значений, кроме заголовков 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_'))
Манодж Говиндан
источник
Мне нужно получить к нему доступ в классе промежуточного программного обеспечения, но когда я повторяю его, я получаю много значений, кроме заголовков HTTP.
Мриданг Агарвалла 08
Спасибо, Манодж. Просто из любопытства - не могли бы вы показать мне, как я могу создать словарь заголовков, отфильтровав все ключи из request.METAпеременной, которые начинаются с a, HTTP_и вычеркнув ведущую HTTP_часть. Возможно ли это с помощью лямбда-функций? (Я думаю, что они называются лямбда-функциями). Я спрашиваю об этом, потому что, вероятно, я бы продолжил делать это долго, сначала перебирая их, затем проверяя, начинается ли оно с a, HTTP_а затем добавляю его в новый словарь. Еще раз спасибо.
Мриданг Агарвалла 08
Еще раз спасибо, Манодж. Я немного изменил его, чтобы использовать lstrip('HTTP_')вместо регулярного выражения. :)
Мриданг Агарвалла 08
3
@Mridang Agarwalla: на lstripсамом деле не будет делать то, что вы просите. lstripудалит все ведущие символы, которые соответствуют любым символам в строке, которую вы ей даете, поэтому, если у вас есть заголовок, "HTTP_TOKEN_ID"он вернется "OKEN_ID", потому что "T"в начале "TOKEN"совпадает с символом в строке, переданной в lstrip. Способ сделать это prefix = 'HTTP_'; header = header[len(prefix):].
jcdyer
2
Django 2.2 поддерживает HttpRequest.headers.
Dcalsky 01
30

Начиная с 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().

Дэниел Хеппер
источник
17

Это еще один способ сделать это, очень похожий на ответ Маноджа Говиндана выше:

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_TYPEи CONTENT_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_TYPEи CONTENT_LENGTH.

Значения каждого заголовка не должны быть изменены.

Дэйв
источник
5
Все это можно объединить в одно регулярное выражение,re.compile(r'^(HTTP_.+|CONTENT_TYPE|CONTENT_LENGTH)$')
Ребс
6

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

вы можете получить это из этого файла ...

Джеймс Варе Самуэль
источник
3

Я не думаю, что есть простой способ получить только заголовки HTTP. Вам нужно выполнить итерацию request.META dict, чтобы получить все, что вам нужно.

django-debug-toolbar использует тот же подход для отображения информации заголовка. Взгляните на этот файл, отвечающий за получение информации заголовка.

Срикантх Чунди
источник
1

Если вы хотите получить ключ клиента из заголовка запроса, вы можете попробовать следующее:

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)
Тони Азиз
источник
1

Как бы то ни было, похоже, вы намерены использовать входящий HTTP-запрос для формирования другого HTTP-запроса. Вроде как шлюз. Есть отличный модуль django-revproxy, который выполняет именно это.

Источник - довольно хороший справочник о том, как достичь того, что вы пытаетесь сделать.

abhayAndPoorvisDad
источник
0
<b>request.META</b><br>
{% for k_meta, v_meta in request.META.items %}
  <code>{{ k_meta }}</code> : {{ v_meta }} <br>
{% endfor %}
С. Ник
источник
0

Просто вы можете использовать HttpRequest.headers начиная с Django 2.2 . Следующий пример непосредственно с официального Джанго документации под объекты запроса и ответа секции.

>>> 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)
Кушан Гунасекера
источник