¿Cómo puedo obtener todos los encabezados de solicitud en Django?

107

Necesito obtener todos los encabezados de solicitud de Django. Por lo que he leído, Django simplemente vierte todo en la request.METAvariable junto con muchos otros datos. ¿Cuál sería la mejor manera de obtener todos los encabezados que el cliente envió a mi aplicación Django?

Los usaré para crear una httplibsolicitud.

Mridang Agarwalla
fuente

Respuestas:

139

Según la documentación, request.META es un "diccionario estándar de Python que contiene todos los encabezados HTTP disponibles". Si quieres conseguir todo los encabezados, simplemente puede recorrer el diccionario.

La parte de su código para hacer esto depende de sus requisitos exactos. Cualquier lugar al que tenga acceso requestdebería hacerlo.

Actualizar

Necesito acceder a él en una clase de Middleware, pero cuando lo repito, obtengo muchos valores además de los encabezados HTTP.

De la documentación:

Con la excepción de CONTENT_LENGTHy CONTENT_TYPE, como se indicó anteriormente, los HTTPencabezados de la solicitud se convierten en METAclaves convirtiendo todos los caracteres a mayúsculas, reemplazando los guiones con guiones bajos y agregando un HTTP_prefijo al nombre .

(Énfasis añadido)

Para obtener HTTPsolo los encabezados, simplemente filtre por claves con el prefijoHTTP_ .

Actualización 2

¿Podría mostrarme cómo podría construir un diccionario de encabezados filtrando todas las claves de la variable request.META que comienza con HTTP_ y elimina la parte principal de HTTP_?

Por supuesto. He aquí una forma de hacerlo.

import re
regex = re.compile('^HTTP_')
dict((regex.sub('', header), value) for (header, value) 
       in request.META.items() if header.startswith('HTTP_'))
Manoj Govindan
fuente
Necesito acceder a él en una clase de Middleware, pero cuando lo repito, obtengo muchos valores además de los encabezados HTTP.
Mridang Agarwalla
Gracias Manoj. Solo por curiosidad, ¿podría mostrarme cómo podría construir un diccionario de encabezados filtrando todas las claves de la request.METAvariable que comienzan con HTTP_ay quitan la HTTP_parte inicial ? ¿Es esto posible a través de funciones lambda? (Creo que se llaman funciones lambda) Estoy preguntando esto porque probablemente continuaría haciéndolo por el camino largo primero iterando sobre ellas, luego verificando si comienza con HTTP_ay luego agregándolo al nuevo diccionario. Gracias de nuevo.
Mridang Agarwalla
Gracias de nuevo Manoj. Lo modifiqué ligeramente para usarlo en lstrip('HTTP_')lugar de la expresión regular. :)
Mridang Agarwalla
3
@Mridang Agarwalla: en lstriprealidad no hará lo que le pides que haga. lstripeliminará todos los caracteres iniciales que coincidan con cualquier carácter de la cadena que le proporcione, por lo que si tiene un encabezado "HTTP_TOKEN_ID", lo devolverá "OKEN_ID", porque "T"al principio de "TOKEN"coincide con un carácter en la cadena pasada a lstrip. La forma de hacerlo es prefix = 'HTTP_'; header = header[len(prefix):].
jcdyer
2
Django 2.2 tiene soporte HttpRequest.headers.
Dcalsky
30

A partir de Django 2.2, puede utilizar request.headerspara acceder a los encabezados HTTP. De la documentación en HttpRequest.headers :

Un objeto similar a un dict que no distingue entre mayúsculas y minúsculas que proporciona acceso a todos los encabezados con prefijo HTTP (más Content-Length y Content-Type) desde la solicitud.

El nombre de cada encabezado se estiliza con el título en mayúsculas (por ejemplo, User-Agent) cuando se muestra. Puede acceder a los encabezados sin distinción entre mayúsculas y minúsculas:

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

Para obtener todos los encabezados, puede usar request.headers.keys()o request.headers.items().

Daniel Hepper
fuente
17

Esta es otra forma de hacerlo, muy similar a la respuesta de Manoj Govindan anterior:

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]

Eso también tomará los encabezados CONTENT_TYPEy CONTENT_LENGTHsolicitará, junto con HTTP_los. request_headers['some_key]== request.META['some_key'].

Modifique en consecuencia si necesita incluir / omitir ciertos encabezados. Django enumera un montón, pero no todos, aquí: https://docs.djangoproject.com/en/dev/ref/request-response/#django.http.HttpRequest.META

Algoritmo de Django para encabezados de solicitud:

  1. Reemplazar guion - con bajo_
  2. Convierte a MAYÚSCULAS.
  3. Anteponer HTTP_a todos los encabezados en la solicitud original, excepto CONTENT_TYPEy CONTENT_LENGTH.

Los valores de cada encabezado no deben modificarse.

Dave
fuente
5
Todo eso se puede combinar en una sola expresión regular,re.compile(r'^(HTTP_.+|CONTENT_TYPE|CONTENT_LENGTH)$')
Rebs
6

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

aunque puede obtenerlo de este archivo ...

James Vare Samuel
fuente
3

No creo que haya una manera fácil de obtener solo encabezados HTTP. Tienes que iterar a través de request.META dict para obtener todo lo que necesitas.

django-debug-toolbar adopta el mismo enfoque para mostrar la información del encabezado. Eche un vistazo a este archivo responsable de recuperar la información del encabezado.

Srikanth Chundi
fuente
1

Si desea obtener la clave del cliente del encabezado de la solicitud, puede intentar lo siguiente:

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
fuente
1

Por lo que vale, parece que su intención es utilizar la solicitud HTTP entrante para formar otra solicitud HTTP. Una especie de puerta de entrada. Existe un excelente módulo django-revproxy que logra exactamente esto.

La fuente es una referencia bastante buena sobre cómo lograr lo que está tratando de hacer.

abhayAndPoorvisDad
fuente
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
fuente
0

Simplemente puede usar HttpRequest.headers desde Django 2.2 en adelante. El siguiente ejemplo se toma directamente de la oficial de documentación de Django bajo solicitud y los objetos de respuesta sección.

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