views:

26

answers:

3

I'm trying to get a PUT request from Python into a servlet in Tomcat. The parameters are missing when I get into Tomcat.

The same code is happily working for POST requests, but not for PUT.

Here's the client:

lConnection = httplib.HTTPConnection('localhost:8080')
lHeaders = {"Content-type": "application/x-www-form-urlencoded",
              "Accept": "text/plain"}
lParams = {'Username':'usr', 'Password':'password', 'Forenames':'First','Surname':'Last'}
lConnection.request("PUT", "/my/url/", urllib.urlencode(lParams), lHeaders)

Once in the server, a request.getParameter("Username") is returning null.

Has anyone got any clues as to where I'm losing the parameters?

+1  A: 

I tried your code and it seems that the parameters get to the server using that code. Tcpdump gives:

PUT /my/url/ HTTP/1.1
Host: localhost
Accept-Encoding: identity
Content-Length: 59
Content-type: application/x-www-form-urlencoded
Accept: text/plain

Username=usr&Password=password&Surname=Last&Forenames=First

So the request gets to the other side correctly, it must be something with either tomcat configuration or the code that is trying to read the parameters.

Jari
+1  A: 

I'm guessing here, but I think the problem is that PUT isn't meant to be used that way. The intent of PUT is to store a single entity, contained in the request, into the resource named in the headers. What's all this stuff about user name and stuff?

Your Content Type is application/X-www-form-urlencoded, which is a bunch of field contents. What PUT wants is something like an encoded file. You know, a single bunch of data it can store somewhere.

Carl Smotricz
This is my first REST interface. Reading around, it looks like PUT should only be used for a complete replacement, where as what I'm trying to do here is update an existing user. POST is probably the way to go. Thanks. Was confused by the "RESTful web services" section at http://en.wikipedia.org/wiki/Representational_State_Transfer
Tim
Http method itself does not care about the content type, you can use PUT for whatever content type you like. For interface to be REST, you are right, it should replace all content in that resource, but nothing prevents you from using application/x-www-form-urlencoded content type for that.
Jari
+1  A: 

I don't know what the Tomcat side of your code looks like, or how Tomcat processes and provides access to request parameters, but my guess is that Tomcat is not "automagically" parsing the body of your PUT request into nice request parameters for you.

I ran into the exact same problem using the built-in webapp framework (in Python) on App Engine. It did not parse the body of my PUT requests into request parameters available via self.request.get('param'), even though they were coming in as application/x-www-form-urlencoded.

You'll have to check on the Tomcat side to confirm this, though. You may end up having to access the body of the PUT request and parse out the parameters yourself.

Whether or not your web framework should be expected to automagically parse out application/x-www-form-urlencoded parameters in PUT requests (like it does with POST requests) is debatable.

Will McCutchen
I think you're probably right with this. Not a big deal for me now - I'll switch to using POST for my needs.
Tim