From f6ce05cf617bb014a3d65c4cb996894a9f4d940b Mon Sep 17 00:00:00 2001 From: Fabio Pinheiro Date: Tue, 7 Nov 2023 17:20:01 +0000 Subject: [PATCH] Update zio-http to 3.0.0-RC3 (#165) Signed-off-by: Fabio Pinheiro Signed-off-by: Shailesh Patil --- build.sbt | 2 +- .../mediator/comm/MessageDispatcherJVM.scala | 12 +- .../atala/mediator/utils/HttpHelpers.scala | 2 + .../iohk/atala/mediator/app/IndexHtml.scala | 57 +++--- .../atala/mediator/app/MediatorAgent.scala | 173 ++++++++---------- .../mediator/app/MediatorStandalone.scala | 26 +-- .../io/iohk/atala/mediator/AppUtils.scala | 3 +- 7 files changed, 121 insertions(+), 154 deletions(-) diff --git a/build.sbt b/build.sbt index 2dfdcaa3..16a75996 100644 --- a/build.sbt +++ b/build.sbt @@ -23,7 +23,7 @@ lazy val V = new { val zio = "2.0.18" val zioJson = "0.6.2" // val zioMunitTest = "0.1.1" - val zioHttp = "3.0.0-RC2" + val zioHttp = "3.0.0-RC3" val zioConfig = "4.0.0-RC16" val zioLogging = "2.1.14" val zioSl4j = "2.1.14" diff --git a/http-utils/jvm/src/main/scala/io/iohk/atala/mediator/comm/MessageDispatcherJVM.scala b/http-utils/jvm/src/main/scala/io/iohk/atala/mediator/comm/MessageDispatcherJVM.scala index 81623bfd..2704c260 100644 --- a/http-utils/jvm/src/main/scala/io/iohk/atala/mediator/comm/MessageDispatcherJVM.scala +++ b/http-utils/jvm/src/main/scala/io/iohk/atala/mediator/comm/MessageDispatcherJVM.scala @@ -33,14 +33,12 @@ class MessageDispatcherJVM(client: Client) extends MessageDispatcher { .pipe(e => Header.ContentType(ZMediaType.application.any.copy(subType = "didcomm-encrypted+json"))) val xForwardedHostHeader = xForwardedHost.map(x => Header.Custom(customName = MyHeaders.xForwardedHost, x)) - // xForwardedHost.map(x => Header.(MyHeaders.xForwardedHost, x)) for { res <- Client .request( - url = destination, - method = Method.POST, - headers = Headers(Seq(Some(contentTypeHeader), xForwardedHostHeader).flatten), - content = Body.fromCharSequence(msg.toJson), + Request + .post(destination, Body.fromCharSequence(msg.toJson)) + .setHeaders(Headers(Seq(Some(contentTypeHeader), xForwardedHostHeader).flatten)) ) .tapError(ex => ZIO.logWarning(s"Fail when calling '$destination': ${ex.toString}")) .mapError(ex => DispatcherError(ex)) @@ -51,5 +49,7 @@ class MessageDispatcherJVM(client: Client) extends MessageDispatcher { case true => ZIO.logWarning(data) case false => ZIO.logInfo(data) } yield (data) - }.provideEnvironment(ZEnvironment(client)) + } + .provideSomeLayer(Scope.default) + .provideEnvironment(ZEnvironment(client)) } diff --git a/http-utils/jvm/src/main/scala/io/iohk/atala/mediator/utils/HttpHelpers.scala b/http-utils/jvm/src/main/scala/io/iohk/atala/mediator/utils/HttpHelpers.scala index 48577fa1..1038b029 100644 --- a/http-utils/jvm/src/main/scala/io/iohk/atala/mediator/utils/HttpHelpers.scala +++ b/http-utils/jvm/src/main/scala/io/iohk/atala/mediator/utils/HttpHelpers.scala @@ -1,3 +1,4 @@ +/* package io.iohk.atala.mediator.utils import zio.* @@ -50,3 +51,4 @@ object MiddlewareUtils { } } + */ diff --git a/mediator/src/main/scala/io/iohk/atala/mediator/app/IndexHtml.scala b/mediator/src/main/scala/io/iohk/atala/mediator/app/IndexHtml.scala index f5923e5e..0af47f53 100644 --- a/mediator/src/main/scala/io/iohk/atala/mediator/app/IndexHtml.scala +++ b/mediator/src/main/scala/io/iohk/atala/mediator/app/IndexHtml.scala @@ -1,31 +1,38 @@ package io.iohk.atala.mediator.app -import zio.http.Response +import zio.http._ import fmgp.did.DID object IndexHtml { - // TODO use the html.Html.fromDomElement() - def html(identity: DID) = Response.html(s""" - | - | - | IOHK Mediator - | - | - | - | - | - | - | - | - | - | - | - |
- | - | - |""".stripMargin) + def html(identity: DID) = + Response( + status = Status.Ok, + headers = Headers(Header.ContentType(MediaType.text.html).untyped), + body = Body.fromString( + s""" + | + | + | + | IOHK Mediator + | + | + | + | + | + | + | + | + | + | + | + |
+ | + | + |""".stripMargin + ), + ) } diff --git a/mediator/src/main/scala/io/iohk/atala/mediator/app/MediatorAgent.scala b/mediator/src/main/scala/io/iohk/atala/mediator/app/MediatorAgent.scala index a79dd525..6da8785d 100644 --- a/mediator/src/main/scala/io/iohk/atala/mediator/app/MediatorAgent.scala +++ b/mediator/src/main/scala/io/iohk/atala/mediator/app/MediatorAgent.scala @@ -14,7 +14,6 @@ import io.iohk.atala.mediator.db.* import io.iohk.atala.mediator.protocols.* import io.iohk.atala.mediator.utils.* import io.netty.handler.codec.http.HttpHeaderNames -import reactivemongo.api.bson.Macros.{*, given} import reactivemongo.api.bson.{*, given} import zio.* import zio.http.* @@ -23,7 +22,6 @@ import zio.json.* import scala.concurrent.ExecutionContext.Implicits.global import scala.util.Try import scala.io.Source -import zio.http.internal.middlewares.Cors.CorsConfig import zio.http.Header.AccessControlAllowOrigin import zio.http.Header.AccessControlAllowMethods @@ -223,18 +221,20 @@ object MediatorAgent { def make(id: DID, keyStore: KeyStore): ZIO[Any, Nothing, MediatorAgent] = ZIO.succeed(MediatorAgent(id, keyStore)) def didCommApp = { - Http.collectZIO[Request] { - case req @ Method.GET -> Root / "headers" => + Routes( + Method.GET / "headers" -> handler { (req: Request) => val data = req.headers.toSeq.map(e => (e.headerName, e.renderedValue)) ZIO.succeed(Response.text("HEADERS:\n" + data.mkString("\n") + "\nRemoteAddress:" + req.remoteAddress)).debug - case req @ Method.GET -> Root / "health" => ZIO.succeed(Response.ok) - case Method.GET -> Root / "version" => ZIO.succeed(Response.text(MediatorBuildInfo.version)) - case Method.GET -> Root / "did" => + }, + Method.GET / "health" -> handler { (req: Request) => ZIO.succeed(Response.ok) }, + Method.GET / "version" -> handler { (req: Request) => ZIO.succeed(Response.text(MediatorBuildInfo.version)) }, + Method.GET / "did" -> handler { (req: Request) => for { agent <- ZIO.service[MediatorAgent] ret <- ZIO.succeed(Response.text(agent.id.string)) } yield (ret) - case Method.GET -> Root / "invitation" => + }, + Method.GET / "invitation" -> handler { (req: Request) => for { agent <- ZIO.service[MediatorAgent] annotationMap <- ZIO.logAnnotations.map(_.map(e => LogAnnotation(e._1, e._2)).toSeq) @@ -247,7 +247,8 @@ object MediatorAgent { _ <- ZIO.log("New mediate invitation MsgID: " + invitation.id.value) ret <- ZIO.succeed(Response.json(invitation.toPlaintextMessage.toJson)) } yield (ret) - case Method.GET -> Root / "invitationOOB" => + }, + Method.GET / "invitationOOB" -> handler { (req: Request) => for { agent <- ZIO.service[MediatorAgent] annotationMap <- ZIO.logAnnotations.map(_.map(e => LogAnnotation(e._1, e._2)).toSeq) @@ -263,98 +264,78 @@ object MediatorAgent { OutOfBandPlaintext.from(invitation.toPlaintextMessage).makeURI("") ) ) - } yield (ret) - case req @ Method.POST -> Root - if req.headers - // .header(Header.ContentType) // TODO BUG? this does not work - .get("content-type") - .exists { h => - // TODO after fix BUG - // h.mediaType.mainType == "application" && - // (h.mediaType.subType == "didcomm-signed+json" || h.mediaType.subType == "didcomm-encrypted+json") - // TODO after update lib - // h.mediaType.mainType == ZMediaTypes.mainType && - // (h.mediaType.subType == MediaTypes.SIGNED.subType || h.mediaType.subType == MediaTypes.ENCRYPTED.subType) - h == MediaTypes.SIGNED.typ || h == MediaTypes.ENCRYPTED.typ - } => - for { - agent <- ZIO.service[MediatorAgent] - data <- req.body.asString - ret <- agent - .receiveMessage(data) - .map { - case None => Response.ok - case Some(value: SignedMessage) => Response.json(value.toJson) - case Some(value: EncryptedMessage) => Response.json(value.toJson) - } - .catchAll { - case MediatorDidError(error) => - ZIO.logError(s"Error MediatorDidError: $error") *> - ZIO.succeed(Response.status(Status.BadRequest)) - case MediatorThrowable(error) => - ZIO.logError(s"Error MediatorThrowable: $error") *> - ZIO.succeed(Response.status(Status.BadRequest)) - case StorageCollection(error) => - ZIO.logError(s"Error StorageCollection: $error") *> - ZIO.succeed(Response.status(Status.BadRequest)) - case StorageThrowable(error) => - ZIO.logError(s"Error StorageThrowable: $error") *> - ZIO.succeed(Response.status(Status.BadRequest)) - case DuplicateMessage(error) => - ZIO.logError(s"Error DuplicateKeyError: $error") *> - ZIO.succeed(Response.status(Status.BadRequest)) - case MissingProtocolError(piuri) => - ZIO.logError(s"MissingProtocolError ('$piuri')") *> - ZIO.succeed(Response.status(Status.BadRequest)) // TODO - } - } yield ret - // TODO [return_route extension](https://github.com/decentralized-identity/didcomm-messaging/blob/main/extensions/return_route/main.md) - case req @ Method.POST -> Root => - ZIO - .logError(s"Request Headers: ${req.headers.mkString(",")}") - .as( - Response - .text(s"The content-type must be ${MediaTypes.SIGNED.typ} or ${MediaTypes.ENCRYPTED.typ}") - .copy(status = Status.BadRequest) - ) - case req @ Method.GET -> Root => { // html.Html.fromDomElement() + }, + Method.POST / trailing -> handler { (req: Request) => + { + if ( + req.headers + .get("content-type") + .exists { h => h == MediaTypes.SIGNED.typ || h == MediaTypes.ENCRYPTED.typ } + ) { + for { + agent <- ZIO.service[MediatorAgent] + data <- req.body.asString + .catchAll(ex => ZIO.fail(Response.badRequest("Unable to read the body of the request"))) + ret <- agent + .receiveMessage(data) + .map { + case None => Response.ok + case Some(value: SignedMessage) => Response.json(value.toJson) + case Some(value: EncryptedMessage) => Response.json(value.toJson) + } + .catchAll { + case MediatorDidError(error) => + ZIO.logError(s"Error MediatorDidError: $error") *> + ZIO.succeed(Response.status(Status.BadRequest)) + case MediatorThrowable(error) => + ZIO.logError(s"Error MediatorThrowable: $error") *> + ZIO.succeed(Response.status(Status.BadRequest)) + case StorageCollection(error) => + ZIO.logError(s"Error StorageCollection: $error") *> + ZIO.succeed(Response.status(Status.BadRequest)) + case StorageThrowable(error) => + ZIO.logError(s"Error StorageThrowable: $error") *> + ZIO.succeed(Response.status(Status.BadRequest)) + case DuplicateMessage(error) => + ZIO.logError(s"Error DuplicateKeyError: $error") *> + ZIO.succeed(Response.status(Status.BadRequest)) + case MissingProtocolError(piuri) => + ZIO.logError(s"MissingProtocolError ('$piuri')") *> + ZIO.succeed(Response.status(Status.BadRequest)) // TODO + } + } yield ret + } else + ZIO + .logError(s"Request Headers: ${req.headers.mkString(",")}") + .as( + Response + .text(s"The content-type must be ${MediaTypes.SIGNED.typ} or ${MediaTypes.ENCRYPTED.typ}") + .copy(status = Status.BadRequest) + ) + } + }, + Method.GET / trailing -> handler { (req: Request) => for { agent <- ZIO.service[MediatorAgent] _ <- ZIO.log("index.html") ret <- ZIO.succeed(IndexHtml.html(agent.id)) } yield ret - } - }: Http[ - Operations & Resolver & MessageDispatcher & MediatorAgent & MessageItemRepo & UserAccountRepo & OutboxMessageRepo, - Throwable, - Request, - Response - ] - } ++ Http - .fromResource(s"public/webapp-fastopt-bundle.js.gz") - .map(_.setHeaders(Headers(Header.ContentType(MediaType.application.javascript), Header.ContentEncoding.GZip))) - .when { - case Method.GET -> Root / "public" / "webapp-fastopt-bundle.js" => true - case _ => false - } - @@ HttpAppMiddleware.cors( - CorsConfig( - allowedOrigin = { - // case origin @ Origin.Value(_, host, _) if host == "dev" => Some(AccessControlAllowOrigin.Specific(origin)) - case _ => Some(AccessControlAllowOrigin.All) - }, - allowedMethods = AccessControlAllowMethods(Method.GET, Method.POST, Method.OPTIONS), - ) + }, + Method.GET / "public" / string("path") -> handler { (path: String, req: Request) => + // RoutesMiddleware + // TODO https://zio.dev/reference/stream/zpipeline/#:~:text=ZPipeline.gzip%20%E2%80%94%20The%20gzip%20pipeline%20compresses%20a%20stream%20of%20bytes%20as%20using%20gzip%20method%3A + val fullPath = s"public/$path" + val classLoader = Thread.currentThread().getContextClassLoader() + val headerContentType = fullPath match + case s if s.endsWith(".html") => Header.ContentType(MediaType.text.html) + case s if s.endsWith(".js") => Header.ContentType(MediaType.text.javascript) + case s if s.endsWith(".css") => Header.ContentType(MediaType.text.css) + case s if s.endsWith(".svg") => Header.ContentType(MediaType.image.`svg+xml`) + case s => Header.ContentType(MediaType.text.plain) + Handler.fromResource(fullPath).map(_.addHeader(headerContentType)) + }.flatten ) - // @@ - // HttpAppMiddleware.updateHeaders(headers => - // Headers( - // headers.map(h => - // if (h.key == HttpHeaderNames.ACCESS_CONTROL_ALLOW_ORIGIN) { - // Header(HttpHeaderNames.ACCESS_CONTROL_ALLOW_ORIGIN, "*") - // } else h - // ) - // ) - // ) + }.sandbox.toHttpApp + } diff --git a/mediator/src/main/scala/io/iohk/atala/mediator/app/MediatorStandalone.scala b/mediator/src/main/scala/io/iohk/atala/mediator/app/MediatorStandalone.scala index 5b1b49ec..e7d36fa4 100644 --- a/mediator/src/main/scala/io/iohk/atala/mediator/app/MediatorStandalone.scala +++ b/mediator/src/main/scala/io/iohk/atala/mediator/app/MediatorStandalone.scala @@ -16,8 +16,6 @@ import zio.config.* import zio.config.magnolia.* import zio.config.typesafe.* import zio.http.* -import zio.http.Http.{Empty, Static} -import zio.http.ZClient.ClientLive import zio.json.* import zio.logging.LogFormat.* import zio.logging.backend.SLF4J @@ -57,17 +55,6 @@ object MediatorStandalone extends ZIOAppDefault { override val bootstrap: ZLayer[ZIOAppArgs, Any, Any] = Runtime.removeDefaultLoggers >>> SLF4J.slf4j(mediatorColorFormat) - // val app: HttpApp[ // type HttpApp[-R, +Err] = Http[R, Err, Request, Response] - // Hub[String] & Operations & MessageDispatcher & MediatorAgent & Resolver & MessageItemRepo & UserAccountRepo & - // OutboxMessageRepo, - // Throwable - // ] - val app: Http[ - Operations & Resolver & UserAccountRepo & OutboxMessageRepo & MessageDispatcher & MediatorAgent & MessageItemRepo, - (HttpAppMiddleware[Nothing, Any, Nothing, Any] | HttpAppMiddleware[Nothing, Any, Nothing, Any])#OutErr[Throwable], - Request, - Response - ] = MediatorAgent.didCommApp override val run = for { _ <- Console.printLine( // https://patorjk.com/software/taag/#p=display&f=ANSI%20Shadow&t=Mediator """███╗ ███╗███████╗██████╗ ██╗ █████╗ ████████╗ ██████╗ ██████╗ @@ -103,18 +90,7 @@ object MediatorStandalone extends ZIOAppDefault { client = Scope.default >>> Client.default inboundHub <- Hub.bounded[String](5) myServer <- Server - .serve( - (app @@ (MiddlewareUtils.annotateHeaders ++ MiddlewareUtils.serverTime)) - .tapUnhandledZIO(ZIO.logError("Unhandled Endpoint")) - .tapErrorCauseZIO(cause => ZIO.logErrorCause(cause)) // THIS is to log all the erros - .mapError(err => - Response( - status = Status.BadRequest, - headers = Headers.empty, - body = Body.fromString(err.toString()), // Body.fromString(err.getMessage()), - ) - ) - ) + .serve(MediatorAgent.didCommApp @@ (Middleware.cors)) .provideSomeLayer(DidPeerResolver.layerDidPeerResolver) .provideSomeLayer(mediatorConfig.agentLayer) // .provideSomeLayer(AgentByHost.layer) .provideSomeLayer( diff --git a/webapp/src/main/scala/io/iohk/atala/mediator/AppUtils.scala b/webapp/src/main/scala/io/iohk/atala/mediator/AppUtils.scala index aebe5586..9a0c044b 100644 --- a/webapp/src/main/scala/io/iohk/atala/mediator/AppUtils.scala +++ b/webapp/src/main/scala/io/iohk/atala/mediator/AppUtils.scala @@ -96,7 +96,8 @@ object AppUtils { href := "https://atalaprism.io", target := "_blank", img( - src := "https://atalaprism.io/images/atala-prism-logo-suite.svg", + // src := "https://atalaprism.io/images/atala-prism-logo-suite.svg", + src := "public/atala-prism-logo-suite.svg", // Note: this is not the best server for CDN className := "logo vanilla", alt := "Prism Mediator" ),