question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Question: how to a POST with form-data correctly

See original GitHub issue

Hi,

So my question is how I would implement the following (with request) using isomorphic-fetch

var options = {
    url: authUrlRoot + 'auth',
    followRedirect: false,
    form: {
      client_id: config.APP_KEY,
      redirect_uri: config.REDIRECT_URL,
      response_type: "code"
    }
  };

  request.post(options, function(error, httpResponse, body){
    // Do something here..
  });

I’ve tried something like

var FormData = require('form-data');
var form = new FormData();
form.append('client_id', config.APP_KEY);
form.append('redirect_url', config.REDIRECT_URL);
form.append('response_type', 'code');
fetch(authUrlRoot + 'auth', { method: 'POST', body: form })
    .then(function(response) {
        if (response.status >= 400) {
            throw new Error("Bad response from server");
        }
        return response.json();
    })
    .then(function(data) {
        console.log(data);
    });

But that gives me “Bad response from server” - status code is 400 Bad request. I might be totally blind, but I cannot seem to figure out what is missing?

Issue Analytics

  • State:closed
  • Created 8 years ago
  • Reactions:18
  • Comments:8

github_iconTop GitHub Comments

66reactions
tracker1commented, Oct 20, 2015

The spec says you pass the FormData instance as the body…

fetch("/login", {
  method: "POST",
  body: form  //just pass the instance
})

You may need additional parameters, depending on your use…

fetch(url, {
  credentials: 'include', //pass cookies, for authentication
  method: 'post',
  headers: {
  'Accept': 'application/json, application/xml, text/plain, text/html, *.*',
  'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8'
  },
  body: form
});

Or you can manually encode your data, example below will take an object… (NOTE: ES6 syntax)

//post-as-form.js

// npm module - safe deep cloning
import clone from 'safe-clone-deep'

export {postAsForm as default};

async function postAsForm(url, data) {
  var response;
  try {
    //safe clone of data
    data = clone(data);

    //array that holds the items that get added into the form
    var form = [];

    //special handling for object/array data, arrays will use "model" as the container ns
    addItemsToForm(form, typeof data == 'object' ? [] : [options.name || 'model'], data);

    //you'll need to await on response.text/blob/json etc
    var response = await fetch(url, {
          credentials: 'include', //pass cookies, for authentication
          method: 'post',
          headers: {
          'Accept': 'application/json, application/xml, text/play, text/html, *.*',
          'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8'
          },
          body: form.join('&')
      });

    //return plain text as-is, don't parse it here
    return {
      response: response,
      text: await response.text()
    }
  } catch(err) {
    //console.error("Error from server:", err && err.stack || err);
    err.response = response;
    throw err;
  }
}

function addItemsToForm(form, names, obj) {
  if (obj === undefined || obj === "" || obj === null) return addItemToForm(form, names, "");

  if (
    typeof obj == "string" 
    || typeof obj == "number" 
    || obj === true 
    || obj === false
  ) return addItemToForm(form, names, obj);

  if (obj instanceof Date) return addItemToForm(form, names, obj.toJSON());

  // array or otherwise array-like
  if (obj instanceof Array) {
    return obj.forEach((v,i) => {
      names.push(`[${i}]`);
      addItemsToForm(form, names, v);
      names.pop();
    });
  }

  if (typeof obj === "object") {
    return Object.keys(obj).forEach((k)=>{
      names.push(k);
      addItemsToForm(form, names, obj[k]);
      names.pop();
    });
  }
}

function addItemToForm(form, names, value) {
  var name = encodeURIComponent(names.join('.').replace(/\.\[/g, '['));
  value = encodeURIComponent(value.toString());
  form.push(`${name}=${value}`);
}
19reactions
amalvcommented, Apr 10, 2017

Regarding @tracker1 response I think you should use URLSearchParams instead of FormData when using application/x-www-form-urlencoded;charset=UTF-8 as Content-Type header, as indicated in the fetch documentation or the fetch specs

Read more comments on GitHub >

github_iconTop Results From Across the Web

Sending form data - Learn web development | MDN
As we'd alluded to above, sending form data is easy, but securing an application can be tricky. Just remember that a front-end developer...
Read more >
Formdata not added properly to the post request
I found the answer: Drop the Content-Type in the headers. In this case dropping the headers at all, solved the problem.
Read more >
FormData - The Modern JavaScript Tutorial
This chapter is about sending HTML forms: with or without files, with additional fields and so on. FormData objects can help with that....
Read more >
Sending Form Data - Questions - n8n community
Simply create everything normally. Then add on the HTTP Request-Node under options “Body Content Type” and select “Form-Data Multipart”. It ...
Read more >
How to use fetch to POST form data as JSON to your API
The FormData API is natively supported by most modern browsers and provides a straightforward way of accessing the values for all the fields...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found