I have an Azure Function that receives File uploads to the endpoint and am trying to repost that file to another endpoint microservice which handles the file using Axios. I am receiving an error to the effect of source.on is not a function when trying to add formData to the ocrServicePromise.
Any ideas on what's wrong?
Error is: [10/26/2020 2:06:27 PM] Executed 'Functions.ReceiveInboundFax' (Failed, Id=0a7bb949-9ff8-4762-8c21-ba2177ba96e2) [10/26/2020 2:06:27 PM] System.Private.CoreLib: Exception while executing function: Functions.ReceiveInboundFax. System.Private.CoreLib: Result: Failure [10/26/2020 2:06:27 PM] Exception: TypeError: source.on is not a function [10/26/2020 2:06:27 PM] Stack: TypeError: source.on is not a function
import { AzureFunction, Context, HttpRequest } from "@azure/functions"
import * as multipart from 'parse-multipart';
import axios from 'axios';
import { OcrStatusResponse } from "./classes/OcrStatusResponse";
import { ApolloClient } from 'apollo-client';
import { InMemoryCache } from 'apollo-cache-inmemory';
import gql from 'graphql-tag';
import fetch from 'node-fetch';
import { createHttpLink } from "apollo-link-http";
const httpTrigger: AzureFunction = async function (context: Context, req: HttpRequest): Promise<void> {
const body = req.rawBody;
// Retrieve the boundary id
const boundary = multipart.getBoundary(req.headers["content-type"]);
let logEntries = [];
if (boundary) {
const files: File[] = multipart.Parse(Buffer.from(body), boundary);
if (files && files.length > 0) {
var allUpdated = await Promise.all(files.map(async (file) => {
//CallOcrService
var ocrresult = await CallOcrService(context, file);
//Write to Hasura
logEntries.push(await LogOcrRequest(context, ocrresult, file.name));
}));
}
}
context.res = {
status: 200,
body: logEntries
}
};
async function CallOcrService(context: Context,file : File) : Promise<OcrStatusResponse>{
const FormDataFile = require('form-data');
const formData = new FormDataFile();
formData.append("file", file)
const ocrServicePromise = await axios.post(process.env["Ocr_Service_Upload_Endpoint"], formData, {
headers: formData.getHeaders()
})
.then((response) => {
const ocrSeriviceResponse = new OcrStatusResponse(response.data);
ocrSeriviceResponse.status = response.data.state;
return ocrSeriviceResponse;
}, (error) => {
context.log.error(error);
throw new Error(error);
}
);
return ocrServicePromise;
}
async function LogOcrRequest(context: Context, ocrResponse: OcrStatusResponse, filename: String){
const headers = {
"content-type": "application/json",
"x-hasura-admin-secret": process.env["ATTACHMENT_API_ADMIN_SECRET"]
}
const client = new ApolloClient({
link: createHttpLink({
uri:
process.env["ATTACHMENT_API_ENDPOINT"],
headers:headers,
fetch:fetch
}),
cache: new InMemoryCache()
});
const ocr_deadline = dateAdd(new Date(), "minute", 20);
const mutationInsertObj = {
date_time_received: new Date(),
file_name_received: filename,
ocr_job_id: ocrResponse.jobid,
date_time_ocr_response_deadline : ocr_deadline,
ocr_result_statuscheck_endpoint : ocrResponse.status_url,
ocr_result : ocrResponse.status,
ocr_document_endpoint: `${process.env["Ocr_Service_Upload_Document_Retrival_Endpoint"]}/${ocrResponse.jobid}/${ocrResponse.jobid}.pdf`
}
if(!ocrResponse.success){
context.log.error(`Response was empty or did not receive a status url for ${filename}`);
mutationInsertObj.ocr_result = "ERROR";
}
const insertMutation = gql `
mutation InsertOcrRequest($ocrResponse: inbound_fax_insert_input!) {
insert_inbound_fax_one(
object: $ocrResponse
) {
inboundfaxid
ocr_job_id
ocr_result_statuscheck_endpoint
ocr_result
date_time_ocr_response_deadline
ocr_document_endpoint
}
}
`;
const {errors,data} = await client.mutate({
mutation: insertMutation,
errorPolicy: 'all',
variables: mutationInsertObj
});
if(errors!== undefined){
const errorList = [];
errorList.push(errors);
return errorList;
}
return data;
}
function dateAdd(date, interval, units) {
if(!(date instanceof Date))
return undefined;
var ret = new Date(date);
var checkRollover = function() { if(ret.getDate() != date.getDate()) ret.setDate(0);};
switch(String(interval).toLowerCase()) {
case 'year' : ret.setFullYear(ret.getFullYear() + units); checkRollover(); break;
case 'quarter': ret.setMonth(ret.getMonth() + 3*units); checkRollover(); break;
case 'month' : ret.setMonth(ret.getMonth() + units); checkRollover(); break;
case 'week' : ret.setDate(ret.getDate() + 7*units); break;
case 'day' : ret.setDate(ret.getDate() + units); break;
case 'hour' : ret.setTime(ret.getTime() + units*3600000); break;
case 'minute' : ret.setTime(ret.getTime() + units*60000); break;
case 'second' : ret.setTime(ret.getTime() + units*1000); break;
default : ret = undefined; break;
}
return ret;
}
export default httpTrigger;
If you use the package parse-multipart
to parse multipart/form-data, it just returns the value like { filename: 'A.txt', type: 'text/plain', data: <Buffer 41 41 41 41 42 42 42 42> }
and it will not return File
Object. For more details, please refer to here
Besides, the package form-data
just supports string, buffer, and file stream. For more details, please refer to here.
So please update as follow
parse-multipart
export interface FileInfo {
filename: string;
type: string;
data: Buffer;
}
import * as multipart from "parse-multipart";
import axios from "axios";
import { FileInfo } from "../entities/FileInfo";
import * as FormDataFile from "form-data";
const httpTrigger: AzureFunction = async function (
context: Context,
req: HttpRequest
): Promise<void> {
context.log("HTTP trigger function processed a request.");
const body = req.rawBody;
// Retrieve the boundary id
const boundary = multipart.getBoundary(req.headers["content-type"]);
let logEntries = [];
if (boundary) {
const files: FileInfo[] = multipart.Parse(Buffer.from(body), boundary);
if (files && files.length > 0) {
var allUpdated = await Promise.all(
files.map(async (file) => {
await CallOcrService(context, file);
})
);
}
}
context.res = {
status: 200,
body: "OK",
};
};
async function CallOcrService(
context: Context,
file: FileInfo
): Promise<String> {
const formData = new FormDataFile();
formData.append("file", Buffer.from(file.data), {
filename: file.filename,
contentType: file.type,
});
// call you api
}