Jaafar Abazid
Jaafar Abazid

Reputation: 142

Pipe GET response to POST request as form-data

I'm trying to read a video file from a URL (Amazon CloudFront) and stream it (upload it) with a POST request to Dailymotion using a NodeJS Lambda function.

Here's the code that I have:

https.get(
  'https://cdn.mysite.com/video.mp4',
  videoStream => {
    videoStream.pipe(
      https.request(
        'https://upload-xx.xxx.dailymotion.com/upload?uuid=xxxxx&seal=xxxxx&extra=xxxxx', {
        method: 'POST',
        headers: {
          'Content-Type': 'multipart/form-data',
        },
        body: {
          'Content-Disposition': 'form-data',
          'Content-Type': 'video/mp4',
          'file': videoStream
        }
      },
      (response) => {
        console.log('statusCode   :', response.statusCode);
        console.log('statusMessage:', response.statusMessage);
      })
    );
  },
  (response) => {
    console.log(response);
  }
);

Using the code above, I'm always getting this response from Dailymotion:

statusCode   : 422
statusMessage: Unproccessable Entity

Based on Dailymotion documentation:

The video can actually be uploaded to the upload_url retrieved above by making a POST HTTP request using the multipart/form-data content type. The video data has to be contained in a file field.

How can I pass the piped chunks as form-data to the POST request?

Upvotes: 1

Views: 1739

Answers (1)

Jaafar Abazid
Jaafar Abazid

Reputation: 142

I found a solution using request and form-data libraries. Just:

  1. Created a new form.
  2. Appended the file to the form as a stream using request.
  3. Submit the form.
  4. Wait for the upload to end to send the callback back to the caller with the response.

If the file was uploaded successfully, the upload server will return a JSON object containing several fields, the only field you need to publish the video is the url one.

Here's a working copy of my Lambda function code:

import request from 'request';
import FormData from 'form-data';

export const handler = (event, context, callback) => {
  const form = new FormData();
  form.append('file', request('https://cdn.mysite.com/video.mp4'));
  form.submit({
    host: 'upload-XX.dcX.dailymotion.com',
    path: '/upload?uuid=XXXXX&seal=XXXXX&extra=XXXXX'
  }, (error, response) => {
    if (error) throw error;
    let body = '';
    response.on('data', chunk => {body += chunk.toString()});
    response.on('end', () => {callback(null, JSON.parse(body))});
    response.resume();
  });
};

Update

Another solution using the https native module of Nodejs instead of the deprecated request library:

import https from 'https';
import FormData from 'form-data';

export const handler = (event, context, callback) => {
  const form = new FormData();
  https.get('https://cdn.mysite.com/video.mp4', response => {
    form.append('file', response);
    form.submit(
      {
        host: 'upload-XX.dcX.dailymotion.com',
        path: '/upload?uuid=XXXXX&seal=XXXXX&extra=XXXXX'
      },
      (error, response) => {
        if (error) callback(error);
        let body = '';
        response.on('data', chunk => body += chunk.toString());
        response.on('end', () => callback(null, JSON.parse(body)));
        response.resume();
      }
    );
  });
};

Upvotes: 1

Related Questions