1
votes

We have a client api call that requires a post be sent as form-data. When we run the call through Chrome's Postman extension it runs successfully when we specify form-data, and returns an error if we specify x-www-form-urlencoded. This is expected.

However when trying to run in node.js using the "request" npm package to handle the post we continue to receive an error message from the api which unfortunately does not give us specifics as to what is wrong. But we do see that the request header object looks like this when it goes out:

_header: 'POST /api/client/coupon/add HTTP/1.1\r\nAuthorization: Basic [auth string redacted]\r\nhost: beta1.client.com\r\ncontent-type: application/x-www-form-urlencoded\r\ncontent-length: 172\r\nConnection: keep-alive\r\n\r\n',

Our Node.js code looks like:

  //Create the coupon
  var coupon = { code: "abcde1234"),
    discount: "33",
    type: "percent"
  }

  var request = require('request');
  request.post(
    {
      url: "https://beta1.client.com/api/coupon/add",
      headers: {
        "authorization": auth,
        "content-disposition": "form-data; name='data'"
      },
      form: coupon
    },

    function (error, response, body) {
      if (!error && response.statusCode == 200) {
        console.log(body)
      }
    }
  );

What I am wondering is why the content-type header continues to read "application/x-www-form-urlencoded" when we have provided a content-disposition of 'form-data'. To me it seems like if I could remove the content-type header attribute it should work - but how to do that?

Any insights would be appreciated.

2

2 Answers

2
votes

The reason why it is updating the Content-Type header to application/x-www-form-urlencoded is because you are using form in your POST request.

request.post({
  url: "https://beta1.client.com/api/coupon/add",
  headers: {
    "authorization": auth,
    "content-disposition": "form-data; name='data'"
  },
  form: coupon
}, function (error, response, body) {
  ...
});

In order to handle this, you need to add the content as body as provided below.

request.post({
  url: "https://beta1.client.com/api/coupon/add",
  headers: {
    "authorization": auth,
    "content-disposition": "form-data; name='data'"
  },
  body: coupon
}, function (error, response, body) {
  ...
});
1
votes

In the end we went with the form-data package found here: https://www.npmjs.com/package/form-data

Our code now looks like this:

    //create coupon json and stringify it
    var coupon = {
      coupon: {
        code: couponCode,
        discount: discountPercentage,
        type: 'percent',
        product: productId,
        times: 1,
        expires: couponExpiresDt
      }
    };
    var couponString = JSON.stringify(coupon);

    //create form-data object to be posted to client api
    var FormData = require('form-data');
    var couponForm = new FormData();
    couponForm.append('data', couponString);

    //create submission options for the post
    var submitOptions = {
      hostname:config.client_api_host,
      path:'/api/2/coupon/add',
      auth:auth,
      protocol:'https:'
    };

    //submit the coupon/add post request
    couponForm.submit(submitOptions, function(err, res) {
      res.resume();

      if (err) {
        callback(err);
      } else if (res.statusCode != 200) {
        callback(new Error('API createDiscount post response error:', res.statusCode));
      } else {
        logger.log('info', "coupon code " + couponCode +  " has apparently been created");
        callback(null, {coupon_code: couponCode, expires: couponExpiresDt});
      }
    });