From 5ec270aa98b806f32338fa25357abdf45dd0625b Mon Sep 17 00:00:00 2001 From: Jakob Odersky Date: Wed, 22 Aug 2018 12:51:36 -0700 Subject: Trait-based initialization and other utilities Adds the concept of a 'platform', a centralized place in which environment-specific information will be managed, and provides common initialization logic for most "standard" apps. As part of the common initialization, other parts of core have also been reworked: - HTTP-related unmarshallers and path matchers have been factored out from core.json to a new core.rest.directives package (core.json extends those unmarshallers and matchers for backwards compatibility) - CORS handling has also been moved to a dedicated utility trait - Some custom headers have been moved from raw headers to typed ones in core.rest.headers - The concept of a "reporter" has been introduced. A reporter is a context-aware combination of tracing and logging. It is intended to issue diagnostic messages that can be traced across service boundaries. Closes #192 Closes #195 --- src/main/scala/xyz/driver/core/init/HttpApi.scala | 89 +++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 src/main/scala/xyz/driver/core/init/HttpApi.scala (limited to 'src/main/scala/xyz/driver/core/init/HttpApi.scala') diff --git a/src/main/scala/xyz/driver/core/init/HttpApi.scala b/src/main/scala/xyz/driver/core/init/HttpApi.scala new file mode 100644 index 0000000..6ea3d51 --- /dev/null +++ b/src/main/scala/xyz/driver/core/init/HttpApi.scala @@ -0,0 +1,89 @@ +package xyz.driver.core +package init + +import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport +import akka.http.scaladsl.server.{RequestContext, Route, RouteConcatenation} +import spray.json.DefaultJsonProtocol._ +import spray.json._ +import xyz.driver.core.rest.Swagger +import xyz.driver.core.rest.directives.Directives +import akka.http.scaladsl.model.headers._ +import xyz.driver.core.reporting.Reporter.CausalRelation +import xyz.driver.core.reporting.SpanContext +import xyz.driver.core.rest.headers.Traceparent + +import scala.collection.JavaConverters._ + +/** Mixin trait that provides some well-known HTTP endpoints, diagnostic header injection and forwarding, + * and exposes an application-specific route that must be implemented by services. + * @see ProtobufApi + */ +trait HttpApi extends CloudServices with Directives with SprayJsonSupport { self => + + /** Route that handles the application's business logic. + * @group hooks + */ + def applicationRoute: Route + + /** Classes with Swagger annotations. + * @group hooks + */ + def swaggerRouteClasses: Set[Class[_]] + + private val healthRoute = path("health") { + complete(Map("status" -> "good").toJson) + } + + private val versionRoute = path("version") { + complete(Map("name" -> self.name.toJson, "version" -> self.version.toJson).toJson) + } + + private lazy val swaggerRoute = { + val generator = new Swagger( + "", + "https" :: "http" :: Nil, + self.version.getOrElse(""), + swaggerRouteClasses, + config, + reporter + ) + generator.routes ~ generator.swaggerUI + } + + private def cors(inner: Route): Route = + cors( + config.getStringList("application.cors.allowedOrigins").asScala.toSet, + xyz.driver.core.rest.AllowedHeaders + )(inner) + + private def traced(inner: Route): Route = (ctx: RequestContext) => { + val tags = Map( + "service_name" -> name, + "service_version" -> version.getOrElse(""), + "http_user_agent" -> ctx.request.header[`User-Agent`].map(_.value).getOrElse(""), + "http_uri" -> ctx.request.uri.toString, + "http_path" -> ctx.request.uri.path.toString + ) + val parent = ctx.request.header[Traceparent].map { p => + SpanContext(p.traceId, p.spanId) -> CausalRelation.Child + } + reporter.traceWithOptionalParentAsync("handle_service_request", tags, parent) { sctx => + val header = Traceparent(sctx.traceId, sctx.spanId) + val withHeader = ctx.withRequest(ctx.request.withHeaders(header)) + inner(withHeader) + } + } + + /** Extended route. */ + override lazy val route: Route = traced( + cors( + RouteConcatenation.concat( + healthRoute, + versionRoute, + swaggerRoute, + applicationRoute + ) + ) + ) + +} -- cgit v1.2.3