5

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.

rosenthal
  • 775
  • 1
  • 11
  • 28
  • Wrong. Not a duplicate, I explicitly state in my question I am aware of how to access the header and that it isn't present. – rosenthal Dec 27 '17 at 23:10
  • @rosenthal, duplicates are not bad, not to me, at least. I even wrote an answer (which you kindly chose, which is appreciated) even though I though it was a duplicate. To me, at least, they're just ways of saying _"Hey, there might be more info here"_ **:)** – Savir Dec 28 '17 at 00:57
  • Left my comment and didn't want to delete it. I was wrong, it honestly was a duplicate and a reminder to keep myself in check sometimes. – rosenthal Dec 29 '17 at 06:05

1 Answers1

5

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

Savir
  • 17,568
  • 15
  • 82
  • 136
  • 1
    Your answer is pretty much exactly what the documentation says that I already read, yet somehow I still missed that it was ending up in the dump. I could've SWORN I didn't see it, but I'm seeing it appear now. Appreciate the extra pair of eyes – rosenthal Dec 27 '17 at 23:22
  • Haha... Yep, it happens to all/many of us: https://stackoverflow.com/questions/45827690/is-there-anything-in-python-that-is-a-nonetype-besides-none – Savir Dec 28 '17 at 00:59