GithubHelp home page GithubHelp logo

Comments (9)

mcollina avatar mcollina commented on May 19, 2024

TL;DR - there is no elegant solution to monkeypatching.

Unfortunately much of the express ecosystem relies on monkey patching the end() method. This is one of the key technical differences between the two frameworks, and partially one of the reasons why @delvedor and myself started Fastify long ago.

In essence this issue is out of scope. As you said, this behavior is explicitly called in the README because we did not want to get into the monkey patching Express (that monkey patches node core), as it's going to be messy and it won't work for all applications so it would need to stay behind an option, disabled by default. The good thing is that I think it's doable.

from fastify-express.

SimenB avatar SimenB commented on May 19, 2024

Unfortunately much of the express ecosystem relies on monkey patching the end() method. This is one of the key technical differences between the two frameworks, and partially one of the reasons why @delvedor and myself started Fastify long ago.

💯

I think it's a way better approach in general and am looking forward to completing migration. We just need to be able to migrate an app running in production piece by piece in between other product development, so packages such as this is awesome 😀 Happy to accept hacks as they are (in theory) temporary

The good thing is that I think it's doable.

Happy to take a stab at a PR if you can provide some guidance on where/how to approach this 🙂

from fastify-express.

mcollina avatar mcollina commented on May 19, 2024

The quickest way is probably to lift https://github.com/SerayaEryn/fastify-session/blob/e201f78fc9d7bd33c6f2e84988be7c8af4b5a8a3/lib/fastifySession.js#L93-L113 and do the monkey patching express-session does before fastify-express is set up. You might also have to fork fastify-express to do this - as I said it's not going to be nice.

We might also add an option function that will be called to do these kind of monkey-patching manually.

from fastify-express.

SimenB avatar SimenB commented on May 19, 2024

Thanks! So just to verify I've understood correctly

  1. Before registering express-fastify, add the code from express-session which monkeypatches res.end so that I can override it and add a hook to do something:tm: before response is sent to the client
  2. This might require some changes in fastify-express as well, that is as of now unclear
  3. Make sure to call onSend from fastify-session within the hook added in step 1

Does that seem right? And 1&2 might be accepted as PRs to this repo behind an option

from fastify-express.

mcollina avatar mcollina commented on May 19, 2024

Yes exactly regarding the PRs. I would not make the new code/options specific to express-session, but make it pluggable (by calling a user-provided function).

from fastify-express.

stale avatar stale commented on May 19, 2024

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

from fastify-express.

SimenB avatar SimenB commented on May 19, 2024

I've been swamped for the last few months. I do plan to get back to this some time in the summer

from fastify-express.

flipperlite avatar flipperlite commented on May 19, 2024

The following information may dissuade you from completing this task. There are other issues at play when mixing native Fastify and non-native Express routes in the same app. My recommendation is to create a brand new repo/app for your migration and not mix native/non-native routes because of many moving variables at play.

I was trying to migrate an existing Express app putting the old and new routes into the same app. I'm sorry to report that the "monkeypatching" may be at play here too. There are two bad scenarios:

  1. When an Express 404 handler is present, all valid, native Fastify routes are incorrectly caught by it resulting in 404.
  2. When the Express 404 handler is removed all non-existent routes are correctly caught by the Fastify OOTB 404 handler and GET routes seem to work as shown in the OP. Unfortunately, with the PATCH route and Express body parsers active in the example below, the request just hangs because of the Express body parsers. I did find an interesting outcome, when I comment out the Express body parsers and when a native Fastify route co-exists, the req.body is parsed by the Fastify OOTB parser making req.body available without an Express body parser. Your two working scenarios are then:
  • No Express body parsers but at least one native Fastify route and no Express 404 handler. The req.body is parsed by the Fastify OOTB parser automatically.
  • No native Fastify routes but with Express body parsers. If you need an Express 404 handler, you can use it or else it defaults to the Fastify OOTB 404 handler.
const fastify = require('fastify')()
const express = require('express')
const router = express.Router()

// non-Express, native route. Caught by 404 hander if it exists, or hangs if 404 handler doesn't exist.
fastify.patch('/bar-fastify', handlePatch)
fastify.get('/hello-fastify', handleGet)

// Express routes
router.use(function (req, res, next) {
  res.setHeader('x-custom', true)
  next()
})

router.get('/hello', handleGet)

router.get('/foo', (req, res) => {
  res.status(400)
  res.json({ foo: 'bar' })
})

router.patch('/bar', handlePatch)

// Express 404 handler. When present, fastify routes incorrectly get 404. When commented out, GET works but PATCH hangs.
// router.use('*', (req, res) => {
//   res.status(404)
//   res.json({ msg: 'not found'})
// })

fastify.register(require('fastify-express'))
  .after(() => {
    // These need to be removed if you have a native Fastify route or parsing hangs
    // fastify.use(express.urlencoded({extended: false})) // for Postman x-www-form-urlencoded
    // fastify.use(express.json())

    fastify.use(router)
  })

fastify.listen(3000, console.log)

async function handlePatch (req, res) {
  if (!req.body || Object.keys(req.body).length === 0) {
    res.status(400)
    const output = { msg: 'no req.body'}
    res.json ? res.json(output) : res.send(output)
  } else {
    res.status(200)
    res.json ? res.json(req.body) : res.send(req.body)
  }
}

async function handleGet (req, res) {
  res.status(201)
  const output = { hello: 'world' }
  res.json ? res.json(output) : res.send(output)
}

My curl commands:

me@computer ~ % curl -X GET http://localhost:3000/asdf (CORRECT with Fastify OOTB 404 handler)
{"message":"Route GET:/asdf not found","error":"Not Found","statusCode":404}

me@computer ~ % curl -X GET http://localhost:3000/asdf (CORRECT with Express 404 handler)
{"msg":"not found"}

me@computer ~ % curl -X GET http://localhost:3000/hello (CORRECT)
{"hello":"world"}

me@computer ~ % curl -X GET http://localhost:3000/hello-fastify (INCORRECT with Express 404 handler)
{"msg":"not found"}

me@computer ~ % curl -X GET http://localhost:3000/hello-fastify (CORRECT w/o Express 404 handler)
{"hello":"world"}

me@computer ~ % curl -X PATCH -H 'content-type:application/json' -d '{"foo2":"bar2"}' http://localhost:3000/bar-fastify (HANGS w/o Express 404 handler and with Express body parser and with Fastify native route)
^C

me@computer ~ % curl -X PATCH -H 'content-type:application/json' -d '{"foo2":"bar2"}' http://localhost:3000/bar-fastify (INCORRECT with Express 404 handler)
{"msg":"not found"}

me@computer ~ % curl -X PATCH -H 'content-type:application/json' -d '{"foo2":"bar2"}' http://localhost:3000/bar-fastify (CORRECT w/o Express 404 handler and w/o Express body parsers and with Fastify native route)
{"foo2":"bar2"}

from fastify-express.

stale avatar stale commented on May 19, 2024

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

from fastify-express.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.