0

I created the Function App, I created a Function named HttpTrigger and provided the code in the index.js file which is the following:

const { performance, promisify } = require('perf_hooks');
const fs = require('fs');
const readline = require('readline');
const multer = require('multer');
const upload = multer();
const readFileAsync = promisify(fs.readFile);
const writeFileAsync = promisify(fs.writeFile);

const processingData = [];
let sortingRequests = 0;

module.exports = async function (context, req) {
    context.res = {
        headers: {
            'Content-Type': 'application/json'
        },
    };


    if (req.method === 'POST') {
        if (req.query.action === 'sort') {
            try {
                const inputFile = await processFileUpload(req);

                const startTime = performance.now();
                let requestsCounter = 0;

                const fileContent = await readFileAsync(inputFile.path, 'utf8');
                const dateArray = fileContent.split('\n');

                dateArray.sort((a, b) => {
                    requestsCounter++;
                    return new Date(b) - new Date(a);
                });

                const sortedDateArray = dateArray.join('\n');

                const data = {
                    requests: requestsCounter,
                    processingTime: performance.now() - startTime,
                };

                processingData.push(data);
                sortingRequests += requestsCounter;

                const filePath = `${context.executionContext.functionDirectory}/uploads/result.txt`;

                await writeFileAsync(filePath, sortedDateArray, 'utf8');

                context.res = {
                    status: 200,
                    body: { message: 'File sorted and saved as result.txt', processingData },
                };
            } catch (error) {
                context.res = {
                    status: 500,
                    body: { error: 'Internal Server Error', details: error.message },
                };
            }
        }
    } else if (req.method === 'GET') {
    if (req.query.action === 'download') {
        // Handle file download
        try {
            const filePath = `${context.executionContext.functionDirectory}/uploads/result.txt`;
            context.res = {
                status: 200,
                body: fs.readFileSync(filePath, 'utf8'),
                headers: {
                    'Content-Type': 'text/plain',
                    'Content-Disposition': 'attachment; filename=result.txt',
                },
            };
            context.done();
        } catch (error) {
            context.res = {
                status: 500,
                body: { error: 'Error downloading file' },
            };
            context.done();
        }
    } else if (req.query.action === 'sortingInfo') {
    
        // Handle sorting information request
        try {
            const sortingInfo = {
                requests: sortingRequests,
                processingData: processingData,
            };
            context.res = {
                status: 200,
                body: sortingInfo,
            };
            context.done();
        } catch (error) {
            context.res = {
                status: 500,
                body: { error: 'Internal Server Error' },
            };
            context.done();
        }
    } else {
        // Handle other GET requests as needed
        try {
            const greetingMessage = 'Hello from Azure Function!';
            context.res = {
                status: 200,
                body: { message: greetingMessage },
            };
            context.done();
        } catch (error) {
            context.res = {
                status: 500,
                body: { error: 'Internal Server Error' },
            };
            context.done();
        }
    }

} else {
        context.res = {
            status: 405,
            body: { error: 'Method Not Allowed' },
        };
        context.done();
    }
};
async function processFileUpload(req) {
    return new Promise((resolve, reject) => {
        upload.single('inputFile')(req, {}, (err) => {
            if (err) {
                console.error('Error processing file upload:', err);
                reject(new Error('Error processing file upload'));
            } else {
                resolve(req.file);
            }
        });
    });
}

Whenever I try to send a POST or GET request to the url provided by the function I keep getting 500 (Internal Server Error).

I tried logging the error but it is always the same thing, and I can't figure out where I'm getting the code wrong because both the client-side and the server-side runs perfectly when I run it locally but it fails when I run it as a function. Does anyone have any suggestions in order to debug the code and adjust it and solve the problem?

3
  • 1
    You need to check the server's log to see why it's getting a 500 error. Commented Feb 9, 2024 at 19:59
  • Result: Failure Exception: Worker was unable to load function HttpTrigger: 'Cannot find module 'multer'. But I have multer in my dependencies in the package.json file. Commented Feb 9, 2024 at 20:02
  • 1
    Apparently multer didn't get deployed to the server properly, even though you have it in package.json. You need to resolve that. Commented Feb 9, 2024 at 20:05

1 Answer 1

0

Below is the modified code with your code to sort the dates using the Multer package in an Azure function.

Code :

const { performance } = require('perf_hooks');
const fs = require('fs');
const { promisify } = require('util');
const multer = require('multer');
const upload = multer();
const readFileAsync = promisify(fs.readFile);
const writeFileAsync = promisify(fs.writeFile);

const processingData = [];
let sortingRequests = 0;

