FormData and URLSearchParams on form-urlencoded in XHR


#1

explain my motivation

I think FormData API is very useful when I send File via XHR in multipart/form-data. but in case of sending text key-value to server, it’s better to send with them in x-www-form-urlencoded body.

for example from http://www.html5rocks.com/ja/tutorials/file/xhr2/

function sendForm() {
  var formData = new FormData();
  formData.append('username', 'johndoe');
  formData.append('id', 123456);

  var xhr = new XMLHttpRequest();
  xhr.open('POST', '/server', true);
  xhr.onload = function(e) { ... };

  xhr.send(formData);
}

in this case, payload became a multipart/form-data. and I think a lot of server receiving like these data, expects x-www-form-urlencoded. (ex. many of oauth server)

of course we can do that via URLSearchParams. but how about this case ?

from http://www.html5rocks.com/ja/tutorials/file/xhr2/

<form id="myform" name="myform" action="/server">
  <input type="text" name="username" value="johndoe">
  <input type="number" name="id" value="123456">
  <input type="submit" onclick="return sendForm(this.form);">
</form>
function sendForm(form) {
  var formData = new FormData(form);

  formData.append('secret_token', '1234567890'); // Append extra data before send.

  var xhr = new XMLHttpRequest();
  xhr.open('POST', form.action, true);
  xhr.onload = function(e) { ... };

  xhr.send(formData);

  return false; // Prevent page from submitting.
}

this is very convenient, but we can’t do that with URLSearchParams(means x-www-form-urlencoded).

opinion

I guess this design based on "blob can’t send via x-www-form-urlencoded so how about think about way to send Form which only includs “form-urlencodable texts” via x-www-form-urlencoded ?

idea1: URLSearchParams construct with Form

var params = new URLSearchParams(document.getElementById("text-only-form"));
xhr.send(params.toString());

idea2: get URLSearchParams from FormData.

var params = new FormData(form).params; // get from FormData
var params = new URLSearchParams(formData); // construct with FormData

idea3: send FormData with form-urlencodable text only falls back to x-www-form-urlencoded no multipar/form-data

var formData = new FormData();
formData.append('username', 'johndoe');
formData.append('id', 123456);
xhr.send(formData); // x-www-formurlencoded

idea4: xhr2 respects Content-Type header

I think sending XHR ignores content-type header when sending FormData. so respect it.

xhr.setRequestHeader( 'Content-Type', 'application/x-www-form-urlencoded' );
var formData = new FormData();
formData.append('username', 'johndoe');
formData.append('id', 123456);
xhr.send(formData); // x-www-formurlencoded

if FormData includes Blob props, one of fallback way is encode in BASE64 for example.

wrapup

I wanna send form-urlencoded using URLSearchParams or FormData construct from plain text only .

thanks and sorry for my poor english ;p

Jxck


#2

Sounds like a good library to write! I hope you write it and share it here!


#3

Yes, please!

So tired of having to half ass implement form serialization in various libraries. This would really help obsolete the need for $.serializeArray


#4

The extended FormData APIs now being implemented might help here.

https://chromium.googlesource.com/chromium/blink/+/0f4632bca55675b72e3e03a8d231c2e879276a02

I’m really hoping this is eventually covered by browser api. Defining helps explain how the existing form serialization process already works. @domenic hoping you get around to "<form> as a custom element" soon to hit all these pain points :wink:


#5

So this is basically asking for new URLSearchParams(HTMLFormElement) correct? I filed https://www.w3.org/Bugs/Public/show_bug.cgi?id=27941 to get this in the specification. Makes sense to me to get parity with FormData.


#6

:heart_eyes: I would love that.


#7

Yes that seems cool :slight_smile:


#8

Has a solution ever been made to the above? I tried do a for(var name in formData) and all I get is the members of the FormData class: append, etc.