lserni lserni - 1 month ago 9
Javascript Question

HTML form seems to be submitting *both* POST and GET?

This is not a duplicate of questions such as this, but rather the opposite: I have a form that I'm submitting via jQuery

$('<form>', {
action : 'service',
method : 'post',
target : '_blank'
}).append(
$('<input>', {
type : 'hidden',
name : 'payload',
value : JSON.stringify(payload)
})
).appendTo('body').submit().remove();


This is done so that I can open a different page with HTML.

Since I need to submit quite a lot of complex information, what I actually do is serialize them all into a big JSON string, then create a form with only one field ("payload") and submit that.

The receiving end has a filter that goes like this:


  • if the method is POST,

  • and there is only one submitted variable,

  • and the name of that one variable is "payload",

  • then JSON-decode its value and use it to create fake GET data.



So when the GET data grows too much I can switch methods without modifying the actual script, which notices no changes at all.

It always worked until today.

What should happen



The server should receive a single POST submission, and open the appropriate response in a popup window.

What actually happens instead



The server does receive the correct POST submission...

...apparently ignores it...

...and immediately after that, the browser issues a GET with no parameters, and it is the result of that parameterless GET that gets (pardon the pun) displayed in the popup window.

Quite unsurprisingly, this is always a "You did not submit any parameters" error. Duh.

What I already did




  • verified that this method works, and has always worked for the last couple of years with different forms and different service endpoints

  • tried replacing the form with a hardcoded
    <FORM>
    in HTML, without any jQuery whatsoever. Same results. So, this is not a jQuery problem.

  • tried with different browsers (it would not have helped if it only worked on some browsers: I need to support most modern browsers. However, I checked. Luckily, this failure reproduces in all of them, even on iPhones).

  • tried sending few data (just "{ test: 0 }").

  • tried halting the endpoint script as soon as it receives anything.

  • checked Stack Overflow. I found what seems to be the same problem, in various flavours, but it's of little comfort. This one has an interesting gotcha but no, it does not help.

  • checked firewalls, proxies, adblockers and plugins (I'm now using plain vanilla Firefox).

  • called the IT guys and asked pointed questions about recent SVN commits. There were none.



What I did not yet do




  • Check the HTTPS conversation at low level (I don't have sufficient access).

  • Compared the configuration, step by step, of a server where this works and the new server where it does not.

  • Quite clearly, put my thinking hat on. There must be something obvious that I'm missing and I'm setting myself up for a sizeable facepalm.


Answer

Use a tool like hurl.it or Postman to manually send a request to the server. The tools will nicely display the response from the server including all HTTP headers. I suspect the server responds with a redirect (Status code 30X) which leads to a GET request being issued after the POST completes.


Update: HTTP redirects

HTTP redirects do not necessarily use the same HTTP method or even the same data to issue a request to the redirect target. Especially for non-idempotent requests this could be a security issue (you don't generally want your form submission to be automatically re-submitted to another address). However, HTTP gives you both options:

[...] For this reason, HTTP/1.1 (RFC 2616) added the new status codes 303 and 307 [...], with 303 mandating the change of request type to GET, and 307 preserving the request type as originally sent. Despite the greater clarity provided by this disambiguation, the 302 code is still employed in web frameworks to preserve compatibility with browsers that do not implement the HTTP/1.1 specification.

[from Wikipedia: HTTP 302]

Also for 301s:

If the 301 status code is received in response to a request of any type other than GET or HEAD, the client must ask the user before redirecting.

[from Wikipedia: HTTP 301]

Comments