notes.dt.in.th

In one of my Node.js projects, I have a legacy Express app (serves an API) that I would rather not touch. Instead, I want future endpoints to be built with Fastify instead.

Plan:

  • Requests to /v2/ go to Fastify.
  • The rest of the requests go to Express.
  • Once legacy routes are no longer used, I can delete the Express app.

Here’s what I did:

  1. Separate Express app listening process:

    • Replace this:

      const server = app.listen(21001, () => {
        console.log(server.address())
      })
    • With this:

      const server = http.createServer((req, res) => {
        app(req, res)
      })
      
      server.listen(21001, () => {
        console.log(server.address())
      })
  2. Create a Fastify app:

    // serverV2.mjs
    import Fastify from 'fastify'
    
    export const app = Fastify({
      logger: true,
    })
    
    app.get('/v2/hello', async () => {
      return 'meow'
    })
  3. Make the http server dispatch to the Fastify app if req.url starts with /v2/:

    • Replace this:

      const server = http.createServer((req, res) => {
        app(req, res)
      })
    • With this:

      const server = http.createServer((req, res) => {
        if (req.url?.startsWith('/v2/')) {
          import('./serverV2.mjs').then(async ({ app }) => {
            await app.ready()
            app.server.emit('request', req, res)
          })
        } else {
          app(req, res)
        }
      })