Come posso ottenere tutte le intestazioni delle richieste in Django?


107

Ho bisogno di ottenere tutte le intestazioni delle richieste Django. Da quello che ho letto, Django scarica semplicemente tutto nella request.METAvariabile insieme a molti altri dati. Quale sarebbe il modo migliore per ottenere tutte le intestazioni che il client ha inviato alla mia applicazione Django?

Li userò per creare una httplibrichiesta.

Risposte:


139

Secondo la documentazione request.META è un "dizionario Python standard contenente tutte le intestazioni HTTP disponibili". Se vuoi ottenere tutte le intestazioni puoi semplicemente scorrere il dizionario.

Quale parte del codice eseguire questa operazione dipende dal tuo requisito esatto. requestDovrebbe andare ovunque .

Aggiornare

Devo accedervi in ​​una classe middleware, ma quando ci ripeto, ottengo molti valori oltre alle intestazioni HTTP.

Dalla documentazione:

Ad eccezione di CONTENT_LENGTHe CONTENT_TYPE, come indicato sopra, tutte le HTTPintestazioni nella richiesta vengono convertite in METAchiavi convertendo tutti i caratteri in maiuscolo, sostituendo eventuali trattini con trattini bassi e aggiungendo un HTTP_prefisso al nome .

(Enfasi aggiunta)

Per ottenere HTTPsolo le intestazioni, basta filtrare per chiavi con prefisso HTTP_.

Aggiorna 2

potresti mostrarmi come posso costruire un dizionario di intestazioni filtrando tutte le chiavi dalla variabile request.META che iniziano con HTTP_ e rimuovono la parte iniziale HTTP_.

Sicuro. Ecco un modo per farlo.

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

Ho bisogno di accedervi in ​​una classe middleware, ma quando ci ripeto, ottengo molti valori oltre alle intestazioni HTTP.
Mridang Agarwalla

Grazie Manoj. Solo per curiosità, potresti mostrarmi come posso costruire un dizionario di intestazioni filtrando tutte le chiavi dalla request.METAvariabile che iniziano con a HTTP_e rimuovono la HTTP_parte iniziale. È possibile tramite le funzioni lambda? (Penso che si chiamino funzioni lambda) Lo chiedo perché probabilmente continuerei a farlo a lungo iterando prima su di esse, quindi controllando per vedere se inizia con a HTTP_e quindi aggiungendolo al nuovo dizionario. Grazie ancora.
Mridang Agarwalla

Grazie ancora Manoj. L'ho modificato leggermente per usarlo al lstrip('HTTP_')posto della regex. :)
Mridang Agarwalla

3
@Mridang Agarwalla: lstripin realtà non farà quello che gli chiedi di fare. lstriprimuoverà tutti i caratteri iniziali che corrispondono a qualsiasi carattere nella stringa che gli dai, quindi se hai un'intestazione "HTTP_TOKEN_ID"restituirà "OKEN_ID", perché "T"all'inizio di "TOKEN"corrisponde un carattere nella stringa passata a lstrip. Il modo per farlo è prefix = 'HTTP_'; header = header[len(prefix):].
jcdyer

2
Django 2.2 ha supportato HttpRequest.headers.
Dcalsky

30

A partire da Django 2.2, puoi usare request.headersper accedere alle intestazioni HTTP. Dalla documentazione su HttpRequest.headers :

Un oggetto senza distinzione tra maiuscole e minuscole, simile a dict che fornisce l'accesso a tutte le intestazioni con prefisso HTTP (più Content-Length e Content-Type) dalla richiesta.

Il nome di ciascuna intestazione è stilizzato con maiuscole / minuscole (es. User-Agent) quando viene visualizzato. È possibile accedere alle intestazioni senza distinzione tra maiuscole e minuscole:

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

Per ottenere tutte le intestazioni, puoi usare request.headers.keys()o request.headers.items().


17

Questo è un altro modo per farlo, molto simile alla risposta di Manoj Govindan sopra:

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]

Questo prenderà anche le intestazioni CONTENT_TYPEe CONTENT_LENGTHrequest, insieme a HTTP_quelle. request_headers['some_key]== request.META['some_key'].

Modificare di conseguenza se è necessario includere / omettere determinate intestazioni. Django ne elenca un sacco, ma non tutti, qui: https://docs.djangoproject.com/en/dev/ref/request-response/#django.http.HttpRequest.META

Algoritmo di Django per le intestazioni delle richieste:

  1. Sostituisci il trattino -con il trattino basso_
  2. Converti in MAIUSCOLO.
  3. Anteponi HTTP_a tutte le intestazioni nella richiesta originale, ad eccezione di CONTENT_TYPEe CONTENT_LENGTH.

I valori di ogni intestazione non dovrebbero essere modificati.


5
Tutto questo può essere combinato in un'unica re.compile(r'^(HTTP_.+|CONTENT_TYPE|CONTENT_LENGTH)$')
espressione regolare

6

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

puoi ottenerlo da questo file però ...


3

Non penso che ci sia un modo semplice per ottenere solo intestazioni HTTP. Devi iterare attraverso request.META dict per ottenere tutto ciò di cui hai bisogno.

django-debug-toolbar utilizza lo stesso approccio per mostrare le informazioni di intestazione. Dai un'occhiata a questo file responsabile del recupero delle informazioni di intestazione.


1

Se vuoi ottenere la chiave del client dall'intestazione della richiesta, puoi provare a seguire:

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

Per quello che vale, sembra che il tuo intento sia quello di utilizzare la richiesta HTTP in arrivo per formare un'altra richiesta HTTP. Una specie di gateway. C'è un eccellente modulo django-revproxy che fa esattamente questo.

La fonte è un buon riferimento su come realizzare ciò che stai cercando di fare.


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

0

Semplicemente puoi usare HttpRequest.headers da Django 2.2 in poi. L'esempio seguente è preso direttamente dalla documentazione ufficiale di Django nella sezione Oggetti di richiesta e risposta .

>>> 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)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.