views:

1193

answers:

1

We're receiving some POST data of xml + arbitrary binary files (like images and audio) from a device that only gives us multipart/mixed encoding.

I've setup a cherrypy upload/POST handler for our receiver end. I've managed to allow it to do arbitrary number of parameters using multipart/form-data. However when we try to send the multipart-mixed data, we're not getting any processing.

@cherrypy.expose
def upload(self, *args,**kwargs):
    """upload adapted from cherrypy tutorials

    We use our variation of cgi.FieldStorage to parse the MIME
    encoded HTML form data containing the file."""

    print args   
    print kwargs

    cherrypy.response.timeout = 1300

    lcHDRS = {}
    for key, val in cherrypy.request.headers.iteritems():
        lcHDRS[key.lower()] = val
    incomingBytes = int(lcHDRS['content-length'])

    print cherrypy.request.rfile 

    #etc..etc...

So, when submitting multipart/form-data, args and kwargs are well defined.
args are the form fields, kwargs=hash of vars and values. When I submit multipart/mixed, args and kwargs are empty, and I just have cherrypy.request.rfile as the raw POST information.

My question is, does cherrypy have a built in handler to handle multipart/mixed and chunked encoding for POST? Or will I need to override the cherrypy.tools.process_request_body and roll my own decoder?

It seems like the builtin wsgi server with cherrypy handles this as part of the HTTP/1.1 spec, but I could not seem to find documentation in cherrypy in accessing this functionality.


...to clarify

I'm using latest version 3.1.1 or so of Cherrypy.

Making a default form just involves making parameters in the upload function.

For the multipart/form-data, I've been calling curl -F [email protected] -F param2=sometext -F [email protected] http://destination:port/upload

In that example, I get:

args = ['param1','param2','param3] 
kwargs = {'param1':CString<>, 'param2': 'sometext', 'param3':CString<>}

When trying to submit the multipart/mixed, I tried looking at the request.body, but kept on getting None for that, regardless of setting the body processing.

The input we're getting is coming in as this:

user-agent:UNTRUSTED/1.0 Profile/MIDP-2.0 Configuration/CLDC-1.1
content-language:en-US
content-length:565719
mime-version:1.0
content-type:multipart/mixed; boundary='newdivider'
host:192.168.1.1:8180
transfer-encoding:chunked



--newdivider
Content-type: text/xml

<?xml version='1.0' ?><data><Stuff>....
etc...etc...

--newdivider
Content-type: image/jpeg
Content-ID: file://localhost/root1/photos/Garden.jpg
Content-transfer-encoding: binary

<binary data>

I've got a sneaking suspicion that the multipart/mixed is the problem that cherrypy is just giving me just the rfile. Our goal is to have cherrypy process the body into its parts with minimal processing on the receive side (ie, let cherrypy do its magic). If that requires us being tougher on the sending format to be a content-type that cherrypy likes, then so be it. What are the accepted formats? Is it only multipart/form-data?

+2  A: 

My bad. Whenever the Content-Type is of type "multipart/*", then CP tries to stick the contents into request.params (if any other Content-Type, it goes into request.body).

Unfortunately, CP has assumed that any multipart message is form-data, and made no provision for other subtypes. I've just fixed this in trunk, and it should be released in 3.1.2. Sorry for the inconvenience. In the short term, you can try applying the changeset locally; see http://www.cherrypy.org/ticket/890.

fumanchu
Hey, thanks, that worked like a charm. Can pull all the parts from the cherrypy.request.params['parts'] with ease now. Thanks!
dmyung