Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django REST Framework custom headers in request object [duplicate]

Tags:

I have a problem viewing incoming custom headers from requests when I'm creating a new API view via the @api_view decorator.

My custom API view looks like this:

 @api_view(['GET'])
 def TestView(request):
   print(request.META)
   return Response({'message': 'test'})

What I'm expecting is doing something like

curl --request GET \ --url http://localhost:8000/test \ --header 'custom: test'

I'd see my custom header called custom to appear in the output. Instead, it's not there at all. From the documentation, it says the following for the request.META field:

A dictionary containing all available HTTP headers. Available headers depend on the client and server, but here are some examples:

Whereas, they don't appear at all in my output. Am I missing something here?

If it's relevant, I register my URL as such:

urlpatterns = [url(r'test', views.TestView, name='test'), ...]

My end goal is to write a custom permission class that will parse the custom header and do something related to authentication with it, and either allow or deny the request. My POC here is just to show the basic example of what I'm dealing with. I can provide the output of the print(request.META) but it's just a wall of text without my expected header present.

like image 866
rosenthal Avatar asked Dec 27 '17 21:12

rosenthal


1 Answers

Django prepends HTTP_ to the custom headers. I think (not sure, though) that it might be related to some security issues described here. It also capitalizes them, so your custom header becomes HTTP_CUSTOM

from rest_framework.decorators import api_view
from rest_framework.response import Response

import logging

logger = logging.getLogger('django.test')

@api_view(['GET'])
def TestView(request):
    logger.info('Meta: %s' % request.META['HTTP_CUSTOM'])
    return Response({'message': 'test'})

Correctly outputs (if the logging has been properly configured as described here):

Django version 2.0, using settings 'django_server.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
"GET /test HTTP/1.1" 301 0
Meta: test
"GET /test/ HTTP/1.1" 200 18

Also, as you can see in the output above, Django gives a 301 redirect when the API is hit (I believe this is for authentication purposes? Not sure either) so you'll have to tell your cURL to follow the redirects using --location:

curl --location --request GET \
     --header 'custom: test' http://localhost:8000/test

Also note that all the hyphens (-) in your header's name are transformed to underline symbols (_) so if you call your header something like my-custom, Django will transform it to HTTP_MY_CUSTOM

like image 123
BorrajaX Avatar answered Sep 20 '22 13:09

BorrajaX