Django'daki tüm istek başlıklarını nasıl alabilirim?


107

Tüm Django istek başlıklarını almam gerekiyor. Okuduğuma göre, Django her şeyi request.METAdeğişkene atıyor ve diğer birçok veriyle birlikte. İstemcinin Django uygulamama gönderdiği tüm başlıkları almanın en iyi yolu ne olabilir ?

Bunları bir httplibistek oluşturmak için kullanacağım .

Yanıtlar:


139

Belgelere göre, request.META"mevcut tüm HTTP başlıklarını içeren standart bir Python sözlüğü" dür. Tüm başlıkları almak istiyorsanız , sözlükte yinelemeniz yeterlidir.

Bunu yapmak için kodunuzun hangi bölümü tam gereksiniminize bağlıdır. Erişimi olan herhangi bir yerin yapması requestgerekir.

Güncelleme

Bir Middleware sınıfında ona erişmem gerekiyor, ancak üzerinde yinelediğimde, HTTP başlıkları dışında birçok değer alıyorum.

Belgelerden:

Yukarıda verilen CONTENT_LENGTHve hariç olmak üzere CONTENT_TYPE, HTTPistekteki tüm başlıklar, METAtüm karakterleri büyük harfe dönüştürerek, herhangi bir kısa çizgiyi altçizgilerle değiştirerek ve ada bir HTTP_önek ekleyerek anahtarlara dönüştürülür .

(Vurgu eklenmiştir)

HTTPBaşlıkları tek başına almak için ön ekli anahtarlara göre filtreleyin HTTP_.

Güncelleme 2

Bir HTTP_ ile başlayan ve baştaki HTTP_ bölümünü çıkaran istek.META değişkenindeki tüm anahtarları filtreleyerek nasıl bir başlık sözlüğü oluşturabileceğimi bana gösterebilir misiniz?

Elbette. İşte bunu yapmanın bir yolu.

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

Bir Middleware sınıfında ona erişmem gerekiyor, ancak üzerinde yinelediğimde, HTTP başlıkları dışında birçok değer alıyorum.
Mridang Agarwalla

Teşekkürler Manoj. Sadece meraktan - request.METAdeğişkendeki a ile başlayan HTTP_ve baştaki HTTP_kısmı çıkaran tüm anahtarları filtreleyerek nasıl bir başlık sözlüğü oluşturabileceğimi gösterebilir misiniz ? Bu lambda fonksiyonları aracılığıyla mümkün müdür? (Sanırım bunlara lambda fonksiyonları deniyor) Bunu soruyorum çünkü muhtemelen uzun yoldan önce onları yineleyerek, sonra a ile başlayıp başlamadığını kontrol HTTP_edip sonra yeni sözlüğe ekleyerek devam ederdim . Tekrar teşekkürler.
Mridang Agarwalla

Tekrar teşekkürler Manoj. lstrip('HTTP_')Normal ifade yerine kullanmak için biraz değiştirdim . :)
Mridang Agarwalla

3
@Mridang Agarwalla: lstripAslında yapmasını istediğiniz şeyi yapmayacak. lstripona verdiğiniz dizedeki herhangi bir karakterle eşleşen tüm önde gelen karakterleri çıkaracaktır, bu nedenle bir başlığınız "HTTP_TOKEN_ID"varsa geri verecektir "OKEN_ID", çünkü "T"başlangıcında "TOKEN"lstrip'e aktarılan dizedeki bir karakterle eşleşir. Bunu yapmanın yolu prefix = 'HTTP_'; header = header[len(prefix):].
jcdyer

2
Django 2.2 destekledi HttpRequest.headers.
Dcalsky

30

Django 2.2'den başlayarak request.headers, HTTP başlıklarına erişmek için kullanabilirsiniz . Gönderen HttpRequest.headers belgelere :

İstekten gelen tüm HTTP önekli başlıklara (artı İçerik Uzunluğu ve İçerik Türü) erişim sağlayan, büyük / küçük harfe duyarlı olmayan, dikte benzeri bir nesne.

Her başlığın adı, görüntülendiğinde başlık büyüklüğüyle (örn. Kullanıcı-Aracı) stilize edilir. Başlıklara büyük / küçük harfe duyarlı olmadan erişebilirsiniz:

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

Tüm başlıkları almak için request.headers.keys()veya kullanabilirsiniz request.headers.items().


17

Bu, Manoj Govindan'ın yukarıdaki cevabına çok benzeyen başka bir yöntemdir :

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]

Bu aynı zamanda başlıkları CONTENT_TYPEve CONTENT_LENGTHbaşlıkları da alacaktır HTTP_. request_headers['some_key]== request.META['some_key'].

Belirli başlıkları eklemeniz / çıkarmanız gerekirse uygun şekilde değiştirin. Django, hepsini değil ama bir grubunu burada listeliyor: https://docs.djangoproject.com/en/dev/ref/request-response/#django.http.HttpRequest.META

Django'nun istek başlıkları için algoritması:

  1. Kısa çizgiyi -alt çizgiyle değiştirin_
  2. UPPERCASE biçimine dönüştür.
  3. Başına ekle HTTP_haricinde orijinal istekte tüm başlıklar için CONTENT_TYPEve CONTENT_LENGTH.

Her başlığın değerleri değiştirilmemiş olmalıdır.


5
Bunların hepsi tek bir normal ifadede birleştirilebilirre.compile(r'^(HTTP_.+|CONTENT_TYPE|CONTENT_LENGTH)$')
Rebs

6

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

bunu bu dosyadan alabilirsiniz ...


3

Yalnızca HTTP başlıklarını almanın kolay bir yolu olduğunu sanmıyorum. İhtiyacınız olanı elde etmek için request.META emriyle yinelemelisiniz.

django-debug-toolbar, başlık bilgilerini göstermek için aynı yaklaşımı kullanır. Başlık bilgilerinin alınmasından sorumlu olan bu dosyaya bir göz atın .


1

İstem başlığından istemci anahtarını almak istiyorsanız, aşağıdakileri deneyebilirsiniz:

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

Ne olursa olsun, amacınız gelen HTTP isteğini başka bir HTTP isteği oluşturmak için kullanmak gibi görünüyor. Bir çeşit ağ geçidi gibi. Tam olarak bunu başaran mükemmel bir django-revproxy modülü var .

Kaynak, yapmaya çalıştığınız şeyi nasıl başaracağınız konusunda oldukça iyi bir referanstır.


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

0

Basitçe Django 2.2'den itibaren HttpRequest.headers'ı kullanabilirsiniz . Aşağıdaki örnek, doğrudan Talep ve yanıt nesneleri bölümü altındaki resmi Django Dokümantasyonundan alınmıştır .

>>> 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)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.