NodeJs FormData & Axios

I can’t seem to get this working correctly. Since the api requires that post requests be made with form data and node does not support FormData(), I imported form-data from form-data - npm. Then using axiosjs to make the request, my code looks like this…

import { FlightAwareNotification, FlightAwareCredentials } from './models/flightaware';
import { Trip, MilestoneTypes } from './models/trips.model';
import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin'
import axios from 'axios';
import * as FormData from 'form-data';

admin.initializeApp();

const urls = {
    inFlightInfo: FlightAwareCredentials.url + 'InFlightInfo',
    mapFlight: FlightAwareCredentials.url + 'MapFlight',
    setAlert: FlightAwareCredentials.url + 'SetAlert',
}

const AUTH_ENCODED = Buffer.from(`${FlightAwareCredentials.user}:${FlightAwareCredentials.password}`).toString('base64');

export const setFlightAwareAlert = functions.https.onRequest(async (request, response) => {
    const body: {[key: string]: any} = request.body;
    const data = new FormData();
    Object.keys(body).forEach(key => data.append(key, body[key]));
    let alert_id;
    try {
        alert_id = await axios({
            url: urls.setAlert,
            method: 'post',
            data: data,
            headers: {
                'Content-Type': 'application/json',
                'Authorization': `Basic ${AUTH_ENCODED}`,
            },
            withCredentials: true,
        });
    } catch(err) {
        console.log(err)
    }
    response.json(alert_id && alert_id.data);
});

When I send the request, the response is "error": "MISSING: no {channels} specified" Which indicates it’s not getting the form data correctly.

So I tried console logging data and it looks like this…

info: FormData {
  _overheadLength: 639,
  _valueLength: 97,
  _valuesToMeasure: [],
  writable: false,
  readable: true,
  dataSize: 0,
  maxDataSize: 2097152,
  pauseStreams: true,
  _released: false,
  _streams: 
   [ '----------------------------992898597909585809439236\r\nContent-Disposition: form-data; name="alert_id"\r\n\r\n', '0',
     [Function: bound ],
     '----------------------------992898597909585809439236\r\nContent-Disposition: form-data; name="channels"\r\n\r\n', '{16 e_filed e_departure e_arrival e_diverted e_cancelled}',
     [Function: bound ],
     '----------------------------992898597909585809439236\r\nContent-Disposition: form-data; name="date_end"\r\n\r\n', '1551056400000',
     [Function: bound ],
     '----------------------------992898597909585809439236\r\nContent-Disposition: form-data; name="date_start"\r\n\r\n', '1551056400000',
     [Function: bound ],
     '----------------------------992898597909585809439236\r\nContent-Disposition: form-data; name="ident"\r\n\r\n', 'DAL123456',
     [Function: bound ],
     '----------------------------992898597909585809439236\r\nContent-Disposition: form-data; name="origin"\r\n\r\n', 'KDTW',
     [Function: bound ] ],
  _currentStream: null,
  _boundary: '--------------------------992898597909585809439236' }

If anyone has experience with a better way to get this done in node, I would REALLY appreciate it.

That Form-Data package appears to be sending multipart messages, which is not what you want.

You need to ensure that the Content-Type header of your request is application/x-www-form-urlencoded. And then your body needs to be URL encoded combination of all arguments (key1=value1&key2=value2&key3=value3).

Rather than trying to POST the data, you may also supply all of the function arguments in the URL as a GET request. That method is typically easier to debug as well, since you can more easily inspect the arguments in request logs.

Have you considered starting with the Node.JS example that we have on our FlightXML2 documentation page? Scroll down to the “Examples (REST / JSON)” section and click on the " “Show example (Node.js)” link. https://flightaware.com/commercial/flightxml/documentation2.rvt