GSOC 2023 Discussion on Configurable Content Type Parsing

Hi everyone,
I want to contribute to this project as a part of GSOC 2023. I have never contributed to any of the official Django projects earlier but I have experience using the framework for last 2 years. In this discussion I would like to propose a high level view of how this can be implemented, any kind of feedback and reference to resources for a more detailed and clear perspective about the project from your side would be very much appreciated, before I start writing the proposal.

Project Title : Configurable Content Type Parsing
Project Description(Given):
For Django 5.0 we’re looking to modernize the HTTPRequest object, adding a content-type aware request.data property. This will parse request.body according to the content type.

The initial phase — targeted for before GSoC — will add request.data and add support for JSON body handling, but the next phase is to make that fully pluggable with custom parsers.

  • Add a list of parsers to the request object, that can be customised — in a middleware for example — at any point prior to accessing request.data.
  • Parsers should implement a can_handle(content_type) -> Bool method. The first parser returning True will be selected to parse the request.body.

Expected outcome is a PR allowing configurable content type parsing.

High level thoughts on implementation :

Step 1: Add a parsers list to the HttpRequest object :
We’ll start by adding a parsers list to the HttpRequest object that will contain instances of parser classes. This list will be empty by default, and will be populated by custom parsers added via middleware.

Step 2: Define a Parser abstract class
We’ll define a Parser abstract class that all custom parsers must inherit from. This abstract class should define the can_handle(content_type) -> Bool method that checks whether the parser can handle the given content type.

Step 3: Implement a default JSONParser class
We’ll implement a default JSONParser class that inherits from Parser and handles JSON request bodies. This parser will be added to the parsers list by default.

Possible high level code example

import json

class JSONParser(Parser):
    def can_handle(self, content_type):
        return content_type == 'application/json'

    def parse(self, body):
        return json.loads(body.decode('utf-8'))

Step 4 : Add a data property to the HttpRequest object
We’ll add a data property to the HttpRequest object that will be responsible for parsing the request body. This property should first check the content type of the request, and then iterate through the parsers list to find the first parser that can handle the content type. If a parser is found, it should be used to parse the request body, and the parsed data should be returned. If no parser can handle the content type, a UnsupportedMediaType exception should be raised.

Possible high level code example

from django.http import UnsupportedMediaType

class HttpRequest:
    def __init__(self):
       .......code........
        self.parsers = [JSONParser()]

    @property
    def data(self):
        content_type = self.headers.get('Content-Type', '')
        for parser in self.parsers:
            if parser.can_handle(content_type):
                return parser.parse(self.body)
        raise UnsupportedMediaType('Unsupported content type: {}'.format(content_type))

Step 5: Allow customization of the parsers list via middleware
We’ll allow customization of the parsers list by providing a way to add or remove parsers. This can be done by adding methods to the middleware that allow adding and removing parsers from the parsers list.

Possible high level code example

class CustomParserMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        # Add custom parsers here
        request.parsers.append(CustomParser())

        response = self.get_response(request)

        return response

Step 6: Document the changes and add appropriate tests
Finally, we’ll document the changes and add appropriate tests to ensure the new functionality is working as expected. We should test that the default JSONParser is able to parse JSON request bodies correctly, and that custom parsers added via middleware are able to parse request bodies of their specified content types.

Due to my beginner level understanding of the codebase there is a lot of scope room for improvement. Your suggestions willbe of great help.

@carltongibson If you can have a look at this and let me know that would be of great help!

Hi @Akash-Kumar-Sen — sorry for the slow reply. Life.

Do submit your proposals. Exact API details can be decided in the project phase. The goal here is for you to demonstrate a clear grasp of the issue.

Kind Regards,

Carlton