Stop Django Rest Framework from leaking your docstrings!

Kshitij Nagvekar
WorkIndia.in
Published in
2 min readJan 27, 2020

When working with HTTP in Web Technologies, we usually use methods such as GET, POST, PUT. We tend to ignore the rest. One such request is the OPTIONS request.
An OPTIONS request is used to ask the SERVER about which other HTTP methods it supports. An OPTIONS request responds with an ‘Allow’ header and gives a comma separated list of supported methods. But in the case of Django Rest Framework, an OPTIONS request ends up responding with more data than required.

Try making an OPTIONS request on your DRF Server:

$ http OPTIONS http://127.0.0.1:8000/api/user/feedback/1HTTP/1.0 200 OK 
Access-Control-Allow-Origin: *
Allow: POST, OPTIONS
Content-Type: application/json
Date: Thu, 23 Jan 2020 09:36:51 GMT
Vary: Accept X-Frame-Options: SAMEORIGIN
{
"description": "Endpoint to add feedback response for a user
:param request: {
"q": string,
"r": float,
"o": string
}
:param aid: int
:return: {
fid: int
}",
"name": "Add",
"parses": ["application/json", "application/x-www-form-urlencoded", "multipart/form-data"],
"renders": ["application/json", "text/html"]
}

As you can see, the default response includes the ‘docstring’ for the given controller in the ‘description’ field. Now this ‘feature’ might be good to share docstring within the organisation, but you certainly don’t want the general public to get a hold of this information.

You can avoid this leakage by overriding ‘DEFAULT_METADATA_CLASS’ in your Django settings.

Refer to the CustomMetadata class that keeps only “parses” and “renders” fields in OPTIONS request.

from rest_framework.metadata import BaseMetadatafrom collections import OrderedDictclass CustomMetadata(BaseMetadata): 
def determine_metadata(self, request, view):
metadata = OrderedDict()
metadata[‘renders’] = [renderer.media_type for renderer in view.renderer_classes]
metadata[‘parses’] = [parser.media_type for parser in view.parser_classes]
return metadata

To set this metadata class, add or update following in your settings.py.

REST_FRAMEWORK = { 
‘DEFAULT_METADATA_CLASS’: ‘WorkIndiaApi.metadata.CustomMetadata’
}

Try the same OPTIONS request now, you will not be leaking any docstrings.

$ http OPTIONS http://127.0.0.1:9000/api/user/feedback/1HTTP/1.0 200 OK
Access-Control-Allow-Origin: *
Allow: POST, OPTIONS
Content-Type: application/json
Date: Thu, 23 Jan 2020 09:36:51 GMT
Vary: Accept
X-Frame-Options: SAMEORIGIN
{
"parses": ["application/json", "application/x-www-form-urlencoded", "multipart/form-data"],
"renders": ["application/json", "text/html"]
}

:)

--

--