web-dev-qa-db-fra.com

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

Je dois obtenir tous les en-têtes de la requête Django. D'après ce que j'ai lu, Django vide tout simplement dans le request.META variable avec beaucoup d'autres données. Quel serait le meilleur moyen d’obtenir tous les en-têtes que le client a envoyés à mon application Django?

Je vais les utiliser pour construire une requête httplib.

91

Selon le documentationrequest.META est un "dictionnaire standard Python contenant tous les en-têtes HTTP disponibles" ". Si vous voulez obtenir tous les en-têtes, vous pouvez simplement parcourir le dictionnaire.

Quelle partie de votre code à faire cela dépend de votre exigence exacte. Tout endroit ayant accès à request devrait faire l'affaire.

Mettre à jour

J'ai besoin d'y accéder dans une classe de middleware, mais lorsque j'y répète, j'obtiens beaucoup de valeurs en dehors des en-têtes HTTP.

De la documentation:

À l'exception de CONTENT_LENGTH et CONTENT_TYPE, comme indiqué ci-dessus, tous les en-têtes HTTP de la demande sont convertis en clés META en convertissant tous les caractères en majuscules, en remplaçant les traits d'union par des traits de soulignement et . ajouter un HTTP_ préfixe du nom.

(Soulignement ajouté)

Pour obtenir uniquement les en-têtes HTTP, il suffit de filtrer les clés précédées du préfixe HTTP_.

Mise à jour 2

pourriez-vous me montrer comment créer 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 principale HTTP_.

Sûr. Voici une façon de le faire.

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

C'est 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 va également saisir le CONTENT_TYPE et CONTENT_LENGTH _ en-têtes de requête, avec le HTTP_ _ ceux. request_headers['some_key] == request.META['some_key'].

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

Algorithme de Django pour les en-têtes de requête:

  1. Remplacer le trait d'union - avec trait de soulignement _
  2. Convertir en majuscules.
  3. Préfini HTTP_ à tous les en-têtes de la demande d'origine, à l'exception de CONTENT_TYPE et CONTENT_LENGTH.

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

17
Dave Gallagher

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

Objet de type dict, insensible à la casse, qui donne accès à tous les en-têtes à préfixe 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 distinction de 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().

13
Daniel Hepper

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

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

5
James Vare Samuel

Je ne pense pas qu'il existe un moyen simple d'obtenir uniquement les en-têtes HTTP. Vous devez parcourir requête.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. Regardez ce fichier responsable de la récupération des informations d'en-tête.

4
Srikanth Chundi

Si vous voulez obtenir la clé du client à partir de l'en-tête de la requête, 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)
1
Tony Jasur
<b>request.META</b><br>
{% for k_meta, v_meta in request.META.items %}
  <code>{{ k_meta }}</code> : {{ v_meta }} <br>
{% endfor %}
0
S. Nick

Pour ce que cela vaut, il semble que votre intention est 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 très bonne référence sur la façon d'accomplir ce que vous essayez de faire.

0
abhayAndPoorvisDad