Open Marcus-Rosti opened 4 years ago
Oh and the call I'm making is:
$ grpc_cli ls localhost:50051
This is indeed an area where the interoperability between Akka gRPC and plain Akka HTTP still can use more work.
In this particular case, you could probably solve your direct problem by inserting your reflection route into the list passed to ServiceHandler.concat
. https://doc.akka.io/docs/akka-grpc/current/server/walkthrough.html#serving-multiple-services might also be interesting.
ServiceHandler.concat
(conceptually) 'seals' the route to make sure that if no matching service is found, we return a gRPC 'Not Found' (rather than a plain HTTP2 'Not Found' - those are unfortunately different). Perhaps we should make that clearer in the naming, and/or provide an easy way to inject a RejectionHandler
that produces a 'plain' or 'gRPC'-style 'Not Found' depending on the request.
We hope to make this nicer when we upgrade to (the as of yet unreleased) Akka HTTP 10.2.0, which will have better features for converting between functions and routes (https://github.com/akka/akka-http/pull/3367, https://github.com/akka/akka-http/pull/3239), though this is not complete yet.
If you could try Akka gRPC with an Akka HTTP 10.2 snapshot and provide feedback/propose improvements, that would be really helpful!
OH! Okay I understand now. I guess the functionality I was looking for was to have the Service itself be authenticated, whereas the reflection isn't. But have them both be on the same port. That's my server setup looks a bit awkward, I'm trying to get the authenticated server match the unauthenticated setup.
import akka.actor.ActorSystem
import akka.grpc.scaladsl.ServiceHandler
import akka.http.scaladsl.server.{Directive0, Route, RouteResult}
import akka.stream.ActorMaterializer
import com.sony.sie.caprica.grpc.Service
import scala.concurrent.ExecutionContext
class AuthenticatedGrpcServer(
port: Int,
authenticator: Directive0,
authedServices: Service*
)(
implicit val ec: ExecutionContext,
system: ActorSystem,
materializer: ActorMaterializer
) extends Server(port, interceptor) {
override val services: Route =
authenticator { ctx =>
ServiceHandler
.concat(authedServices: _*)(ctx.request)
.map(RouteResult.Complete)
}
}
I guess the functionality I was looking for was to have the Service itself be authenticated, whereas the reflection isn't
Aah, gotcha! For now you could probably get away with something like:
val reflectionRoute: Route = {
{ ctx =>
reflection
.andThen(_.fast.map(RouteResult.Complete)(ctx.executionContext))
.applyOrElse[HttpRequest, Future[RouteResult]](ctx.request, _ => ctx.reject())
}
}
concat(
reflectionRoute,
services
)
Let me try that and I'll report back!
That worked thanks! You can close this issue if you'd like or just tie it to whatever improvement y'all have in the works
although the fix was without .fast
val reflectionRoute: Route = {
{ ctx =>
reflection
.andThen(_.map(RouteResult.Complete)(ctx.executionContext))
.applyOrElse[HttpRequest, Future[RouteResult]](ctx.request, _ => ctx.reject())
}
}
concat(
reflectionRoute,
services
)
Versions used
Akka-grpc version: 1.0.0
Expected Behavior
Concating
Route
of server and reflection results in both working on same portActual Behavior
Concating partial routes leads to first route only being evaluated
Relevant logs
Reproducible Test Case