0

I am on my way to separate the code for my API in different modules using the exports object, as it is the most similar way to the ES6 standard (not yet supported by Node).

Here is my code currently (it can be run as shown), the problem is that, after separating, the function "cleanFormData" gets called fine, but stops without returning anything (observe the comments starting with "STACK OVERFLOW"):

File: main.js

// Dependencies:
const express = require('express');
const bodyParser = require('body-parser');

// Define app:
const app = express();

// API v0 code:
const apiV0 = require('./api0_sources/api');

// Configuration variables:
const consoleLogActions = true;

// Server start:
app.listen(8888, function () {
    console.log('Server running on port ' + this.address().port + ' - ' + new Date());
});

// For parsing every application/json request:
app.use(bodyParser.json());

// Submit data to register an user:
app.post('/registration', function (req, res) {

    res.set({'Content-Type': 'application/json'});

    // Clean the required data after obtaining it from the parsed JSON:
    let cleanedFormData = apiV0.cleanFormData({ // STACK OVERFLOW: The code stops working here.
        username: req.body.formdata.username,
        email: req.body.formdata.email,
        phone: req.body.formdata.phone,
        password: req.body.formdata.password
    });

    // The "required or not" policy is enforced here (after the strings have been cleaned to prevent blank fields to pass):
    errors = [];
    if (cleanedFormData.username === undefined)   errors.push('username_required');
    if (cleanedFormData.email === undefined)      errors.push('email_required');
    if (cleanedFormData.phone === undefined)      errors.push('phone_required');
    if (cleanedFormData.password === undefined)   errors.push('password_required');
    if (errors.length > 0) {
        let result = {
            success: false,
            errors: errors
        };

        res.jsonp(result);
    }
})
// [More things happen after]

File: ./api0_sources/api.js

// Fix and delete object's strings (for data coming from user's inputs):
exports.cleanFormData = function(object) {
    for (let i in object) {
        object[i] = String(object[i]); // Convert all the object properties to strings (to prevent problems with true, false and null).
        if ((object[i] === 'undefined') || (!object[i].replace(/\s/g, '').length)) { // Deletes 'undefined' strings, empty strings and the ones containing only spaces.
            delete object[i];
            continue; // Skip to the next loop after the property is removed.
        }
        // Do not try to fix the "password" or "newPassword" property:
        if ((i === 'password') || (i === 'newPassword')) continue;
        // Replace multiple spaces with a single one:
        object[i] = object[i].replace(/\s\s+/g, ' ');
        // Check if it is "trimmable" and if so, trim the string:
        if (object[i].trim()) object[i] = object[i].trim();
        console.log(object[i]) // Observing iterations.
    }
    if (consoleLogActions) console.log('▼ Cleaned object keys:\n', object);
    return object;
};

Before, everything was in the same file and worked perfectly fine! Can someone help me to identify what has triggered this unexpected behaviour?

UPDATED 1: Apparently, I identified the problem: I had a variable not shown in the example before: "consoleLogActions", that was only defined in the main file and apparently this stopped the function in the child module from finishing. However, absolutely no error was being thrown by Node. In the updated example it does, in my actual file it doesn't (still, no idea why).

UPDATE 2: Thanks, Marcos Casagrande. It seems like this Express middleware is catching the wrong exceptions. I had literally no idea that this could affect the rest of the code nor I have idea how to fix it. Any suggestions?:

// Detecting syntax errors (depending on the "application/type"):
app.use(function(err, req, res, next) {
    if (err instanceof SyntaxError) { // If "SyntaxError" is part of the error object:
        res
            .status(400)
            .jsonp({
                success: false,
                errors: ['bad_syntax']
            });
    }
});
UserJ
  • 159
  • 3
  • 13

1 Answers1

1

Apparently, I identified the problem: I had a variable not shown in the example before: "consoleLogActions", that was only defined in the main file and apparently this stopped the function in the child module from finishing. However, absolutely no error was being thrown by Node. In the updated example it does, in my actual file it doesn't (still, no idea why).

If you're not getting any error, you probably have an express error-handling middleware, that it's not logging the error.

app.use((err, req, res, next) => {
    // console.error(err); // I'm not doing this.
    res.status(500).end();
});

Or you have an uncaughtException listener somewhere in your code.

process.on('uncaughtException', () => {}); 

The code above, will prevent uncaught errors from being logged, and the process from crashing. This is a really bad practice, and you should avoid it.

Check the following question:

Node.js Best Practice Exception Handling

Marcos Casagrande
  • 37,983
  • 8
  • 84
  • 98
  • Thank you very much for your follow-up. However, I do not seem to have it anywhere in my code. I don't know if maybe some public module is affecting this. I also tried to put the chunk at the top of my code, like this: process.on('uncaughtException', () => {console.log('smth is happening')}); to see if I can trigger the issue, but nothing happens. – UserJ Apr 14 '18 at 22:36
  • @UserJ updated my answer, probably an express error handling middleware. – Marcos Casagrande Apr 14 '18 at 22:43
  • Identified! Updated my question :) – UserJ Apr 14 '18 at 23:01
  • Indeed, it was as I said, an express error handler :) – Marcos Casagrande Apr 14 '18 at 23:04
  • I am when I make a request to an inexistent mount point (as it should work). In exchange, it is ignoring errors in the rest of the code (this should not happen). – UserJ Apr 14 '18 at 23:09
  • When calling `/registration` what status code and response message are you getting? – Marcos Casagrande Apr 14 '18 at 23:15
  • Well, right now it just hangs without completing the request. Before I would get the responses properly (including the 400 ones if the wrong route was requested) after going through the whole code. But it seems like this change I've made has exposed that this is happening because Express is wrongly catching exceptions that shouldn't. – UserJ Apr 14 '18 at 23:25
  • I doubt express is doing that, check an error middleware like the one I posted in my answer. – Marcos Casagrande Apr 14 '18 at 23:29
  • Corrected, it seems to be the one for the error 400 / bad syntax. – UserJ Apr 14 '18 at 23:30
  • So, it's like my answer says, you're not logging the error. – Marcos Casagrande Apr 14 '18 at 23:30
  • There' is nothing to "fix", just log the error and end the request, you have an error in your code, a 500 status code should be returned, and you should fix your error. – Marcos Casagrande Apr 14 '18 at 23:34
  • In any case, you should use a linter, that undefined variable would have been catch by any linter. – Marcos Casagrande Apr 14 '18 at 23:35