tumblr / colossus

I/O and Microservice library for Scala
Apache License 2.0
1.14k stars 96 forks source link

Middleware support #495

Closed teodor-pripoae closed 7 years ago

teodor-pripoae commented 7 years ago

Hi,

Is there any option to add middlewares to my handlers ? I have two particular cases for middlewares:

DanSimon commented 7 years ago

Hey sorry for the delay in response, just got back from vacation :)

So there is currently nothing built-in to do what you want, especially in the latest 0.8.3 release. However I think some of the changes we made in the upcoming 0.9.0 release will facilitate this.

That said, since your handler is just a plain old Scala PartialFunction, there is nothing to stop you from implementing this functionality yourself without much boilerplate. I have done this myself to do things like ensure all responses are sent back as json or to do common error handling in routes. Sure it's not a fancy DSL, but it works nonetheless.

For example, if I have several routes that require a common query-string parameter I've done something like:

def withParameter
  (request: HttpRequest)
  (onSuccess: String => Callback[HttpResponse]): Callback[HttpResponse] = //...

def handleFooRoute(request: HttpRequest) = withParameter(request) { param =>
  //...
}

def handleBarRoute(request: HttpRequest): Callback[HttpResponse] = //...

def handle = {
  case request @ Get on Root / "foo" => handleFooRoute(request)
  case request @ Get on Root / "bar" => handleBarRoute(request)
}

The combination of moving all route-handling code into functions and using higher-order wrapper functions has allowed us to achieve (I think) the kinds of scenarios you're talking about. We've even done request tracing and rate limiting this way.

If you're looking for something lower-level or something more self-contained and reusable across multiple services, it will probably be more doable in 0.9.0, which is currently in the release candidate phase. Basically everything is a lot more modular and provides ways for you to inject middleware layers into the request handling pipeline. We plan to use this to support things like SSL and protocol handshakes, but I'm anticipating it will solve the above problems as well.