/interop-tests/src/main/scala/akka/grpc/interop/AkkaGrpcServerScala.scala

https://github.com/akka/akka-grpc · Scala · 87 lines · 62 code · 19 blank · 6 comment · 0 complexity · d7603868128d6fd31969c4629e340d4a MD5 · raw file

  1. /*
  2. * Copyright (C) 2018-2020 Lightbend Inc. <https://www.lightbend.com>
  3. */
  4. package akka.grpc.interop
  5. import java.io.FileInputStream
  6. import java.nio.file.{ Files, Paths }
  7. import java.security.cert.CertificateFactory
  8. import java.security.spec.PKCS8EncodedKeySpec
  9. import java.security.{ KeyFactory, KeyStore, SecureRandom }
  10. import scala.concurrent.duration._
  11. import akka.actor.ActorSystem
  12. import akka.util.ByteString
  13. import akka.http.scaladsl.Http.ServerBinding
  14. import akka.http.scaladsl.model.{ HttpRequest, HttpResponse }
  15. import akka.http.scaladsl.{ ConnectionContext, Http2 }
  16. import akka.stream.SystemMaterializer
  17. import io.grpc.internal.testing.TestUtils
  18. import javax.net.ssl.{ KeyManagerFactory, SSLContext }
  19. import scala.concurrent.{ Await, Future }
  20. /**
  21. * Glue code to start a gRPC server based on the akka-grpc Scala API to test against
  22. */
  23. case class AkkaGrpcServerScala(serverHandlerFactory: ActorSystem => HttpRequest => Future[HttpResponse])
  24. extends GrpcServer[(ActorSystem, ServerBinding)] {
  25. override def start() = {
  26. implicit val sys = ActorSystem()
  27. implicit val mat = SystemMaterializer(sys).materializer
  28. val testService = serverHandlerFactory(sys)
  29. val bindingFuture = Http2().bindAndHandleAsync(
  30. testService,
  31. interface = "127.0.0.1",
  32. port = 0,
  33. parallelism = 256, // TODO remove once https://github.com/akka/akka-http/pull/2146 is merged
  34. connectionContext = serverHttpContext())
  35. val binding = Await.result(bindingFuture, 10.seconds)
  36. (sys, binding)
  37. }
  38. override def stop(binding: (ActorSystem, ServerBinding)) =
  39. binding match {
  40. case (sys, binding) =>
  41. sys.log.info("Exception thrown, unbinding")
  42. Await.result(binding.unbind(), 10.seconds)
  43. Await.result(sys.terminate(), 10.seconds)
  44. }
  45. private def serverHttpContext() = {
  46. val keyEncoded =
  47. new String(Files.readAllBytes(Paths.get(TestUtils.loadCert("server1.key").getAbsolutePath)), "UTF-8")
  48. .replace("-----BEGIN PRIVATE KEY-----\n", "")
  49. .replace("-----END PRIVATE KEY-----\n", "")
  50. .replace("\n", "")
  51. val decodedKey = ByteString(keyEncoded).decodeBase64.toArray
  52. val spec = new PKCS8EncodedKeySpec(decodedKey)
  53. val kf = KeyFactory.getInstance("RSA")
  54. val privateKey = kf.generatePrivate(spec)
  55. val fact = CertificateFactory.getInstance("X.509")
  56. val is = new FileInputStream(TestUtils.loadCert("server1.pem"))
  57. val cer = fact.generateCertificate(is)
  58. val ks = KeyStore.getInstance("PKCS12")
  59. ks.load(null)
  60. ks.setKeyEntry("private", privateKey, Array.empty, Array(cer))
  61. val keyManagerFactory = KeyManagerFactory.getInstance("SunX509")
  62. keyManagerFactory.init(ks, null)
  63. val context = SSLContext.getInstance("TLS")
  64. context.init(keyManagerFactory.getKeyManagers, null, new SecureRandom)
  65. ConnectionContext.httpsServer(context)
  66. }
  67. override def getPort(binding: (ActorSystem, ServerBinding)): Int = binding._2.localAddress.getPort
  68. }