1

I have more than one endpoints.I am able to apply common filters on endpoints using finagle filter.But now I want to apply a filter on a specific endpoint. How can I achieve this?

Kumar Waghmode
  • 509
  • 2
  • 18
  • What exactly you're trying to? In 99% of the cases, you can use endpoints instead of filters. – Vladimir Kostyukov Nov 07 '17 at 20:34
  • @VladimirKostyukov I have an endpoint on which I need to add logging using a filter.Could you please share an example of endpoint filtering? – Kumar Waghmode Nov 09 '17 at 05:48
  • If it's just one endpoint maybe add logging within "endpoint body" (i.e., map function)? – Vladimir Kostyukov Nov 10 '17 at 01:27
  • @VladimirKostyukov in logging I want to log everything whatever I receive in request and response including URL and status code content type etc.This data is not available inside an endpoint. – Kumar Waghmode Nov 10 '17 at 08:21
  • @VladimirKostyukov, any comment about my suggested solution? I'd be curious to know if there are simpler/better ways of doing it. – Shastick Nov 13 '17 at 11:24

2 Answers2

3

I had a similar question (for basic authentication filtering) that popped up while playing with redbubble's finch template which I partially solved in the following way:

class AuthenticatedEndpoint[A](e: Endpoint[A]) extends Endpoint[A] { self =>

final def apply(mapper: Mapper[A]): Endpoint[mapper.Out] = mapper(self)

final def apply(input: Input): Endpoint.Result[A] =
  if (checkSession(input.request)) {
    e(input)
  } else {
    // TODO return something meaningful to the caller (if possible?)
    EndpointResult.Skipped
  }
}

object AuthenticatedEndpoint {

  def validSession[A](e: Endpoint[A]): Endpoint[A] = new AuthenticatedEndpoint(e)

}

(with checkSession returning true if all is well with the request). Then my api is defined as:

val api = "v1" :: loginApi :+: validSession(peopleApi :+: healthApi :+: adminApi)

This works well in the sense that requests without a session won't have access to the endpoints passed to validSession, but I have yet to find an easy way to return an error message to the caller, and I'd be curious to know if I chose the right path here.

Shastick
  • 1,218
  • 1
  • 12
  • 29
0

This is how I got around it. It's probably not ideal but works.

class AuthenticatedEndpoint[A](e: Endpoint[A])(implicit auth: Request => Boolean) extends Endpoint[A] { self =>

  final def apply(mapper: Mapper[A]): Endpoint[mapper.Out] = mapper(self)

  final def apply(input: Input): Endpoint.Result[A] =
    if (auth(input.request)) {
      e(input)
    } else {
      EndpointResult.Matched[Nothing](input, Rerunnable( Unauthorized(new Exception(s"Authentication Failed."))) )
    }
}

object AuthenticatedEndpoint {

  def validSession[A](e: Endpoint[A]): Endpoint[A] = new AuthenticatedEndpoint(e)

}