Search code examples
cherrypy

Why is the request body blank when the content-type is application/x-www-form-urlencoded?


I am receiving a request with content-type application/x-www-form-urlencoded. When I try to read the body of the request using cherrypy.request.body.read() the results is b''.

I seem to be able to access the request form parameters using any of these:

cherrypy.request.params

cherrypy.request.body.params

cherrypy.request.body.request_params

But this is inconvenient for my use case, I want to be able to obtain the raw request body regardless of content-type. Also the above 3 give me a dictionary, which isn't the exact format that the request had in its body. Is there a way to do that with cherrypy? Or is this functionality hidden?


Solution

  • Not sure what are you trying to accomplish by not using the already parsed body that correspond to the defined Content-Type... but you can process the body of the request yourself configuring: cherrypy.request.process_request_body = False and read the body with something like:

    cherrypy.request.rfile.read(cherrypy.request.headers['Content-Length'])
    

    For more information see: https://github.com/cherrypy/cherrypy/blob/master/cherrypy/_cprequest.py#L292-L315

    Fragment of relevant parts of that url:

    rfile = None
    """
    If the request included an entity (body), it will be available
    as a stream in this attribute. However, the rfile will normally
    be read for you between the 'before_request_body' hook and the
    'before_handler' hook, and the resulting string is placed into
    either request.params or the request.body attribute.
    You may disable the automatic consumption of the rfile by setting
    request.process_request_body to False, either in config for the desired
    path, or in an 'on_start_resource' or 'before_request_body' hook.
    WARNING: In almost every case, you should not attempt to read from the
    rfile stream after CherryPy's automatic mechanism has read it. If you
    turn off the automatic parsing of rfile, you should read exactly the
    number of bytes specified in request.headers['Content-Length'].
    Ignoring either of these warnings may result in a hung request thread
    or in corruption of the next (pipelined) request.
    """
    
    process_request_body = True
    """
    If True, the rfile (if any) is automatically read and parsed,
    and the result placed into request.params or request.body.
    """
    
    body = None
    """
    If the request Content-Type is 'application/x-www-form-urlencoded'
    or multipart, this will be None. Otherwise, this will be an instance
    of :class:`RequestBody<cherrypy._cpreqbody.RequestBody>` (which you
    can .read()); this value is set between the 'before_request_body' and
    'before_handler' hooks (assuming that process_request_body is True."""