module.exports = async function (context, req) {
    context.res = {
        headers: {
            'Content-Type': 'application/json'
        },
    };

    try {
        if (req.method === 'POST') {
            if (req.query.action === 'sort') {
                const filePath = req.body && req.body.filePath;
                if (!filePath) {
                    throw new Error('No file path provided');
                }

                const fileContent = await readFileAsync(filePath, 'utf8');
                const dateArray = fileContent.split('\n');

                const startTime = Date.now();
                let requestsCounter = 0;

                dateArray.sort((a, b) => {
                    requestsCounter++;
                    return new Date(b) - new Date(a);
                });

                const sortedDateArray = dateArray.join('\n');
                const data = {
                    requests: requestsCounter,
                    processingTime: Date.now() - startTime,
                };

                processingData.push(data);
                sortingRequests += requestsCounter;

                const resultFilePath = `${context.executionContext.functionDirectory}/uploads/result.txt`;
                await writeFileAsync(resultFilePath, sortedDateArray, 'utf8');

                context.res = {
                    status: 200,
                    body: { message: 'File sorted and saved as result.txt', processingData },
                };
            }
        } else if (req.method === 'GET') {
            if (req.query.action === 'download') {
                try {
                    const filePath = `${context.executionContext.functionDirectory}/uploads/result.txt`;
                    const fileContent = fs.readFileSync(filePath, 'utf8');

                    context.res = {
                        status: 200,
                        body: fileContent,
                        headers: {
                            'Content-Type': 'text/plain',
                            'Content-Disposition': 'attachment; filename=result.txt',
                        },
                    };
                } catch (error) {
                    context.res = {
                        status: 500,
                        body: { error: 'Error downloading file' },
                    };
                }
            } else if (req.query.action === 'sortingInfo') {
                const sortingInfo = {
                    requests: sortingRequests,
                    processingData: processingData,
                };
                context.res = {
                    status: 200,
                    body: sortingInfo,
                };
            } else {
                const greetingMessage = 'Hello from Azure Function!';
                context.res = {
                    status: 200,
                    body: { message: greetingMessage },
                };
            }
        } else {
            context.res = {
                status: 405,
                body: { error: 'Method Not Allowed' },
            };
        }
    } catch (error) {
        context.res = {
            status: 500,
            body: { error: 'Internal Server Error', details: error.message },
        };
    }
};

async function processFileUpload(req) {
    return new Promise((resolve, reject) => {
        upload.single('inputFile')(req, {}, (err) => {
            if (err) {
                console.error('Error processing file upload:', err);
                reject(new Error('Error processing file upload'));
            } else {
                resolve(req.file);
            }
        });
    });
}

Output in Postman :

http://localhost:7071/api/HttpTrigger1?action=sort

json body:

{
    "filePath": "C:/Users/xxxxxxxxx/Documents/xxxxxxxxx/HttpTrigger1/uploads/dates.txt"
}
{
  "message": "File sorted and saved as result.txt",
  "processingData": [
    {
      "requests": 6,
      "processingTime": 1
    }
  ]
}

enter image description here

Browser Output :

localhost:7071/api/HttpTrigger1?action=sortingInfo

{
  "requests": 6,
  "processingData": [
    {
      "requests": 6,
      "processingTime": 1
    }
  ]
}

enter image description here

http://localhost:7071/api/HttpTrigger1?action=download

result.txt file is downloaded using GET method in browser as below.

enter image description here

Output :

It ran successfully as below,

 *  Executing task: func host start 

Azure Functions Core Tools
Core Tools Version:       4.0.5030 Commit hash: N/A  (64-bit)
Function Runtime Version: 4.15.2.20177

[2024-02-13T05:16:28.613Z] Debugger listening on ws://127.0.0.1:9229/aa5f50b2xxxxxxxxxxxxxx
[2024-02-13T05:16:28.618Z] For help, see: https://nodejs.org/en/docs/inspector

Functions:

        HttpTrigger1: [GET,POST] http://localhost:7071/api/HttpTrigger1

For detailed output, run func with --verbose flag.
[2024-02-13T05:16:29.634Z] Worker process started and initialized.
[2024-02-13T05:16:29.786Z] Debugger attached.
[2024-02-13T05:16:35.501Z] Host lock lease acquired by instance ID '0000000000xxxxxxxxxxxx'.
[2024-02-13T05:16:55.643Z] Executing 'Functions.HttpTrigger1' (Reason='This function was programmatically called via the host APIs.', Id=831c04cbxxxxxxxxxxxx)
[2024-02-13T05:16:56.038Z] Executed 'Functions.HttpTrigger1' (Succeeded, Id=831c04cbxxxxxxxxxxx, Duration=465ms)
[2024-02-13T05:17:23.955Z] Executing 'Functions.HttpTrigger1' (Reason='This function was programmatically called via the host APIs.', Id=2df554b2xxxxxxxxxxxxxxxx)
[2024-02-13T05:17:23.982Z] Executed 'Functions.HttpTrigger1' (Succeeded, Id=2df554b2xxxxxxxxxxx, Duration=28ms)
[2024-02-13T05:17:34.554Z] Executing 'Functions.HttpTrigger1' (Reason='This function was programmatically called via the host APIs.', Id=39d2374dxxxxxxxxxxxxx)
[2024-02-13T05:17:34.595Z] Executed 'Functions.HttpTrigger1' (Succeeded, Id=39d2374d-1e81-4f21-b52a-d39eef10a5fd, Duration=41ms)
[2024-02-13T05:17:50.464Z] Executing 'Functions.HttpTrigger1' (Reason='This function was programmatically called via the host APIs.', Id=70b272d7xxxxxxxxxxxxxx)
[2024-02-13T05:17:50.487Z] Executed 'Functions.HttpTrigger1' (Succeeded, Id=70b272d7xxxxxxxxxxxxx, Duration=24ms)

enter image description here

Before sort :

enter image description here

After sort :

enter image description here

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.