Welcome to the Linux Foundation Forum!

Ch5, Lab 1 - validate running before server ready

caphsob
caphsob Posts: 3
edited December 2021 in LFW212 Class Forum

Hi all,

I'm attempting to complete the lab for ch-5 ("Implement a RESTful JSON GET").

I've create the server using express but when I run node validate I get an error stating " Unable to connect to server on port: ....".

It looks like the validate() checks are running before the express server is actually ready. I added a delay to validate.js to wait 1000ms before the validate() function runs just to test it out. When I do this, the code passes successfully so it looks like I've missed something out on my code - but I'm not sure what? Can anyone point me in the right direction?

I've set my npm start correctly. Running in VS Code, Windows 10.

My Code:-


const express = require('express');
const model = require('./model');

const app = express();

app.get('/boat/:id', (req, res) => {

 model.boat.read(req.params.id, (err, data) => {

    if (err) {

      if (err.code == 'E_NOT_FOUND') {
        res.sendStatus(404);
      } else {
        res.sendStatus(500);
      }

    } else {
      res.send(data);
    }

  })
});

app.use(function (req,res,next){
    res.status(404).send('Unable to find the requested resource!');
});

app.listen(process.env.PORT, () => {
    console.log(`Listening on ${process.env.PORT}`)
});

Thanks!

Comments

  • One extra note, this worked fine for me using Fastify - it's just the Express version I can't seem to get working without introducing a delay before validate()

  • the function should be async, then you wait until finished or maybe return a promise.

    const data = require('../../data')
    
    router.get('/', async (req, res) => {
      const randomString = await data();
      res.send(randomString)
    })
    
  • @caphsob I've checked your code against validate.js and it seems to work just fine. This may be related to your host machine and there's perhaps a race condition. I'm going to update the start function in validate.js to:

    async function start () {
      const server = net.createServer().listen()
      await once(server, 'listening')
      const { port } = server.address()
      server.close()
      await once(server, 'close')
      await writeFile(join(__dirname, 'model.js'), testingModel())
      const sp = spawn(process.platform === 'win32' ? 'npm.cmd' : 'npm', ['start'], { env: { ...process.env, PORT: port }, stdio: ['ignore', 'ignore', 'inherit'] })
      const [ err ] = await Promise.race([once(sp, 'spawn'), once(sp, 'error')])
    
      try {
        if (err) throw err
        await validate({ port })
      } catch (err) {
        if (err.code === 'ERR_ASSERTION') {
          console.log('⛔️ ' + err.message)
          process.exit(1)
        }
        throw err
      } finally {
        await writeFile(join(__dirname, 'model.js'), model())
        try { sp.kill() } catch {}
      }
    }
    

    This being the key line:

      const [ err ] = await Promise.race([once(sp, 'spawn'), once(sp, 'error')])
    

    The spawn event was only added fairly recently, so this will be part of our major update to Node v16 (but you can try this out with Node 14/Node 16 and see if it works).

    @jhonny111s avoid recommending async functions be used with Express, the training material goes into detail as to why this is a bad idea.

  • debido
    debido Posts: 4

    same thing happened to me using windows 10, fastify, and the latest validate.js.

    the server child process took a smidge over two seconds to start listening for requests so the validation code (the validate function in validate.js) throws an AssertionError with message 'Unable to connect to server on port:...'.

    in validate.js, in function validate, changing the if block condition to retries > 6 should avoid this problem on most machines i would guess

  • Bolzano
    Bolzano Posts: 1

    Thanks @debido, your fix (changing number of retries check) worked great for me.

  • can you explain how to resolve GET http://localhost:3000/boat/02e9 must respond with 500 response? on validate.js

    thanks

  • xdxmxc
    xdxmxc Posts: 110

    @anitaliberatore its checking against an injected route that's designed to fail, it's up to you to handle the failure and ensure that the server responds with a 500 status code

  • sms92
    sms92 Posts: 5

    for me changing the node version to 16 worked.

  • xdxmxc
    xdxmxc Posts: 110

    @sms92 that'll be because the init time of 16 changed the outcome of the race condition

    all timeouts and retry counts for all server validation scripts are being increased to eliminate false failures

Categories

Upcoming Training