Wassily
Wassily

Reputation: 162

Sending Form Data with the native node module

for my current project I have to send form-data from my lambda function to an api endpoint. The api endpoint essentially expects two images (that it compares with one another) and a key. As mentioned before, I somehow seem unable to send the correct form-data to the api endpoint. I checked out postman, and it seems to have worked alright, but something doesn't seem to work in my function. I presume it must be related the form-data string that I'm sending. Below you can find a shortened version of the function (I excluded the two image files), but somehow I'm getting an error back telling me that the api cannot read the key property:

const http = require('http');
const https = require('https');
const httpPromise = (protocol, params, postData) => {
    return new Promise((resolve, reject) => {
        const requestModule = protocol === 'http' ? http : https;
        const req = requestModule.request(params, res => {
            // grab request status
            const statusCode = res.statusCode;
            if(statusCode < 200 || statusCode > 299) {
                throw new Error('Request Failed with Status Code:', statusCode);
            }

            let body = '';
            // continuosly update data with incoming data
            res.setEncoding('utf8');
            res.on('data', data => body += data);

            // once all data was received
            res.on('end', () => resolve(body));
        })

        // write data to a post request
        if(typeof(params.method) === 'string' && params.method === 'POST' && postData) {
            req.write(postData)
        }


        // bind to the error event
        req.on('error', err => reject(err));

        // end the request
        req.end();
    })
}

const controller = async () => {
    const apiKey = "00000000";
    const options = {
        hostname: '***"
        port: 80,
        path: '***'
       method: 'POST',
       headers: {"content-type": "multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW"}
    }
    const postData = "------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"key\"\r\n\r\00000000\r\n------WebKitFormBoundary7MA4YWxkTrZu0gW--"
    let result = await httpPromise('http', options, postData)
    console.log(result);
}

yeah, so somehow it just doesn't seem to recognise the key in the postData string. I have tried various different combinations but just can't seem to get this to work.

Upvotes: 0

Views: 1558

Answers (2)

Wassily
Wassily

Reputation: 162

Alright, so for anyone who might also face the same issue, it took me a little but figured out what the issue was. I didn't set the Content-Length header, which then in turn meant that node automatically added the Transfer-Encoding Header and set its value to chunk. This broke the receiving api and resulted in the issue. Setting the Content-Length header to the correct length and setting the Transfer-Encoding Header to an empty string solved my issue here (but I think one could also simply omit the transfer-encoding header once you defined the Content-Length Header).

Upvotes: 1

Shyam Seshadri
Shyam Seshadri

Reputation: 341

The default http and https libraries are kind of wordy and annoying.

Would recommend using the request library instead. Read more here

In which case, to make the request, you can simply write it as :

var request = require('request');

var formData = {
  // Pass a simple key-value pair
  my_field: 'my_value',
}

request.post({url:'http://service.com/upload', formData: formData}, (err, response, body) => {
   // Handle response here
});

Upvotes: 1

Related Questions