Como posso obter todos os cabeçalhos de solicitação no Django?

107

Preciso obter todos os cabeçalhos de solicitação do Django. Pelo que li, o Django simplesmente despeja tudo na request.METAvariável junto com muitos outros dados. Qual seria a melhor maneira de obter todos os cabeçalhos que o cliente enviou para meu aplicativo Django?

Vou usar isso para criar uma httplibsolicitação.

Mridang Agarwalla
fonte

Respostas:

139

De acordo com a documentação, request.META é um "dicionário Python padrão contendo todos os cabeçalhos HTTP disponíveis". Se você deseja obter todos os cabeçalhos, pode simplesmente iterar no dicionário.

Qual parte do seu código deve ser feita depende de sua necessidade exata. Qualquer lugar que tenha acesso requestdeve servir.

Atualizar

Eu preciso acessá-lo em uma classe de Middleware, mas quando eu itero sobre ele, obtenho muitos valores além dos cabeçalhos HTTP.

Da documentação:

Com exceção de CONTENT_LENGTHe CONTENT_TYPE, conforme fornecido acima, todos os HTTPcabeçalhos na solicitação são convertidos em METAchaves, convertendo todos os caracteres em maiúsculas, substituindo todos os hifens por sublinhados e adicionando um HTTP_prefixo ao nome .

(Enfase adicionada)

Para obter apenas os HTTPcabeçalhos, basta filtrar por chaves com o prefixo HTTP_.

Atualização 2

você poderia me mostrar como eu poderia construir um dicionário de cabeçalhos filtrando todas as chaves da variável request.META que começam com um HTTP_ e eliminam a parte principal do HTTP_.

Certo. Aqui está uma maneira de fazer isso.

import re
regex = re.compile('^HTTP_')
dict((regex.sub('', header), value) for (header, value) 
       in request.META.items() if header.startswith('HTTP_'))
Manoj Govindan
fonte
Preciso acessá-lo em uma classe de Middleware, mas quando itero sobre ele, obtenho muitos valores além dos cabeçalhos HTTP.
Mridang Agarwalla
Obrigado Manoj. Apenas por curiosidade - você poderia me mostrar como eu poderia construir um dicionário de cabeçalhos filtrando todas as chaves da request.METAvariável que começam com a HTTP_e removendo a HTTP_parte inicial. Isso é possível por meio de funções lambda? (Acho que são chamadas de funções lambda). Estou perguntando isso porque provavelmente continuaria fazendo isso da maneira mais longa, primeiro iterando sobre elas, depois verificando se começa com a HTTP_e adicionando-o ao novo dicionário. Obrigado novamente.
Mridang Agarwalla
Obrigado novamente Manoj. Eu o modifiquei ligeiramente para usar em lstrip('HTTP_')vez do regex. :)
Mridang Agarwalla,
3
@Mridang Agarwalla: lstripnão fará realmente o que você está pedindo. lstripirá remover todos os caracteres iniciais que correspondam a quaisquer caracteres na string que você forneceu, então se você tiver um cabeçalho, "HTTP_TOKEN_ID"ele retornará "OKEN_ID", porque "T"no início de "TOKEN"corresponde um caractere na string passada para lstrip. A maneira de fazer isso é prefix = 'HTTP_'; header = header[len(prefix):].
jcdyer de
2
Django 2.2 tem suporte HttpRequest.headers.
Dcalsky 01 de
30

A partir do Django 2.2, você pode usar request.headerspara acessar os cabeçalhos HTTP. Da documentação em HttpRequest.headers :

Um objeto sem distinção entre maiúsculas e minúsculas, semelhante a dict que fornece acesso a todos os cabeçalhos com prefixo HTTP (mais Content-Length e Content-Type) da solicitação.

O nome de cada cabeçalho é estilizado com capitalização (por exemplo, Agente do Usuário) quando é exibido. Você pode acessar os cabeçalhos sem fazer distinção entre maiúsculas e 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 obter todos os cabeçalhos, você pode usar request.headers.keys()ou request.headers.items().

Daniel Hepper
fonte
17

Esta é outra maneira de fazer isso, muito semelhante à resposta de Manoj Govindan acima:

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]

Isso também pegará os cabeçalhos CONTENT_TYPEe CONTENT_LENGTHrequest, junto com os HTTP_outros. request_headers['some_key]== request.META['some_key'].

Modifique de acordo se precisar incluir / omitir certos cabeçalhos. Django lista um monte, mas não todos, deles aqui: https://docs.djangoproject.com/en/dev/ref/request-response/#django.http.HttpRequest.META

Algoritmo do Django para cabeçalhos de solicitação:

  1. Substitua o hífen -por sublinhado_
  2. Converter para MAIÚSCULAS.
  3. Anexar HTTP_a todos os cabeçalhos na solicitação original, exceto para CONTENT_TYPEe CONTENT_LENGTH.

Os valores de cada cabeçalho não devem ser modificados.

Dave
fonte
5
Tudo isso pode ser combinado em uma única expressão regular,re.compile(r'^(HTTP_.+|CONTENT_TYPE|CONTENT_LENGTH)$')
Rebs
6

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

você pode obter isso deste arquivo ...

James Vare Samuel
fonte
3

Não acho que haja uma maneira fácil de obter apenas cabeçalhos HTTP. Você deve iterar por meio de request.META dict para obter tudo o que você precisa.

django-debug-toolbar usa a mesma abordagem para mostrar as informações do cabeçalho. Dê uma olhada neste arquivo responsável por recuperar as informações do cabeçalho.

Srikanth Chundi
fonte
1

Se você deseja obter a chave do cliente no cabeçalho da solicitação, pode tentar o seguinte:

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

Pelo que vale a pena, parece que sua intenção é usar a solicitação HTTP de entrada para formar outra solicitação HTTP. Uma espécie de portal. Existe um excelente módulo django-revproxy que faz exatamente isso.

A fonte é uma boa referência sobre como realizar o que você está tentando fazer.

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

Simplesmente você pode usar HttpRequest.headers do Django 2.2 em diante. O exemplo a seguir foi retirado diretamente da Documentação oficial do Django na seção Objetos de solicitação e resposta .

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