Comment puis-je obtenir tous les en-têtes de requête dans Django?

107

J'ai besoin de tous les en-têtes de requête Django. D'après ce que j'ai lu, Django vide simplement tout dans la request.METAvariable avec beaucoup d'autres données. Quelle serait la meilleure façon d'obtenir tous les en-têtes que le client a envoyés à mon application Django?

Je vais les utiliser pour créer une httplibrequête.

Mridang Agarwalla
la source

Réponses:

139

Selon la documentation, il request.META existe un "dictionnaire Python standard contenant tous les en-têtes HTTP disponibles". Si vous souhaitez obtenir tous les en-têtes, vous pouvez simplement parcourir le dictionnaire.

La partie de votre code pour cela dépend de vos besoins exacts. N'importe quel endroit qui a accès requestdevrait faire.

Mettre à jour

J'ai besoin d'y accéder dans une classe Middleware, mais lorsque je l'itère, j'obtiens beaucoup de valeurs en dehors des en-têtes HTTP.

De la documentation:

À l'exception de CONTENT_LENGTHet CONTENT_TYPE, comme indiqué ci-dessus, tous les en- HTTPtêtes de la demande sont convertis en METAclés en convertissant tous les caractères en majuscules, en remplaçant les tirets par des traits de soulignement et en ajoutant un HTTP_préfixe au nom .

(Je souligne)

Pour obtenir les en- HTTPtêtes seuls, filtrez simplement par clés précédées du préfixe HTTP_.

Mise à jour 2

pourriez-vous me montrer comment je pourrais construire un dictionnaire d'en-têtes en filtrant toutes les clés de la variable request.META qui commencent par HTTP_ et suppriment la partie HTTP_ principale.

Sûr. Voici une façon de procéder.

import re
regex = re.compile('^HTTP_')
dict((regex.sub('', header), value) for (header, value) 
       in request.META.items() if header.startswith('HTTP_'))
Manoj Govindan
la source
J'ai besoin d'y accéder dans une classe Middleware, mais lorsque je l'itère, j'obtiens beaucoup de valeurs en dehors des en-têtes HTTP.
Mridang Agarwalla
Merci Manoj. Juste par curiosité - pourriez-vous me montrer comment je pourrais construire un dictionnaire d'en-têtes en filtrant toutes les clés de la request.METAvariable qui commencent par a HTTP_et en supprimant la HTTP_partie principale . Est-ce possible grâce aux fonctions lambda? (Je pense qu'on les appelle des fonctions lambda) Je pose cette question parce que je continuerais probablement à le faire le long du chemin en les itérant d'abord, puis en vérifiant si cela commence par un HTTP_et en l'ajoutant au nouveau dictionnaire. Merci encore.
Mridang Agarwalla
Merci encore Manoj. Je l'ai légèrement modifié pour l'utiliser à la lstrip('HTTP_')place de l'expression régulière. :)
Mridang Agarwalla
3
@Mridang Agarwalla: lstripne fera pas ce que vous lui demandez de faire. lstripsupprimera tous les premiers caractères qui correspondent à tous les caractères de la chaîne que vous lui donnez, donc si vous avez un en-tête, "HTTP_TOKEN_ID"il vous le rendra "OKEN_ID", car "T"au début de "TOKEN"correspond un caractère dans la chaîne passée à lstrip. La façon de le faire est prefix = 'HTTP_'; header = header[len(prefix):].
jcdyer
2
Django 2.2 a pris en charge HttpRequest.headers.
Dcalsky
30

À partir de Django 2.2, vous pouvez utiliser request.headerspour accéder aux en-têtes HTTP. À partir de la documentation sur HttpRequest.headers :

Un objet de type dict insensible à la casse qui donne accès à tous les en-têtes préfixés HTTP (plus Content-Length et Content-Type) à partir de la requête.

Le nom de chaque en-tête est stylisé avec une casse de titre (par exemple, User-Agent) lorsqu'il est affiché. Vous pouvez accéder aux en-têtes sans tenir compte de la casse:

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

Pour obtenir tous les en-têtes, vous pouvez utiliser request.headers.keys()ou request.headers.items().

Daniel Hepper
la source
17

Voici une autre façon de le faire, très similaire à la réponse de Manoj Govindan ci-dessus:

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]

Cela récupérera également les en CONTENT_TYPE- CONTENT_LENGTHtêtes et request, ainsi que HTTP_ceux. request_headers['some_key]==request.META['some_key'] .

Modifiez en conséquence si vous devez inclure / omettre certains en-têtes. Django en répertorie un certain nombre, mais pas tous, ici: https://docs.djangoproject.com/en/dev/ref/request-response/#django.http.HttpRequest.META

L'algorithme de Django pour les en-têtes de requête:

  1. Remplacer le trait -d' union par un trait de soulignement_
  2. Convertir en MAJUSCULES.
  3. Ajouter HTTP_à tous les en-têtes de la demande d'origine, à l'exception de CONTENT_TYPEet CONTENT_LENGTH.

Les valeurs de chaque en-tête ne doivent pas être modifiées.

Dave
la source
5
Tout cela peut être combiné en une seule expression rationnelle,re.compile(r'^(HTTP_.+|CONTENT_TYPE|CONTENT_LENGTH)$')
Rebs
6

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

vous pouvez cependant l'obtenir à partir de ce fichier ...

James Vare Samuel
la source
3

Je ne pense pas qu'il existe un moyen facile d'obtenir uniquement des en-têtes HTTP. Vous devez parcourir request.META dict pour obtenir tout ce dont vous avez besoin.

django-debug-toolbar adopte la même approche pour afficher les informations d'en-tête. Jetez un œil à ce fichier chargé de récupérer les informations d'en-tête.

Srikanth Chundi
la source
1

Si vous souhaitez obtenir la clé client à partir de l'en-tête de la demande, vous pouvez essayer de suivre:

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
la source
1

Pour ce que cela vaut, il semble que votre intention soit d'utiliser la requête HTTP entrante pour former une autre requête HTTP. Un peu comme une passerelle. Il existe un excellent module django-revproxy qui accomplit exactement cela.

La source est une assez bonne référence sur la façon d'accomplir ce que vous essayez de faire.

abhayAndPoorvisDad
la source
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
la source
0

Vous pouvez simplement utiliser HttpRequest.headers à partir de Django 2.2 . L'exemple suivant est directement tiré de la documentation officielle de Django dans la section Objets de requête et de réponse .

>>> 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
la source