funktionswerk / hapi-i18n

Translation module for hapi based on mashpie's i18n module
MIT License
39 stars 22 forks source link

An empty string causes a server restart #1

Closed rapoell closed 9 years ago

rapoell commented 9 years ago

Executing the following somewhere in a route handler:

var myEmptyString = '';
var myServerRestart = request.i18n.__(myEmptyString); 

Causes the Hapi server to restart and resulting on the client side in "Connection refused" errors.

codeva commented 9 years ago

Works on my side.. Can you provide a code snippet that reproduces the server restart?

rapoell commented 9 years ago

Hi, thanks for replying quickly. I discovered this in a big project, but I've setup a quick thing that will reproduce the effect:

server.js

var Hapi = require('hapi');
var i18n = require('hapi-i18n');

var server = new Hapi.Server();
server.connection({ port: 3333 });

// i18n internationalization
server.register(
    {
        register: require( "hapi-i18n" ),
        options: {
            locales: ["en", "fr", "nl"],
            directory: __dirname + "/locales"
        }
    },
    function ( err ){
        if ( err ){
            console.log( err );
        }
    }
);

server.views({
        path: './views',
        engines: {
            html: require('swig')
        }
});

server.route({
    method: 'GET',
    path: '/',
    handler: function (request, reply) {

        reply.view('test', {sometext: request.i18n.__('Hello, world!')});
    }
});

server.route({
    method: 'GET',
    path: '/boom',
    handler: function (request, reply) {

        reply.view('test', {sometext: request.i18n.__('')});
    }
});

server.start(function () {
    console.log('Server running at:', server.info.uri);
});

start.js

var exec = require('child_process').exec;

var start = function() {
    var startStat = exec('pm2 start '+__dirname+'/server.js --watch --name "Test" -e test-err.log -o test.log -f -x',
        function(err, stdout, stderr) {
            if (err) return console.log(err);

            list();
        });
};

// Display all our processes
var list = function() {
    var processes = exec('pm2 list', function(err, stdout, stderr) {
        if (err) return console.log(err)
    });

    processes.stdout.on('data', function (data) {
        console.log(data);
    })
}

start();

views/test.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>i18n test page</title>

</head>
<body >
    {{ sometext }}
</body>
</html>

Then start the server with

node start.js

Each time you acces

http://localhost:3333/boom

you will have a line in the test.log

Server running at: http://yourMachineName.local:3333
pm2 list

will show you something like:

┌──────────┬────┬──────┬───────┬────────┬─────────┬────────┬─────────────┬──────────┐
│ App name │ id │ mode │ pid   │ status │ restart │ uptime │ memory      │ watching │
├──────────┼────┼──────┼───────┼────────┼─────────┼────────┼─────────────┼──────────┤
│ Test     │ 0  │ fork │ 99979 │ online │ 12      │ 3m     │ 50.266 MB   │  enabled │
└──────────┴────┴──────┴───────┴────────┴─────────┴────────┴─────────────┴──────────┘
 Use `pm2 show <id|name>` to get more details about an app

Hope this helps to track down the problem.

Kind regards,

Ronald

codeva commented 9 years ago

The first time I have run your script, the server has permanently restarted. This was caused by passing "--watch" to pm2 and writing log files in the same directory. After specifying another path for the log files, I could reproduce the behavior you described. It seems that everytime you pass an empty string to i18n, the translation files (located in locales) are touched and the server restarts because of "pm2 --watch"

rapoell commented 9 years ago

In my test situation the server only restarts after I hid the boom url. In the situation where I discovered this the log files were in a different dir. If I understand you correctly pm2 --watch reacts on 'touch' not on 'modifications'. However, the restarts don't occur when a non empty string is used. Only if an empty one is used. So in the case of the none empty strings the touches wouldn't occur. Which would imply that the contents is in memory, right? In any case in both situations (original and test) the empty string appears in the locale.en (and should then also be in memory) and no reason for a touch should be there. But the restarts do occur. This doesn't seem to be a very consistent behavior. Any ideas about this?

My work around is to wrap the i18n call in a small function to test for the empty string and doesn't call i18n in case it is.

codeva commented 9 years ago

hapi-i18n is just a wrapper for mashpie's i18n module to get it work as a hapi plugin. If you see a problem in the behavior of the i18n call, please contact the authors of i18n.

Anyways, the translation files are only touched if "updateFiles" is set to true. Reading the docs, this value is set to true by default. I think in production you should always set this value to false. Setting the default to true is a risk to me.

Hope that helps..

rapoell commented 9 years ago

Thanks. I will. The whole platform is still under development (running at least 7 different kinds of node.js servers + 3 other servers) and thus the settings are those of the dev mode.