Opened 12 years ago

Closed 9 years ago

#4314 closed defect (invalid)

Query parameters are not passed to the server with dojo.xhrPut()

Reported by: guest Owned by: James Burke
Priority: high Milestone: 1.0
Component: IO Version: 0.9
Keywords: xhrPut Cc:
Blocked By: Blocking:

Description (last modified by James Burke)

I was playing with dojo xhrPut(), xhrPost(), xhrDelete() and xhrGet() methods and found out that I am unable to retrieve parameters on the server if I use xhrPut(). For GET and DELETE method dojo takes parameters and ads them to url. It looks like it should do the same for PUT request.

From client I send a request:

  1. dojo.xhrPut({ url: "http://example.com/doItBabe",
  2. content: {param1:"value1", param2: "value2"},
  3. handleAs: "text",
  4. load: function(result){ alert (result); }
  5. });

on the server I retrieve param1:

String param1 = request.getParameter("param1");

I can get parameters for POST, GET and DELETE but not for PUT.

One way to fix that would be adding arguments to url as it is done in xhrGet and xhrDelete method. var dfd = _makeXhrDeferred(args);

dojo._ioAddQueryToUrl(dfd.ioArgs);

but I am not sure if that would be the right thing to do.

Attachments (3)

TestREST.html (1.4 KB) - added by guest 12 years ago.
Test page for sending POST, PUT, GET and DELETE requests
MyServlet.java (1.2 KB) - added by guest 12 years ago.
Java Sevlet for handling requests
TestREST.2.html (1.4 KB) - added by James Burke 12 years ago.
New TestREST.html file that works for me.

Download all attachments as: .zip

Change History (11)

Changed 12 years ago by guest

Attachment: TestREST.html added

Test page for sending POST, PUT, GET and DELETE requests

Changed 12 years ago by guest

Attachment: MyServlet.java added

Java Sevlet for handling requests

comment:1 Changed 12 years ago by guest

Behaviour is the same in FF and IE.

Changed 12 years ago by James Burke

Attachment: TestREST.2.html added

New TestREST.html file that works for me.

comment:2 Changed 12 years ago by James Burke

Milestone: 1.0
Resolution: invalid
Status: newclosed

I can't reproduce the problem. When I watch the HTTP requests in a proxy, like Charles, I see the parameters being sent in the body of the request. The Content-Type for the request is application/x-www-form-urlencoded, and the Content-Length seems correct too. The parameters are encoded in the normal way: name1=value1&name2=value2

I uploaded a new TestREST.html file that works for me. The original one did not, maybe it was just the URL.

comment:3 Changed 12 years ago by guest

Hi jburke

You are saying I see the parameters being sent in the body of the request. and I think that is the problem (maybe :). If the parameters in the PUT request are in the content, then Servlet is unable to retrieve them.

comment:4 Changed 12 years ago by James Burke

From what I understand, PUTs are similar to POSTs in the request construction, just a different HTTP method is used. So, just like A POST puts its parameters in the body of the request, I would expect it to be the same for PUTs.

It also seems to make sense from a REST perspective: you could potentially be PUTing a very large resource, some that may not fit on the limited size allowed for querystring parameters (as what happens in a GET).

This part of the <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.6">HTTP spec</a> seems to indicate that POST and PUT are very similar except for the meaning that is implied by the method name.

BTW, I've been calling a Java servlet-based API with PUTs via dojo.xhrPut and I have not noticed a problem. I'm not sure if there is a special config to tell a servlet to look in the body for request parameters with a PUT, as it does for POST requests.

comment:5 Changed 10 years ago by kolban

Resolution: invalid
Status: closedreopened

Folks, I too am suffering exactly the same problem ... What I want to do is send a PUT request to:

http://localhost:80/x/y/z?a=1&b=2

I coded:

dojo.xhrPut( {
   "url": "/x/y/z",
   content: {"a": "1", "b", "2"},
   timeout: 5000,
...

What I find is that the ?a=1&b=2 is NOT sent but instead the data is placed INSIDE the body of the HTTP request. These semantics seem to diverge from the other xhr* requests.

comment:6 Changed 10 years ago by James Burke

Description: modified (diff)
Resolution: invalid
Status: reopenedclosed

kolban: See my comment above your comment. It is proper HTTP semantics to place the content in the HTTP body for a PUT command. If you are using something like a servlet to read the response be sure to implement the doPut() method in your servlet.

comment:7 Changed 9 years ago by kolban

Resolution: invalid
Status: closedreopened

Guys ... sorry to be a pain on this. 19 months ago I worked in this area and was told that proper HTTP semantics was not to allow name/value pairs on an HTTP PUT request. I found I have the same need today. Have a look at this IBM URL for a REST request that they expose from one of their products:

http://publib.boulder.ibm.com/infocenter/dmndhelp/v7r0mx/topic/com.ibm.bspace.help.api.rest.doc/rest/wsprocessserver/rest_bpm_htm_v1_task_tkiid_put_complete.htm

If I am reading this correctly, it seems that this request is:

  1. An HTTP PUT
  2. Requires a name/value pair (in this case action=complete)

When I coded "content" in the xhrPut, the back-end REST request failed. When I explicitly coded "url....?action=complete" as the target URL it worked. So either IBM needs to change their REST request or Dojo needs a fix.

Neil

comment:8 Changed 9 years ago by James Burke

Resolution: invalid
Status: reopenedclosed

Right now there is no good way to specify some parameters that should go in the querystring (URL) and some parameters go in the body of an HTTP request. We default in Dojo to using one or the other based on accepted HTTP semantics, namely that POST and PUT should send content in the HTTP body.

So I am not sure what the fix would be without complicating the API for what seems like edge cases, improper use of query strings and bodies. Note that you can still use those kinds of APIs with Dojo's XHR calls, you just have to know what args go where, which is what you would have to do if we were to expose some API for you to target some parameters for the URL and some for the HTTP body.

This sort of use of Dojo APIs could help with the particular IBM example, and I do not believe it would be much different as far as the amount of typing if we were to support some API in dojo.xhr itself to do this work:

dojo.xhrPut({
    url: '/rest/bpm/htm/v1/task/someId?' +  dojo.objectToQuery({action: 'complete'}),
    putData: "<some xml string goes here>"
});

Using dojo.objectToQuery is the generic tool to use for this pattern, but for the specific IBM URL, since only "complete" is the only valid value, then you could just hardcode the "?action=complete" as part of the URL, which would be the most efficient as far as typing and runtime performance.

I am going to close this because I do not believe it is worth complicating the dojo.xhr APIs with some way to list both URL and body arguments when dojo.objectToQuery will do the job just as well for these cases. However, if you see a reason for otherwise, please feel free to reopen with more info and possibly ideas on how a change to the dojo.xhr* calls so as to not complicate the API.

Note: See TracTickets for help on using tickets.