Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature or Question] Run middleware after route handler #284

Closed
geekflyer opened this issue Dec 1, 2017 · 9 comments
Closed

[Feature or Question] Run middleware after route handler #284

geekflyer opened this issue Dec 1, 2017 · 9 comments

Comments

@geekflyer
Copy link

I'm submitting a...

[x] Feature request

Current behavior

When registering middlewares via consumer.apply(middleware)..... they'll run always before the controller handler.

Expected behavior

Ability to run middleware after the route handler.

Environment

Nest version: 4.4.2

What is the motivation / use case for changing the behavior?

I have a use case where I'm using nestjs to create an API gateway. The gateway itself has some authentication / session management endpoints whose logic is implemented in controllers.
Their route is /v1/auth/*.
All routes which are not handled by those controllers e.g. /v1/something should be proxied to a set of other microservices. In the previous plain express app we had a simple middleware for that. Without getting into details, this middleware more or less pipes the request to another microservice via request and contains a line like this req.pipe(request('http://targetUrl').pipe(res).
Now the problem in nestjs is that when registering middlewares they always run before the controllers route handler, but I need them to run only afterwards, if the request didn't get handled the /v1/auth/* handler already.

My solution thoughts so far have been:

  1. turn the proxy middleware into a route handler itself. e.g.:
@Controller()
export class ProxyController {
  constructor(@Inject(configProviderToken) private config: Config) {}

  @All('*')
  async proxyRequest(@Req() req, @Res() res, @Next() next) { }

that kind of works but doesn't feel right and I'm getting actually some problems with errors when piping the proxied response.

  1. Using interceptors
    When using interceptors I don't get access to the underlying res object which I need to pipe the request / response.

Any idea on how to solve this use case? I think the most elegant solution would be the ability to register middlwares after the controller handler, maybe calling it afterWare.

@kamilmysliwiec
Copy link
Member

Hi @geekflyer :)
You should have an access to the res object since it's a property of the request object (req.res should work here).

@geekflyer
Copy link
Author

geekflyer commented Dec 1, 2017

@kamilmysliwiec Thanks, good to know. However I just realized that interceptors also are not the right thing, since they will only be called for route handlers - in my case the proxy default route doesn't even have a route handler.

What are your thoughts about adding functionality to add a middleware after the router handler?

@kamilmysliwiec
Copy link
Member

@geekflyer In the nearest update, Nest will throw NotFoundException when the route won't be found. It means that you'll be able to catch this exception inside the exception filter and then pipe the request to the underlying services. What do you think about that?

@geekflyer
Copy link
Author

Hmm, while this may work this seems honestly a bit abusive to me. It basically means I register my middleware as some sort of error handler even though it's not actually an error handling middleware.

@wbhob
Copy link
Contributor

wbhob commented Dec 12, 2017

Not found is an error, and needs a handler, hence 404 Not Found. Obviously, I'd imagine you could change the response code to a 3xx Redirect, but at it's core, it is your handler for when the resource you requested is not available in the scope.

@kamilmysliwiec
Copy link
Member

I have similar feelings as @wbhob. Not found is an error, thus it's a good place to handle this kind of things in the exception filter. Since it's possible to pick outside any instance from the Nest application context, you are able to use global exception filter defined inside module (so with DI) now (you may even call a component from there)

@stathopou
Copy link

Hello, Is it possible to post a code snippet where a request is forwarded using an interceptor (second case that @geekflyer mentioned) ?

@wbhob
Copy link
Contributor

wbhob commented May 26, 2019

you can ask questions on StackOverflow.

@lock
Copy link

lock bot commented Sep 23, 2019

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@lock lock bot locked as resolved and limited conversation to collaborators Sep 23, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants