express 4: serveur bloqué en utilisant certain middlewares

L’auteur de ce sujet a trouvé une solution à son problème.
Auteur du sujet

Bonjour à tous,

Pour m'amuser un peu et voir autre chose que du JavaEE/Spring et du PHP/Symfony, j'essaie de faire un mini site web avec Node.js et Express 4.

Je n'ai même pas commencé à faire quelque chose de vraiment intéressant que je suis déjà coincé par un problème très con. Dès lors que j'ajoute certains middlewares génériques, le serveur ne répond plus, et j'obtiens alors systématiquement une page blanche ou alors un serveur introuvable provenant du navigateur.

Dans tous les tutoriaux et exemples que je vois sur le net, ces middlewares sont faits pour être chaînés, et pour être génériques (i.e. s'appliquer à toutes les requêtes / ils déterminnent tout seuls s'ils doivent s'activer ou non en fonction de la requête reçue). Du coup je ne comprends pas vraiment…

Si je contacte le serveur directement via telnet, je constate que je reste connecté mais que je ne reçois jamais de réponse !

1
2
3
4
5
6
7
> netcat localhost 3000
GET / HTTP/1.1
Host: localhost
<enter>
<enter>
...
<là je devrais recevoir une réponse mais je n'en obtiens jamais, tout en restant connecté; je suis obligé de Ctrl+C>

En ajoutant me middleware timeout (connect-timeout), mes absences de réponse / pages blanches / serveur introuvable deviennent des erreurs de timeout. Le serveur met trop de temps à répondre, il se « bloque ». Mais pourquoi donc ?!

Les middlewares qui me bloquent mon serveur sont :

  • bodyparser.json
  • multer
  • compression
  • csurf

Pourquoi ? Qu'est-ce qui se passe ? Qu'ais-je oublié, ou qu'ais-je fait de faux ?

Mon code est ci-dessous.
Système: Windows 10
Version de node.js: 6.9.1 (la dernière version stable disponible pour windows x64 à ce jour)

Merci pour vos réponses.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
const
express = require('express'),
util = require('util'),
app = express(),
config = require('./config.json');

{
    const
    bodyParser = require('body-parser'),
    cookieParser = require('cookie-parser'),
    multer = require('multer'),
    session = require('./session'),
    csurf = require('csurf'),
    compression = require('compression'),
    timeout = require('connect-timeout'),
    passport = require('passport'),
    LocalStrategy = require('passport-local') .Strategy;

    app.use(timeout(3000));
    app.use(cookieParser(config.cookieSecret));
app.use(bodyParser.urlencoded( { extended: true }));
    app.use(bodyParser.json);
//.use(multer)
    app.use(session);
//.use(csurf({ cookie: false }))
//.use(compression)
}

app.all('*', function(req,res) {
    res.status(200).send(`
    $ {new Date()}<br />
query: $ {util.inspect(req.query)} <br />
Body: $ {util.inspect(req.body)} <br />
Headers: $ {util.inspect(req.headers)} <br />
Session: $ {util.inspect(req.session)} <br />
Params: $ {util.inspect(req.params)} <br />
    `);
});

{

    const errorhandler = require('errorhandler');
    app
    .use(express.static(__dirname + config.static))
    .use( (req,res)=>res.sendStatus(404) )
    .use(errorhandler);
}

app.listen(config.port);
console.log(`Server ready on port $ {config.port}`);

Édité par QuentinC

Ma plateforme avec 23 jeux de société classiques en 6 langues et 13000 joueurs: http://qcsalon.net/ | Apprenez à faire des sites web accessibles http://www.openweb.eu.org/

+0 -0
Auteur du sujet

Tu as utilisé le serveur http intégré à node avant de tester express, non ? Il n'y a pas de status à envoyer dans la fonction send et il n'y a pas besoin de end.

Bien vu ! Mais ça ne règle pas le problème. Je mets à jour mon code dans le premier post.

Ma plateforme avec 23 jeux de société classiques en 6 langues et 13000 joueurs: http://qcsalon.net/ | Apprenez à faire des sites web accessibles http://www.openweb.eu.org/

+0 -0

QuentinC, tu devrais indenter un peu ton code, ça aide à y voir clair pour toi comme pour nous.

Aussi, fais attention à l'insertion automatique de point-virgule. Déclare chaque variable séparément. Evite aussi les blocs inutiles : {const x = 12;}

+0 -0
Auteur du sujet

QuentinC, tu devrais indenter un peu ton code, ça aide à y voir clair pour toi comme pour nous.

Je suis non-voyant, l'indentation je m'en fiche totalement, ce qui explique pourquoi je n'en mets pas dans mes développements perso.

J'avais cru qu'il y avait un genre d'indenteur automatique sur ZDS. Ce qui me fait croire ça c'est que quand je poste du code python, il met tout à 4 espaces, même quand j'utilise des tabs ou un seul espace (ce que je fais souvent quand je fais du python).

J'ai passé mon code dans astyle avec les options par défaut, j'espère que ça vous convient. J'avais supprimé quelques lignes inutiles à la résolution du problème, du coup il est un peu plus long qu'avant. Astlye semble aussi avoir viré les doubles lignes blanches que j'avais mis intentionnellement pour séparer un peu mon code. Dites-moi si c'est mieux, sinon je remets la non indentée.

Aussi, fais attention à l'insertion automatique de point-virgule.

Quelle insertion automatique ? IL y en a pas dans le bloc-notes. J'utilise eclipse exclusivement pour faire du Java, et exclusivement au boulot. C'est trop chiant à configurer pour ce que ça m'apporte pour développer dans mes temps libres.

Déclare chaque variable séparément.

Ca ne change rien ça normalement.

Evite aussi les blocs inutiles : {const x = 12;}

Le but c'était de minimiser au maximum la portée des variables. Ca ne sert peut-être à rien ici effectivement…

Édité par QuentinC

Ma plateforme avec 23 jeux de société classiques en 6 langues et 13000 joueurs: http://qcsalon.net/ | Apprenez à faire des sites web accessibles http://www.openweb.eu.org/

+0 -0
Auteur du sujet

Selon cette page, all doit appeller next, qui est son 3ème argument.

De ce que j'ai compris du fonctionnement d'express, je dois appeler next quand le traitement n'est pas terminal. Là comme je renvoie une réponse définitive, je n'ai pas besoin d'appeler next.

J'ai ajouté un console.log('coucou!') au début de ma fonction app.all et elle n'est en fait jamais appelée. Comme si le serveur restait bloqué sur le module bodyParser.json (et que c'est lui qui n'appelle jamais next alors qu'il le devrait).

Comme proposé sur leurs guides, j'ai défini la variable d'environnement debug à express:* et là je vois bien :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
Server ready on port 3000
  express:router dispatching GET /cccc?x=1&y=2 +10s
  express:router query  : /cccc?x=1&y=2 +4ms
  express:router expressInit  : /cccc?x=1&y=2 +0ms
  express:router <anonymous>  : /cccc?x=1&y=2 +4ms
  express:router cookieParser  : /cccc?x=1&y=2 +4ms
  express:router urlencodedParser  : /cccc?x=1&y=2 +0ms
  express:router json  : /cccc?x=1&y=2 +4ms
  express:router <anonymous>  : /cccc?x=1&y=2 +3s
  express:router serveStatic  : /cccc?x=1&y=2 +0ms
  express:router <anonymous>  : /cccc?x=1&y=2 +0ms
  express:router errorHandler  : /cccc?x=1&y=2 +4ms
ServiceUnavailableError: Response timeout
    at IncomingMessage.<anonymous> (C:\...\node_modules\connect-timeout\index.js:70:8)
    at emitOne (events.js:96:13)
    at IncomingMessage.emit (events.js:188:7)
    at Timeout._onTimeout (C:\...\node_modules\connect-timeout\index.js:43:11)
    at ontimeout (timers.js:365:14)
    at tryOnTimeout (timers.js:237:5)
    at Timer.listOnTimeout (timers.js:207:5)

Ma plateforme avec 23 jeux de société classiques en 6 langues et 13000 joueurs: http://qcsalon.net/ | Apprenez à faire des sites web accessibles http://www.openweb.eu.org/

+0 -0

Je suis non-voyant, l'indentation je m'en fiche totalement, ce qui explique pourquoi je n'en mets pas dans mes développements perso.

Aucun problème, je ne le savais pas, désolé pour la remarque. :)

L'indentation ne se fait pas automatiquement sur Zeste de Savoir, et pour les voyants c'est une aide, d'où ma remarque. Mais vraiment ne te formalise pas pour ça, c'était un conseil qui ici ne s'applique pas.

Quelle insertion automatique ? IL y en a pas dans le bloc-notes.

L'insertion automatique de points virgules est un mécanisme de JavaScript. D'après le standard JavaScript, implémenté par tous les interpréteurs ou compilateurs JavaScript, des points virgule sont insérés automatiquement à certains endroits du code. C'est une source d'erreur très courante chez les débutants en JavaScript.

Voici un exemple :

1
2
3
function test() {
  return true;
}

Cette fonction nommée test retourne true.

1
2
3
4
function test2() {
return
true;
}

Cette deuxième fonction nommée test2 retourne undefined, parce qu'un point virgule a été inséré automatiquement après return, avant le retour à la ligne.

Evite aussi les blocs inutiles : {const x = 12;}

Le but c'était de minimiser au maximum la portée des variables. Ca ne sert peut-être à rien ici effectivement…

Oui ici ça ne sert à rien. Un simple block en JavaScript ne restreint pas la portée des variables.

Édité par victor

+0 -0
Auteur du sujet

L'insertion automatique de points virgules est un mécanisme de JavaScript. D'après le standard JavaScript, implémenté par tous les interpréteurs ou compilateurs JavaScript, des points virgule sont insérés automatiquement à certains endroits du code.

Je ne suis pas du tout un débutant en js, j'en fais régulièrement depuis 10 ans même si c'est à petites doses. Je savais qu'à certains endroits les points-virgule étaient facultatifs, qu'il valait mieux ne pas se fier au fait que ce soit optionel parce que ça introduit facilement des erreurs, mais par contre c'est la première fois que j'entend parler de pseudo points-virgule automatiquement ajoutés par le compilateur.

Entre temps j'ai trouvé la solution à mon problème tout seul. C'est toujours après qu'on a posté une question sur un forum qu'on trouve la solution… la blague classique.

J'ai simplement raté le fait que certains middlewares doivent être construits, et d'autres pas: app.use(machin) vs app.use(machin()). C'est hyper con. J'ai honte.

Ma plateforme avec 23 jeux de société classiques en 6 langues et 13000 joueurs: http://qcsalon.net/ | Apprenez à faire des sites web accessibles http://www.openweb.eu.org/

+0 -0

Je ne suis pas du tout un débutant en js, j'en fais régulièrement depuis 10 ans même si c'est à petites doses. Je savais qu'à certains endroits les points-virgule étaient facultatifs, qu'il valait mieux ne pas se fier au fait que ce soit optionel parce que ça introduit facilement des erreurs, mais par contre c'est la première fois que j'entend parler de pseudo points-virgule automatiquement ajoutés par le compilateur.

Justement, oui, ce que tu considères comme "facultatif" sont les endroits où les points-virgules sont insérés automatiquement.

C'est un truc important à savoir quand tu fais du javascript, l'exemple que j'ai donné est un bon exemple vu que le point virgule automatiquement inséré fait qu'une fonction retourne undefined au lieu de la valeur à laquelle on pourrait s'attendre.

En règle générale t'as pas vraiment besoin de points virgule sauf avant un crochet ouvrant ou une parenthèse ouvrante. Du coup si tu veux pas te planter, soit tu mets des points virgule partout, soit t'en mets presque aucun tout en utilisant un outil qui te dira quand t'as oublié d'en mettre un nécessaire, par exemple standard.

Si tu veux comprendre comment les points virgule sont insérés automatiquement et où, le mieux est évidemment de lire la spécification du langage. Ici pour ES5, ici pour ES2015.

Édité par victor

+0 -0
Vous devez être connecté pour pouvoir poster un message.
Connexion

Pas encore inscrit ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte