Bagaimana saya bisa mendapatkan semua tajuk permintaan di Django?

107

Saya perlu mendapatkan semua tajuk permintaan Django. Dari apa yang telah saya baca, Django hanya membuang semuanya ke dalam request.METAvariabel bersama dengan banyak data lainnya. Apa cara terbaik untuk mendapatkan semua tajuk yang klien kirim ke aplikasi Django saya?

Saya akan menggunakan ini untuk membuat httplibpermintaan.

Mridang Agarwalla
sumber

Jawaban:

139

Menurut dokumentasinya request.META adalah "kamus Python standar yang berisi semua header HTTP yang tersedia". Jika Anda ingin mendapatkan semua header, Anda dapat mengulangnya melalui kamus.

Bagian mana dari kode Anda untuk melakukan ini bergantung pada kebutuhan Anda. Tempat mana pun yang memiliki akses requestharus melakukannya.

Memperbarui

Saya perlu mengaksesnya di kelas Middleware tetapi ketika saya mengulanginya, saya mendapatkan banyak nilai selain dari header HTTP.

Dari dokumentasi:

Dengan pengecualian CONTENT_LENGTHdan CONTENT_TYPE, seperti yang diberikan di atas, setiap HTTPheader dalam permintaan diubah menjadi METAkunci dengan mengonversi semua karakter menjadi huruf besar, mengganti tanda hubung dengan garis bawah dan menambahkan HTTP_awalan ke nama .

(Penekanan ditambahkan)

Untuk mendapatkan HTTPheader saja, cukup filter dengan kunci yang diawali dengan HTTP_.

Perbarui 2

dapatkah Anda menunjukkan kepada saya bagaimana saya bisa membuat kamus tajuk dengan menyaring semua kunci dari variabel request.META yang dimulai dengan HTTP_ dan menghapus bagian HTTP_ terkemuka.

Tentu. Inilah salah satu cara untuk melakukannya.

import re
regex = re.compile('^HTTP_')
dict((regex.sub('', header), value) for (header, value) 
       in request.META.items() if header.startswith('HTTP_'))
Manoj Govindan
sumber
Saya perlu mengaksesnya di kelas Middleware tetapi ketika saya mengulanginya, saya mendapatkan banyak nilai selain dari header HTTP.
Mridang Agarwalla
Terima kasih Manoj. Hanya karena penasaran - dapatkah Anda menunjukkan kepada saya bagaimana saya dapat membuat kamus tajuk dengan menyaring semua kunci dari request.METAvariabel yang dimulai dengan a HTTP_dan menghapus bagian utamanya HTTP_. Apakah ini mungkin melalui fungsi lambda? (Saya pikir mereka disebut fungsi lambda) Saya menanyakan ini karena saya mungkin akan terus melakukannya dengan terlebih dahulu mengulanginya, kemudian memeriksa untuk melihat apakah itu dimulai dengan a HTTP_dan kemudian menambahkannya ke kamus baru. Terima kasih lagi.
Mridang Agarwalla
Terima kasih lagi Manoj. Saya memodifikasinya sedikit untuk digunakan lstrip('HTTP_')sebagai pengganti regex. :)
Mridang Agarwalla
3
@Mridang Agarwalla: lstriptidak akan benar-benar melakukan apa yang Anda minta. lstripakan menghapus semua karakter utama yang cocok dengan karakter manapun dalam string yang Anda berikan, jadi jika Anda memiliki header "HTTP_TOKEN_ID"itu akan memberikan kembali "OKEN_ID", karena "T"pada awal "TOKEN"pertandingan karakter dalam string diteruskan ke lstrip. Cara melakukannya adalah prefix = 'HTTP_'; header = header[len(prefix):].
jcdyer
2
Django 2.2 telah mendukung HttpRequest.headers.
Dcalsky
30

Mulai dari Django 2.2, Anda dapat menggunakan request.headersuntuk mengakses tajuk HTTP. Dari dokumentasi di HttpRequest.headers :

Objek tidak peka huruf besar dan kecil, seperti dikt yang menyediakan akses ke semua header yang diawali HTTP (ditambah Panjang Konten dan Jenis Konten) dari permintaan.

Nama masing-masing tajuk disesuaikan dengan kapitalisasi judul (mis. Agen-Pengguna) saat ditampilkan. Anda dapat mengakses header tanpa membedakan huruf besar / kecil:

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

Untuk mendapatkan semua header, Anda dapat menggunakan request.headers.keys()atau request.headers.items().

Daniel Hepper
sumber
17

Ini adalah cara lain untuk melakukannya, sangat mirip dengan jawaban Manoj Govindan di atas:

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]

Itu juga akan mengambil CONTENT_TYPEdan CONTENT_LENGTHmeminta header, bersama dengan yang HTTP_ada. request_headers['some_key]== request.META['some_key'].

Ubah seperlunya jika Anda perlu menyertakan / menghilangkan header tertentu. Django mendaftar sekelompok, tetapi tidak semuanya, di sini: https://docs.djangoproject.com/en/dev/ref/request-response/#django.http.HttpRequest.META

Algoritme Django untuk tajuk permintaan:

  1. Ganti tanda hubung -dengan garis bawah_
  2. Ubah menjadi UPPERCASE.
  3. Tambahkan HTTP_di awal semua tajuk dalam permintaan asli, kecuali untuk CONTENT_TYPEdan CONTENT_LENGTH.

Nilai dari setiap tajuk tidak boleh diubah.

Dave
sumber
5
Itu semua dapat digabungkan menjadi satu regexp,re.compile(r'^(HTTP_.+|CONTENT_TYPE|CONTENT_LENGTH)$')
Rebs
6

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

Anda bisa mendapatkannya dari file ini ...

James Vare Samuel
sumber
3

Saya rasa tidak ada cara mudah untuk hanya mendapatkan header HTTP. Anda harus mengulang melalui request.META dict untuk mendapatkan semua yang Anda butuhkan.

django-debug-toolbar menggunakan pendekatan yang sama untuk menampilkan informasi header. Lihat file ini yang bertanggung jawab untuk mengambil informasi header.

Srikanth Chundi
sumber
1

Jika Anda ingin mendapatkan kunci klien dari header permintaan, Anda dapat mencoba berikut ini:

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

Untuk apa nilainya, tampaknya maksud Anda adalah menggunakan permintaan HTTP yang masuk untuk membentuk permintaan HTTP lain. Semacam pintu gerbang. Ada modul django-revproxy yang sangat baik yang menyelesaikan hal ini dengan tepat.

Sumber adalah referensi yang cukup bagus tentang bagaimana mencapai apa yang Anda coba lakukan.

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

Secara sederhana Anda dapat menggunakan HttpRequest.headers dari Django 2.2 dan seterusnya. Contoh berikut diambil langsung dari Dokumentasi Django resmi di bawah bagian objek Permintaan dan tanggapan .

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