Як я можу отримати всі заголовки запитів у Django?


107

Мені потрібно отримати всі заголовки запиту Django. З того, що я прочитав, Джанго просто скидає все наrequest.META змінну разом з великою кількістю інших даних. Що було б найкращим способом отримати всі заголовки, які клієнт надіслав до моєї програми Django?

Я буду використовувати їх для створення httplibзапиту.

Відповіді:


139

Згідно з документацією request.META , це "стандартний словник Python, що містить усі доступні заголовки HTTP". Якщо ви хочете отримати всі заголовки, ви можете просто перебрати його через словник.

Яка частина вашого коду для цього залежить від вашої точної вимоги. Будь-який, хто має доступ, 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_'))

Мені потрібно отримати доступ до класу Middleware, але коли я перебираю його, я отримую багато значень, крім заголовків HTTP.
Mridang Agarwalla

Дякую Маной. Лише з цікавості - чи не могли б ви показати мені, як я можу скласти словник заголовків, відфільтрувавши всі клавіші зі request.METAзмінної, які починаються з а, HTTP_і викресліть провідну HTTP_частину. Це можливо через функції лямбда? (Я думаю, що вони називаються лямбда-функціями) Я запитую це, тому що, ймовірно, я б продовжував це робити довгим шляхом, спочатку повторюючи їх, потім перевіряючи, чи не починається він з, HTTP_а потім додаючи його до нового словника. Знову дякую.
Mridang Agarwalla

Ще раз дякую Маной. Я трохи змінив його, щоб використовувати lstrip('HTTP_')замість регулярного виразу. :)
Mridang Agarwalla

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.
Дкальський

30

Починаючи з Django 2.2, ви можете використовувати request.headersдля доступу до заголовків HTTP. З документації на HttpRequest.headers :

Нечутливий до регістру об'єкт, схожий на малюнок, що забезпечує доступ до всіх заголовків із попередньою приставкою HTTP (плюс довжина вмісту та тип вмісту) із запиту.

Ім'я кожного заголовка стилізується під заголовком (наприклад, 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'].

Змініть відповідно, якщо вам потрібно включити / пропустити певні заголовки. Джанго перераховує купу, але не всіх, тут: https://docs.djangoproject.com/en/dev/ref/request-response/#django.http.HttpRequest.META

Алгоритм Джанго для заголовків запитів:

  1. Замініть дефіс -на підкреслення_
  2. Перетворити на ПОВЕРНЕННЯ.
  3. Додайте HTTP_всі заголовки в оригінальному запиті, крім CONTENT_TYPEі CONTENT_LENGTH.

Значення кожного заголовка повинні бути немодифікованими.


5
Це все можна об'єднати в єдиний регулярний вираз,re.compile(r'^(HTTP_.+|CONTENT_TYPE|CONTENT_LENGTH)$')
Rebs


3

Я не думаю, що існує легкий спосіб отримати лише заголовки HTTP. Ви повинні повторити запит.META, щоб отримати все, що вам потрібно.

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 який здійснює саме це.

Джерело - досить хороша довідка про те, як досягти того, що ви намагаєтеся зробити.


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 . Наступний приклад безпосередньо взято з офіційної документації 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)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.