Request body of PUT with no Content-Type is processed incorrectly by CP3 (CP2 does it right)

6 views
Skip to first unread message

Chris Miles

unread,
Feb 19, 2008, 6:01:59 AM2/19/08
to cherrypy-devel
I'm porting a CP2 app to CP3 (3.1.0beta3) and have an issue with CP3
Request.process_body() attempting to parse params from the request
body of a PUT request with no "Content-Type" header defined, which
wasn't how CP2 behaved in the same situation.

Given this super simple CP3 test app:
{{{
import cherrypy
class Root(object):
@cherrypy.expose
def upload(self):
return "Upload OK"
cherrypy.quickstart(Root())
}}}

If I create a PUT request to /upload, with no "Content-Type" header
defined, then CP3 attempts to parse the request body (which, in my
case, contains binary data, but that doesn't matter) into params, and
the request fails because the params cannot be mapped to method
arguments (which you can examine by defining upload(self, *args,
**kwargs)) which is not what would be expected. Compare this with the
same app running under CP2 and the request body is not parsed.

If I create a PUT request with any "Content-Type" (besides
"application/x-www-form-urlencoded" and similar) then the request
works properly (CP3 doesn't attempt to parse the request body).

If I create a PUT request with "Content-Type: application/x-www-form-
urlencoded" then CP3 does attempt to parse the request body (as I
would expect).

Here's some examples of the above behaviour using curl (error
responses truncated):
{{{
$ curl --upload-file ~/tmp/foo.tmp http://localhost:8080/upload
TypeError: upload() got an unexpected keyword argument 'test file.
# (works with CP2)

$ curl --header "Content-Type: foo/bar" --upload-file ~/tmp/foo.tmp
http://localhost:8080/upload
Upload OK

$ curl --header "Content-Type: application/x-www-form-urlencoded" --
upload-file ~/tmp/foo.tmp http://localhost:8080/upload
TypeError: upload() got an unexpected keyword argument 'test file.
}}}

I'd like to see the behaviour changed back to only attempting to parse
the request body if a valid form-like "Content-Type" (like
"application/x-www-form-urlencoded") is supplied, for a few reasons:

1. Request.body_params__doc (and Request.body__doc) indicate that this
is how it should behave, i.e. body_params: "If the request Content-
Type is 'application/x-www-form-urlencoded' or multipart, this will be
a dict of the params pulled from the entity body"; and body: "If the
request Content-Type is 'application/x-www-form-urlencoded' or
multipart, this will be None. Otherwise, this will contain the request
entity body as a string"

2. The request body should be left alone unless the Content-Type
indicates that it contains encoded parameters or multipart data.

3. This is how it worked in CP2.

In the case of my application, I don't want to force my users to
supply a Content-Type with their PUT request, when they didn't need to
before (doing so is optional).

If this is reasonable, I'm happy to create a ticket (and possibly a
patch) for CP3.

Cheers,
Chris Miles

Robert Brewer

unread,
Feb 19, 2008, 1:52:06 PM2/19/08
to cherryp...@googlegroups.com

Sounds good to me. RFC 2616 says:

Any HTTP/1.1 message containing an entity-body SHOULD include a
Content-Type header field defining the media type of that body. If
and only if the media type is not given by a Content-Type field, the
recipient MAY attempt to guess the media type via inspection of its
content and/or the name extension(s) of the URI used to identify the
resource. If the media type remains unknown, the recipient SHOULD
treat it as type "application/octet-stream".

...which I read as: let the app decide since we don't want to get into
sniffing.

> If this is reasonable, I'm happy to create a ticket (and possibly a
> patch) for CP3.

Please do! :)


Robert Brewer
fuma...@aminus.org

Sylvain Hellegouarch

unread,
Feb 19, 2008, 2:54:42 PM2/19/08
to cherryp...@googlegroups.com

> Sounds good to me. RFC 2616 says:
>
> Any HTTP/1.1 message containing an entity-body SHOULD include a
> Content-Type header field defining the media type of that body. If
> and only if the media type is not given by a Content-Type field, the
> recipient MAY attempt to guess the media type via inspection of its
> content and/or the name extension(s) of the URI used to identify the
> resource. If the media type remains unknown, the recipient SHOULD
> treat it as type "application/octet-stream".
>
> ...which I read as: let the app decide since we don't want to get into
> sniffing.
>
>

Indeed. However Chris, note that in the IETF language, a SHOULD is a
very strong requirement. They seldom use MUST but SHOULD means "we know
there are some cases where it won't be suitable but those should be rare
enough". I would invite you Chris to get the habit of sending the
content-type (you could actually hit some intermediairies that would get
you into trouble as well without that header).

- Sylvain

Chris Miles

unread,
Feb 20, 2008, 3:39:05 AM2/20/08
to cherryp...@googlegroups.com, Chris Miles

Ticket created with patch attached. http://www.cherrypy.org/ticket/790

Cheers,
Chris Miles

Chris Miles

unread,
Feb 20, 2008, 3:41:06 AM2/20/08
to cherryp...@googlegroups.com, Chris Miles

Good point Sylvain. We actually encourage our clients to define a
Content-Type, but we also make sure we handle cases where they leave
it out.

Cheers,
Chris Miles

Reply all
Reply to author
Forward
0 new messages