Error Received: Source.on is not a function

Hi @Akhil_Kulkarni

The reason why TypeError: source.on... error occurs in this context is primarily because formData accepts only String / Buffer / Stream types for its properties. A straightforward solution would be to convert it to one of those types. However, that leads us to couple of other issues

  • JSON.stringify() on file object is not going to work the way we expect and will technically result in an error
{"description":"Validation failed","errors":[{"field":"attachments",
"message":"It should contain elements of type valid file format only",
"code":"datatype_mismatch"}]}
  • The right choice would be to create a readable file stream. However, since our app runs in AWS lambda, maintaining files/assets inside the app won’t scale and would be technically challenging. If it were a local machine or a secure middleware running the logic, fs would be handy in creating a stream and it can be appropriately passed while making the call

As I see from your code, the intent is to attach a specific file during ticket creation. I just gave a shot with unirest NPM package - which has a simpler interface and also supports reading remote file streams. This also could keep the middleware lean. For example,

var unirest = require('unirest');

exports = {
  events: [{
    event: 'onAppInstall',
    callback: 'aiHandler'
  }],
  aiHandler: function (args) {
    /* Substitute with the right handler and event. This is just to demo */
    logger('--Inside App Install Handler--');
    logger(args);
    attFile();
    renderData();
  }
};

function attFile(){
  logger("--Let's attach a file --");
  var url = "https://xxx.freshdesk.com/api/v2/tickets";
  var apiKEY = "yyy";
  var headers = {
    "Content-Type": "multipart/form-data",
    "Authorization": "Basic " + apiKEY
  };
  var fields = {
    "description": "support ticket....",
    "subject": "support ticket...",
    "email": "example@example.com",
    "status":"2", // certain fields are required during creation
    "priority":"1"
  };
// Lets make use of unirest to attach files from our secure file store/s3/...
  unirest.post(url)
  .headers(headers)
  .field(fields)
  .attach('attachments[]', 'https://i.imgur.com/lcB62xb.jpg')
  .attach('attachments[]', 'https://gist.githubusercontent.com/hemchander23/6708ad5595dd56ef31087d47d4f96a44/raw/89ab0df9685cac94bbb88e1ebfd3655bcade6c9d/DarkS1E4_Script.txt#')
  .attach('attachments[]', 'https://www.gstatic.com/covid19/mobility/2020-05-25_US_Mobility_Report_en.pdf')
  .end(function(response){
    logger(response.body)
    logger("Response Status : " + response.status)
    if(response.status == 201){
      logger("Location Header : "+ response.headers['location'])
    }
    else{
      logger("X-Request-Id :" + response.headers['x-request-id']);
    }
  });
}


function logger(dat){
  console.log(dat);
}

will create a ticket like so:

It is very important to note that the file storage service that you use has to be secure and must generate short-lived (possibly signed as well) links that are only valid for the ticket creation session. Upon creation of the ticket, you will notice that the attachments have a link of their own.

3 Likes