Wie kann ich alle Anforderungsheader in Django abrufen?

107

Ich muss alle Django-Anforderungsheader erhalten. request.METANach dem, was ich gelesen habe, legt Django einfach alles zusammen mit vielen anderen Daten in der Variablen ab. Was wäre der beste Weg, um alle Header zu erhalten, die der Client an meine Django-Anwendung gesendet hat?

Ich werde diese verwenden, um eine httplibAnfrage zu erstellen .

Mridang Agarwalla
quelle

Antworten:

139

Der Dokumentation zufolge request.METAhandelt es sich um ein "Standard-Python-Wörterbuch, das alle verfügbaren HTTP-Header enthält". Wenn Sie alle Header erhalten möchten, können Sie einfach das Wörterbuch durchlaufen.

Welcher Teil Ihres Codes dies tut, hängt von Ihrer genauen Anforderung ab. Jeder Ort, zu dem Zugang besteht, requestsollte dies tun.

Aktualisieren

Ich muss in einer Middleware-Klasse darauf zugreifen, aber wenn ich darüber iteriere, erhalte ich neben HTTP-Headern viele Werte.

Aus der Dokumentation:

Mit Ausnahme von CONTENT_LENGTHund CONTENT_TYPE, wie oben angegeben, werden alle HTTPÜberschriften in der Anforderung in METASchlüssel konvertiert, indem alle Zeichen in Großbuchstaben konvertiert, Bindestriche durch Unterstriche ersetzt und dem Namen ein HTTP_Präfix hinzugefügt werden .

(Betonung hinzugefügt)

Um die HTTPHeader alleine zu erhalten, filtern Sie einfach nach Schlüsseln, denen ein Präfix vorangestellt ist HTTP_.

Update 2

Können Sie mir zeigen, wie ich ein Wörterbuch mit Headern erstellen kann, indem ich alle Schlüssel aus der request.META-Variablen herausfiltere, die mit einem HTTP_ beginnen und den führenden HTTP_-Teil entfernen.

Sicher. Hier ist eine Möglichkeit, dies zu tun.

import re
regex = re.compile('^HTTP_')
dict((regex.sub('', header), value) for (header, value) 
       in request.META.items() if header.startswith('HTTP_'))
Manoj Govindan
quelle
Ich muss in einer Middleware-Klasse darauf zugreifen, aber wenn ich darüber iteriere, erhalte ich neben HTTP-Headern viele Werte.
Mridang Agarwalla
Danke Manoj. Nur aus Neugier - können Sie mir zeigen, wie ich ein Wörterbuch mit Überschriften erstellen kann, indem Sie alle Schlüssel aus der request.METAVariablen HTTP_herausfiltern, die mit a beginnen, und den führenden HTTP_Teil entfernen . Ist dies durch Lambda-Funktionen möglich? (Ich denke, sie heißen Lambda-Funktionen.) Ich frage dies, weil ich es wahrscheinlich auf lange Sicht tun würde, indem ich zuerst über sie iteriere, dann überprüfe, ob es mit a beginnt, HTTP_und es dann dem neuen Wörterbuch hinzufüge. Danke noch einmal.
Mridang Agarwalla
Nochmals vielen Dank Manoj. Ich habe es leicht modifiziert, um es lstrip('HTTP_')anstelle des regulären Ausdrucks zu verwenden. :)
Mridang Agarwalla
3
@ Mridang Agarwalla: Ich lstripwerde nicht das tun, was du von ihm verlangst . lstripEntfernt alle führenden Zeichen, die mit den Zeichen in der von Ihnen angegebenen Zeichenfolge übereinstimmen. Wenn Sie also eine Kopfzeile "HTTP_TOKEN_ID"haben, wird diese zurückgegeben "OKEN_ID", da "T"zu Beginn "TOKEN"ein Zeichen in der Zeichenfolge übereinstimmt, das an lstrip übergeben wurde. Der Weg dazu ist prefix = 'HTTP_'; header = header[len(prefix):].
JCDyer
2
Django 2.2 hat unterstützt HttpRequest.headers.
Dcalsky
30

Ab Django 2.2 können Sie request.headersauf die HTTP-Header zugreifen. Aus der Dokumentation zu HttpRequest.headers :

Ein Objekt ohne Berücksichtigung der Groß- und Kleinschreibung, das Zugriff auf alle Header mit HTTP-Präfix (plus Inhaltslänge und Inhaltstyp) aus der Anforderung bietet.

Der Name jedes Headers wird bei der Anzeige mit einem Titel (z. B. User-Agent) stilisiert. Sie können unabhängig von Groß- und Kleinschreibung auf Header zugreifen:

>>> 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)

Um alle Header zu erhalten, können Sie request.headers.keys()oder verwenden request.headers.items().

Daniel Hepper
quelle
17

Dies ist eine andere Möglichkeit, die der obigen Antwort von Manoj Govindan sehr ähnlich ist :

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]

Dadurch werden auch die Header abgerufen CONTENT_TYPEund CONTENT_LENGTHangefordert, zusammen mit HTTP_denen. request_headers['some_key]== request.META['some_key'].

Ändern Sie entsprechend, wenn Sie bestimmte Header einschließen / weglassen müssen. Django listet hier einige, aber nicht alle auf: https://docs.djangoproject.com/de/dev/ref/request-response/#django.http.HttpRequest.META

Djangos Algorithmus für Anforderungsheader:

  1. Ersetzen Sie den Bindestrich -durch einen Unterstrich_
  2. In GROSSBUCHSTABEN konvertieren.
  3. Stellen Sie HTTP_alle Header in der ursprünglichen Anforderung mit Ausnahme von CONTENT_TYPEund voran CONTENT_LENGTH.

Die Werte der einzelnen Header sollten unverändert bleiben.

Dave
quelle
5
Das kann alles zu einem einzigen regulären Ausdruck kombiniert werdenre.compile(r'^(HTTP_.+|CONTENT_TYPE|CONTENT_LENGTH)$')
Rebs
6

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

Sie können das aber aus dieser Datei bekommen ...

James Vare Samuel
quelle
3

Ich glaube nicht, dass es einen einfachen Weg gibt, nur HTTP-Header zu bekommen. Sie müssen die Anfrage durchlaufen. META-Diktat, um alles zu bekommen, was Sie brauchen.

Die django-debug-Symbolleiste verwendet denselben Ansatz, um Header-Informationen anzuzeigen. Schauen Sie sich diese Datei an, die für das Abrufen von Header-Informationen verantwortlich ist.

Srikanth Chundi
quelle
1

Wenn Sie den Clientschlüssel aus dem Anforderungsheader abrufen möchten, können Sie Folgendes versuchen:

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)
Tony Aziz
quelle
1

Es scheint, dass Sie beabsichtigen, die eingehende HTTP-Anforderung zu verwenden, um eine weitere HTTP-Anforderung zu bilden. Irgendwie wie ein Gateway. Es gibt ein exzellentes Modul django-revproxy , das genau dies erreicht.

Die Quelle ist eine ziemlich gute Referenz dafür, wie Sie das erreichen, was Sie versuchen.

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

Sie können einfach HttpRequest.headers ab Django 2.2 verwenden . Das folgende Beispiel stammt direkt aus der offiziellen Django-Dokumentation im Abschnitt Anforderungs- und Antwortobjekte .

>>> 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)
Kushan Gunasekera
quelle