Server Reflection

Note

This feature is experimental (Issue #850).

It implements version v1alpha of the upstream standard, so we might expect subsequent versions of the service to emerge. Also, the Java/Scala API’s to enable this feature may still change in further versions of Akka gRPC, and future versions of this feature may not work with services generated with older versions of Akka gRPC.

There may be missing features and bugs in the current implementation. If you encounter any, you are welcome to share a reproducer in our issue tracker.

Server Reflection is a gRPC feature that allows ‘dynamic’ clients, such as command-line tools for debugging, to discover the protocol used by a gRPC server at run time. They can then use this metadata to implement things like completion and sending arbitrary commands.

This is achieved by providing a gRPC service that provides endpoints that can be used to query this information

Providing

When providing gRPC Server Reflection, you will be serving multiple services (at least your own service and the reflection service) as described here. The reflection service can be generated via ServerReflection:

Scala
import akka.http.scaladsl._
import akka.http.scaladsl.model._

import akka.grpc.scaladsl.ServiceHandler
import akka.grpc.scaladsl.ServerReflection

import example.myapp.helloworld.grpc._

// Create service handlers
val greeter: PartialFunction[HttpRequest, Future[HttpResponse]] =
  GreeterServiceHandler.partial(new GreeterServiceImpl())
val reflection: PartialFunction[HttpRequest, Future[HttpResponse]] =
  ServerReflection.partial(List(GreeterService))

// Bind service handler servers to localhost:8080
val binding = Http().bindAndHandleAsync(
  ServiceHandler.concatOrNotFound(greeter, reflection),
  interface = "127.0.0.1",
  port = 8080,
  connectionContext = HttpConnectionContext())
Java
import java.util.Arrays;

import akka.grpc.javadsl.ServiceHandler;
import akka.grpc.javadsl.ServerReflection;
import akka.http.javadsl.*;

import example.myapp.helloworld.grpc.*;

// Instantiate implementation
GreeterService impl = new GreeterServiceImpl();

// Bind service handler servers to localhost:8080
return Http.get(sys).bindAndHandleAsync(
    ServiceHandler.concatOrNotFound(
        GreeterServiceHandlerFactory.create(impl, sys),
        ServerReflection.create(Arrays.asList(GreeterService.description), sys)
    ),
    ConnectHttp.toHost("127.0.0.1", 8080),
    mat);

Consuming

The Server Reflection endpoint exposed above can be used for example to consume the service with grpc_cli:

$ ./bins/opt/grpc_cli call localhost:8080 helloworld.GreeterService.SayHello "name:\"foo\""
connecting to localhost:8080
Received initial metadata from server:
date : Wed, 08 Jan 2020 16:57:56 GMT
server : akka-http/10.1.10
message: "Hello, foo"

Received trailing metadata from server:
date : Wed, 08 Jan 2020 16:57:56 GMT
Rpc succeeded with OK status
Found an error in this documentation? The source code for this page can be found here. Please feel free to edit and contribute a pull request.