COMMUNITY

[tink_http] Is it possible to use a `FormData` object as body of a `Client.fetch` request?

In plain JavaScript, it’s very handy to pass a FormData or URLSearchParams object as body of a XMLHttpRequest.send() or window.fetch() call.

With Tink HTTP client, it seems that the body can only be a haxe.io.Bytes or String object.
URLSearchParams objects can be serialized to string with the toString() method, but FormData objects provide no way to serialize them.

Does anyone known if it is possible to use FormData objects, and how, with the Tink HTTP client?
(the compilation target is JavaScript)

Is the data necessarily FormData? If so, I guess this is the best way to transform it:

import tink.multipart.Multipart;
import js.html.File;
import js.html.*;

using tink.io.Source;

function tinkify(data:FormData):IdealSource {
  var builder = new Multipart();
  data.forEach((entry:haxe.extern.EitherType<String, File>, name:String)->
    switch Std.downcast(entry, File) {
      case null:
        builder.addValue(name, entry);
      case file:
        builder.addFile(name, file.name, file.type, Source.ofJsFile(name, file).idealize(e -> Source.EMPTY));
    }
  );

  return builder.toIdealSource();
}

Little warning: not 100% about the signature of FormData::forEach. You’ll need to double check that :wink:

1 Like

That’s not completely true: if the form does not contain any file input, we can use the URLSearchParams constructor (alongside the application/x-www-form-urlencoded content type): see FormData.

import js.Browser.document;
import js.html.*;

final formData = new FormData(cast(document.querySelector("form"), FormElement));
final requestBody = new URLSearchParams(cast formData).toString();

The signature is OK. As usual, thanks a lot @back2dos! That’s exactly what I needed. :tada: