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()

  • jhonny111s
    jhonny111s Posts: 22

    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: 61

    @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

Categories

Upcoming Training