Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error 504 Gateway Time-out with POST (on Node.JS) #4342

Closed
Madriix opened this issue Mar 7, 2022 · 10 comments
Closed

Error 504 Gateway Time-out with POST (on Node.JS) #4342

Madriix opened this issue Mar 7, 2022 · 10 comments
Assignees
Labels
support Questions, discussions, and general support

Comments

@Madriix
Copy link

Madriix commented Mar 7, 2022

Hi

I have a problem with POST, the /_test2 page is slowing down and after a minute there is a 504 error code Gateway Timeout

    {
        method: 'GET',
        path: '/_test',
        handler: function (request, reply) {

            reply('<html><body><form method="post" action="/_test2"><input type="text" id="nick" name="nick" value="toto300"><input type="submit" value="button"/></form></body></html>');
        }
    },{
        method: 'POST',
        path: '/_test2',
        handler: function (request, reply) {
        	const post = request.payload;
        	reply(post.nick);
        }
    }

Do you know where the problem could come from?
is it at least possible to send a post on /_test2 with jquery?

I have a Debian 11, hapi v16.0.1, Nodejs v16.14.0 with GET it works fine, but not with POST.
What is strange is that locally on my PC, this POST works without problem, but not on the dedicated server
Cordially

@Madriix Madriix added the support Questions, discussions, and general support label Mar 7, 2022
@Madriix
Copy link
Author

Madriix commented Mar 7, 2022

curl -fsSL https://deb.nodesource.com/setup_14.x | sudo -E bash -
sudo apt-get install -y nodejs

I solved the problem by reverting to the old nodejs version: v14.19.0
So it works but too bad I can't update NodeJS anymore, do you have an idea for it to work with new versions? What are the causes ?

@Madriix Madriix changed the title Error 504 Gateway Time-out with POST Error 504 Gateway Time-out with POST (on Node.JS) Mar 7, 2022
@Marsup
Copy link
Contributor

Marsup commented Mar 7, 2022

hapi 16 requires paid support and probably doesn't work with node 16, you should upgrade.

@Marsup Marsup closed this as completed Mar 7, 2022
@Marsup Marsup self-assigned this Mar 7, 2022
@Madriix
Copy link
Author

Madriix commented Mar 8, 2022

I can pay if it is not very expensive.

According to your comment, I have two choices:

  1. either adapt Hapi 16 so that it works with Node 16, concerning "POST".

  2. either put back the latest Node 16 version and update Hapi to the latest version 20.2.1: I've never done that, impossible to migrate, it's too difficult. My NodeJS project is made like this:

Project > config.js (here there is data for Hapi)
            > server (folder) (no Hapi data)
            > client (folder) > server.js (there is Hapi data, there are plugins too)
                                    > router (folder) it has two files index.js and default.js, in default.js there are the famous POST, GET and the handler: function (request, reply) {}
                                    > others....js including the client, they are not impacted by Hapi at first glance

How to contact you to update?

@Nargonath
Copy link
Member

Nargonath commented Mar 8, 2022

@Madriix There was a big major breaking change between version 16 and version 17 (full rewrite to async/await). You can find a detailed upgrade explanation here: #3658. You can use this search for the other versions: https://github.com/hapijs/hapi/issues?q=label%3A%22breaking+changes%22+is%3Aclosed. I believe there were several breaking changes in node@16 that impacted web frameworks in the ecosystem. We fixed the issue in the latest version of hapi.

Since you're still on hapi@16 you might not be aware of the changes that happen in hapi's governance. You can find details here:
#4111
#4113

The support of older hapi versions is not the responsibility of the TSC but rather a paid service offered by @hueniverse. You'd have to contact him to get the details of the offer and whether it's still offered.

I highly suggest you to look into upgrading your hapi version since I don't think the services offered by Eran will last forever.

@Madriix
Copy link
Author

Madriix commented Mar 8, 2022

I managed to recode everything, put the latest version of node back, and put the latest version of "@hapi/<..." and everything is working now.
I started this morning around 9 a.m., it ended at 4 p.m. and it went into production.
I learned things, I learned what I never modified on my project (because the base was created by someone a few years ago and I had never touched this part there) and I am happy to have been able to reproduce everything. It's in production testing.

Here's the new one (for server.js):

    const start = async function () {
        console.log('Test1: Configuring Hapi server...');
        
        const server = new Hapi.server(config.client.settings.servers[1]);
    
        console.log('Registering plugins...');
        await server.register([{
            plugin: require('@hapi/vision'),
            options: {}
        }, {
            plugin: require('@hapi/inert'),
            options: {}
        }/*, {
            plugin: require('./libs/cachebuster.js'),
            options: {
                buster: ((config.cacheBuster || {}).buster || Date.now())
            }
        }*/]);


        console.log('Plugins registered; adding views...');

        server.views({
            engines: {
                html: handlebars
            },
            context: config.client.views.default,
            relativeTo: __dirname,
            path: 'public',
            layout: true,
            layoutPath: path.join(__dirname, 'views/layouts'),
            helpersPath: path.join(__dirname, 'views/helpers')
        });

        try {
            server.route(require('./router'));
          } catch (error) {
            console.error('Failed to register routes.');
            throw error;
        }

         console.log('Routes added; starting HTTP server...');
        
        await server.start();
        console.log('Started: %s (%s:%d)', server.info.uri, server.info.address, server.info.port);

    };


    const start2 = async function () {
        console.log('Test1: Configuring Hapi server...');
        
        const server = new Hapi.server(config.client.settings.servers[0]);
    
        console.log('Registering plugins...');
        await server.register([{
            plugin: require('@hapi/vision'),
            options: {}
        }, {
            plugin: require('@hapi/inert'),
            options: {}
        }/*, {
            plugin: require('./libs/cachebuster.js'),
            options: {
                buster: ((config.cacheBuster || {}).buster || Date.now())
            }
        }*/]);


        console.log('Plugins registered; adding views...');

        server.views({
            engines: {
                html: handlebars
            },
            context: config.client.views.default,
            relativeTo: __dirname,
            path: 'public',
            layout: true,
            layoutPath: path.join(__dirname, 'views/layouts'),
            helpersPath: path.join(__dirname, 'views/helpers')
        });

        try {
            server.route(require('./router'));
          } catch (error) {
            console.error('Failed to register routes.');
            throw error;
        }

         console.log('Routes added; starting HTTP server...');
        
        await server.start();
        console.log('Started: %s (%s:%d)', server.info.uri, server.info.address, server.info.port);

    };

    process.on('unhandledRejection', (err) => {

        console.log("Erreur2: " + err);
        process.exit(1);
    });

    start();
    start2();

Here is the old one:

try {
    console.log('Configuring Hapi server...');
    const server = new Hapi.Server(config.client.settings);
    config.client.servers.forEach(function (conf) {
        server.connection(conf);
    });
    console.log('Registering plugins...');
    server.register([{
        register: require('@hapi/vision')
     },{
        register: require('@hapi/inert')
     },{
        register: require('./libs/cachebuster.js'),
        options: {
            buster: ((config.cacheBuster || {}).buster || Date.now())
        }
    }], function (error) {
        if (error) {
           console.trace(error);
           process.exit(1);
        }
        try {
           console.log('Plugins registered; adding views...');
           server.views({
               engines: {
                   html: handlebars
               },
               context: config.client.views.default,
               relativeTo: __dirname,
               path: 'public',
               layout: true,
               layoutPath: path.join(__dirname, 'views/layouts'),
               helpersPath: path.join(__dirname, 'views/helpers')
           });
           console.log('Views added; adding routes...')
         } catch (error) {
           console.error('Failed to add views.');
           throw error;
        }
        try {
           server.route(require('./router'));
         } catch (error) {
           console.error('Failed to register routes.');
           throw error;
        }
        console.log('Routes added; starting HTTP server...');
        server.start(function (err) {
            if (err) {
               console.log('Failed to start HTTP server.');
               throw err;
            }
            if (!server.info) {
               server.connections.map(function (con) {
                   console.log('Started: %s (%s:%d)', con.info.uri, con.info.address, con.info.port);
               });
             } else {
               console.log('Started: %s (%s:%d)', server.info.uri, server.info.address, server.info.port);
            }
            process.on('SIGINT', (function (http) {
                return function () {
                    console.log('Attempting graceful shutdown...');
                    http.stop({ timeout: 10 * 1000 }, function (error) {
                        //process.exit(error ? 1 : 0);
                        process.exit(1);
                    });
                }
            })(server));
        });
    });
 } catch (e) {
   console.trace(e);
   process.exit(1);
}

For this part, know how to restore it?

/*, {
            plugin: require('./libs/cachebuster.js'),
            options: {
                buster: ((config.cacheBuster || {}).buster || Date.now())
            }
    }*/

content of cachebuster.js (1 file only) :

/*
  This is based on 'hapi-cache-buster' on npm.

*/
exports.register = function (server, options, next) {
    var buster = (options.buster || Date.now());
    server.ext('onPostHandler', function (request, reply) {
        var response = request.response;
        if (response.variety === 'view') {
           response.source.context = (response.source.context || {});
           response.source.context.CacheBuster = (response.source.context.CacheBuster || {});
           response.source.context.CacheBuster.buster = ['?v=', buster].join('');
           response.source.context.CacheBuster.buster2 = [buster].join('');
        }
        return reply.continue();
    });
    return next();
};
exports.register.attributes = {
    pkg: {
        name: 'cache-buster',
        description: 'Cache buster plugin for Hapi.',
        version: '0.0.1',
    }
};

Paid support or maybe the cache buster is useless as my project is running?! on the other hand there is no longer any cache buster.
I should put a random number on each start or each "grunt-cli"

@Nargonath
Copy link
Member

Well done @Madriix, I'm glad to know you managed to fix everything and migrate to the latest hapi version in about a day.

Regarding the cachebusting it seems that code is style pre-v17. You can find some basic information regarding plugins in our plugins section on the website: https://hapi.dev/tutorials/plugins/?lang=en_US. I don't expect it to be hard to migrate over the latest version.

I should put a random number on each start or each "grunt-cli"

That's basically what the code you shared seems to be doing.

@Madriix
Copy link
Author

Madriix commented Mar 8, 2022

@Nargonath thanks for motivating me, i put this up and it looks working :

cachebuster.js:

/*
  This is based on 'hapi-cache-buster' on npm.

*/
'use strict';
exports.plugin = {
    pkg: require('../package.json'),
    register: async function (server, options) {
        var buster = (options.buster || Date.now());
        server.ext('onPostHandler', async function (request, h) {
            var response = request.response;
            if (response.variety === 'view') {
               response.source.context = (response.source.context || {});
               response.source.context.CacheBuster = (response.source.context.CacheBuster || {});
               response.source.context.CacheBuster.buster = ['?v=', buster].join('');
               response.source.context.CacheBuster.buster2 = [buster].join('');
            }
            return h.continue;
        });
    }
};

@Nargonath
Copy link
Member

Well done @Madriix. 👍

@Madriix
Copy link
Author

Madriix commented Mar 12, 2022

Hi, what is the difference between "new" and without? :

const server = Hapi.server(....);
const server = new Hapi.server(...);

Which should be used?

I removed it and I see no difference

@devinivy
Copy link
Member

devinivy commented Mar 12, 2022

Technically both new Hapi.Server() and Hapi.server() are supported, but I would recommend going with Hapi.server() if you otherwise have no preference. Here's the test backing this up:

hapi/test/index.js

Lines 17 to 23 in dc2213c

it('supports new Server()', async () => {
const server = new Hapi.Server();
server.route({ method: 'GET', path: '/', handler: () => 'old school' });
const res = await server.inject('/');
expect(res.result).to.equal('old school');

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
support Questions, discussions, and general support
Projects
None yet
Development

No branches or pull requests

4 participants