From fcbbebf0012df602305c59c3a00057bd8f282ca7 Mon Sep 17 00:00:00 2001 From: Nabil Abdel-Hafeez <7283535+987Nabil@users.noreply.github.com> Date: Sun, 9 Jun 2024 23:15:36 +0200 Subject: [PATCH] Simpler default `Endpoint#implement` (#2811) (#2894) Co-authored-by: John A. De Goes --- docs/reference/endpoint.md | 8 +-- .../zio/http/grpc/ZIOHttpGRPCGenSpec.scala | 6 +- .../http/benchmarks/EndpointBenchmark.scala | 36 +++++----- .../main/scala/example/EndpointExamples.scala | 12 +--- .../example/ServerSentEventEndpoint.scala | 2 +- .../endpoint/BooksEndpointExample.scala | 2 +- .../scala/example/endpoint/CliExamples.scala | 6 +- ...ndpointWithMultipleErrorsUsingEither.scala | 2 +- .../EndpointWithMultipleUnifiedErrors.scala | 2 +- .../style/DeclarativeProgrammingExample.scala | 2 +- .../scala/zio/http/StaticFileRoutesSpec.scala | 7 +- .../scala/zio/http/endpoint/AuthSpec.scala | 4 +- .../zio/http/endpoint/BadRequestSpec.scala | 12 ++-- .../zio/http/endpoint/CustomErrorSpec.scala | 6 +- .../zio/http/endpoint/MultipartSpec.scala | 14 ++-- .../zio/http/endpoint/NotFoundSpec.scala | 8 +-- .../http/endpoint/QueryParameterSpec.scala | 28 ++++---- .../scala/zio/http/endpoint/RequestSpec.scala | 68 +++++++++---------- .../zio/http/endpoint/RoundtripSpec.scala | 30 ++++---- .../http/endpoint/openapi/SwaggerUISpec.scala | 4 +- .../scala/zio/http/endpoint/Endpoint.scala | 27 +++++++- 21 files changed, 152 insertions(+), 134 deletions(-) diff --git a/docs/reference/endpoint.md b/docs/reference/endpoint.md index 22a6bf5f27..46563e41e5 100644 --- a/docs/reference/endpoint.md +++ b/docs/reference/endpoint.md @@ -34,7 +34,7 @@ In the above example, we defined an endpoint on the path `/books` that accepts a After defining the endpoint, we are ready to implement it. We can implement it using the `Endpoint#implement` method, which takes a proper handler function that will be called when the endpoint is invoked and returns a `Route`: ```scala -val booksRoute = endpoint.implement(handler((query: String) => BookRepo.find(query))) +val booksRoute = endpoint.implement(query => BookRepo.find(query)) ``` We can also generate OpenAPI documentation for our endpoint using the `OpenAPIGen.fromEndpoints` constructor: @@ -261,13 +261,13 @@ object EndpointWithMultipleOutputTypes extends ZIOAppDefault { .out[Quiz] def run = Server.serve( - endpoint.implement(handler { + endpoint.implement(_ => ZIO.randomWith(_.nextBoolean) .map(r => if (r) Right(Course("Introduction to Programming", 49.99)) else Left(Quiz("What is the boiling point of water in Celsius?", 2)), ) - }) + ) .toRoutes).provide(Server.default, Scope.default) } ``` @@ -417,7 +417,7 @@ case class Book( The `OpenAPIGen.fromEndpoints` constructor generates OpenAPI documentation from the endpoints. By having the OpenAPI documentation, we can easily generate Swagger UI routes using the `SwaggerUI.routes` constructor: ```scala -val booksRoute = endpoint.implement(handler((query: String) => BookRepo.find(query))) +val booksRoute = endpoint.implement(query => BookRepo.find(query)) val openAPI = OpenAPIGen.fromEndpoints(title = "Library API", version = "1.0", endpoint) val swaggerRoutes = SwaggerUI.routes("docs" / "openapi", openAPI) val routes = Routes(booksRoute) ++ swaggerRoutes diff --git a/sbt-zio-http-grpc-tests/src/test/scala/zio/http/grpc/ZIOHttpGRPCGenSpec.scala b/sbt-zio-http-grpc-tests/src/test/scala/zio/http/grpc/ZIOHttpGRPCGenSpec.scala index 4b9fa8c124..38cf5b4630 100644 --- a/sbt-zio-http-grpc-tests/src/test/scala/zio/http/grpc/ZIOHttpGRPCGenSpec.scala +++ b/sbt-zio-http-grpc-tests/src/test/scala/zio/http/grpc/ZIOHttpGRPCGenSpec.scala @@ -13,11 +13,7 @@ object ZIOHttpGRPCGenSpec extends ZIOSpecDefault { assertTrue(true) }, test("plugin generates Endpoint") { - val impl = V1.test.implement { - Handler.fromFunction[TestMsg] { msg => - msg - } - } + val impl = V1.test.implementPurely { msg => msg } assertTrue(true) }, ) diff --git a/zio-http-benchmarks/src/main/scala-2.13/zio/http/benchmarks/EndpointBenchmark.scala b/zio-http-benchmarks/src/main/scala-2.13/zio/http/benchmarks/EndpointBenchmark.scala index 21f76759e8..0dc79c735d 100644 --- a/zio-http-benchmarks/src/main/scala-2.13/zio/http/benchmarks/EndpointBenchmark.scala +++ b/zio-http-benchmarks/src/main/scala-2.13/zio/http/benchmarks/EndpointBenchmark.scala @@ -95,7 +95,7 @@ class EndpointBenchmark { .out[ExampleData] val handledUsersPosts = - usersPosts.implement { + usersPosts.implementHandler { Handler.fromFunction { case (userId, postId, limit) => ExampleData(userId, postId, limit) } @@ -218,7 +218,7 @@ class EndpointBenchmark { ) / "seventh" / int("id5"), ) .out[Unit] - .implement(Handler.unit) + .implementHandler(Handler.unit) .toRoutes // Collect DSL @@ -333,20 +333,20 @@ class EndpointBenchmark { // API DSL - val broadUsers = Endpoint(Method.GET / "users").out[Unit].implement(Handler.unit) + val broadUsers = Endpoint(Method.GET / "users").out[Unit].implementHandler(Handler.unit) val broadUsersId = - Endpoint(Method.GET / "users" / int("userId")).out[Unit].implement(Handler.unit) + Endpoint(Method.GET / "users" / int("userId")).out[Unit].implementHandler(Handler.unit) val boardUsersPosts = Endpoint(Method.GET / "users" / int("userId") / "posts") .out[Unit] - .implement(Handler.unit) + .implementHandler(Handler.unit) val boardUsersPostsId = Endpoint( Method.GET / "users" / int("userId") / "posts" / int("postId"), ) .out[Unit] - .implement(Handler.unit) + .implementHandler(Handler.unit) val boardUsersPostsComments = Endpoint( Method.GET / @@ -355,7 +355,7 @@ class EndpointBenchmark { ) / "comments", ) .out[Unit] - .implement(Handler.unit) + .implementHandler(Handler.unit) val boardUsersPostsCommentsId = Endpoint( Method.GET / @@ -364,14 +364,14 @@ class EndpointBenchmark { ) / "comments" / int("commentId"), ) .out[Unit] - .implement(Handler.unit) - val broadPosts = Endpoint(Method.GET / "posts").out[Unit].implement(Handler.unit) + .implementHandler(Handler.unit) + val broadPosts = Endpoint(Method.GET / "posts").out[Unit].implementHandler(Handler.unit) val broadPostsId = - Endpoint(Method.GET / "posts" / int("postId")).out[Unit].implement(Handler.unit) + Endpoint(Method.GET / "posts" / int("postId")).out[Unit].implementHandler(Handler.unit) val boardPostsComments = Endpoint(Method.GET / "posts" / int("postId") / "comments") .out[Unit] - .implement(Handler.unit) + .implementHandler(Handler.unit) val boardPostsCommentsId = Endpoint( Method.GET / @@ -380,14 +380,14 @@ class EndpointBenchmark { ), ) .out[Unit] - .implement(Handler.unit) - val broadComments = Endpoint(Method.GET / "comments").out[Unit].implement(Handler.unit) + .implementHandler(Handler.unit) + val broadComments = Endpoint(Method.GET / "comments").out[Unit].implementHandler(Handler.unit) val broadCommentsId = - Endpoint(Method.GET / "comments" / int("commentId")).out[Unit].implement(Handler.unit) + Endpoint(Method.GET / "comments" / int("commentId")).out[Unit].implementHandler(Handler.unit) val broadUsersComments = Endpoint(Method.GET / "users" / int("userId") / "comments") .out[Unit] - .implement(Handler.unit) + .implementHandler(Handler.unit) val broadUsersCommentsId = Endpoint( Method.GET / @@ -396,7 +396,7 @@ class EndpointBenchmark { ), ) .out[Unit] - .implement(Handler.unit) + .implementHandler(Handler.unit) val boardUsersPostsCommentsReplies = Endpoint( Method.GET / @@ -406,7 +406,7 @@ class EndpointBenchmark { "replies", ) .out[Unit] - .implement(Handler.unit) + .implementHandler(Handler.unit) val boardUsersPostsCommentsRepliesId = Endpoint( Method.GET / @@ -415,7 +415,7 @@ class EndpointBenchmark { ) / "comments" / int("commentId") / "replies" / int("replyId"), ) .out[Unit] - .implement(Handler.unit) + .implementHandler(Handler.unit) val broadApiApp = Routes( diff --git a/zio-http-example/src/main/scala/example/EndpointExamples.scala b/zio-http-example/src/main/scala/example/EndpointExamples.scala index 490cc99bf0..c0e420a1b2 100644 --- a/zio-http-example/src/main/scala/example/EndpointExamples.scala +++ b/zio-http-example/src/main/scala/example/EndpointExamples.scala @@ -19,11 +19,7 @@ object EndpointExamples extends ZIOAppDefault { Endpoint(Method.GET / "users" / int("userId")).out[Int] @@ auth val getUserRoute = - getUser.implement { - Handler.fromFunction[Int] { id => - id - } - } + getUser.implement { id => ZIO.succeed(id) } val getUserPosts = Endpoint(Method.GET / "users" / int("userId") / "posts" / int("postId")) @@ -31,10 +27,8 @@ object EndpointExamples extends ZIOAppDefault { .out[List[String]] @@ auth val getUserPostsRoute = - getUserPosts.implement[Any] { - Handler.fromFunctionZIO[(Int, Int, String)] { case (id1: Int, id2: Int, query: String) => - ZIO.succeed(List(s"API2 RESULT parsed: users/$id1/posts/$id2?name=$query")) - } + getUserPosts.implement { case (id1: Int, id2: Int, query: String) => + ZIO.succeed(List(s"API2 RESULT parsed: users/$id1/posts/$id2?name=$query")) } val openAPI = OpenAPIGen.fromEndpoints(title = "Endpoint Example", version = "1.0", getUser, getUserPosts) diff --git a/zio-http-example/src/main/scala/example/ServerSentEventEndpoint.scala b/zio-http-example/src/main/scala/example/ServerSentEventEndpoint.scala index 05eb0dc773..c698f24317 100644 --- a/zio-http-example/src/main/scala/example/ServerSentEventEndpoint.scala +++ b/zio-http-example/src/main/scala/example/ServerSentEventEndpoint.scala @@ -21,7 +21,7 @@ object ServerSentEventEndpoint extends ZIOAppDefault { val sseEndpoint: Endpoint[Unit, Unit, ZNothing, ZStream[Any, Nothing, ServerSentEvent], None] = Endpoint(Method.GET / "sse").outStream[ServerSentEvent] - val sseRoute = sseEndpoint.implement(Handler.succeed(stream)) + val sseRoute = sseEndpoint.implementHandler(Handler.succeed(stream)) val routes: Routes[Any, Response] = sseRoute.toRoutes diff --git a/zio-http-example/src/main/scala/example/endpoint/BooksEndpointExample.scala b/zio-http-example/src/main/scala/example/endpoint/BooksEndpointExample.scala index 29ffab3f65..a907a36e00 100644 --- a/zio-http-example/src/main/scala/example/endpoint/BooksEndpointExample.scala +++ b/zio-http-example/src/main/scala/example/endpoint/BooksEndpointExample.scala @@ -44,7 +44,7 @@ object BooksEndpointExample extends ZIOAppDefault { "Endpoint to query books based on a search query", ) - val booksRoute = endpoint.implement(handler((query: String) => BookRepo.find(query))) + val booksRoute = endpoint.implementHandler(handler((query: String) => BookRepo.find(query))) val openAPI = OpenAPIGen.fromEndpoints(title = "Library API", version = "1.0", endpoint) val swaggerRoutes = SwaggerUI.routes("docs" / "openapi", openAPI) val routes = Routes(booksRoute) ++ swaggerRoutes diff --git a/zio-http-example/src/main/scala/example/endpoint/CliExamples.scala b/zio-http-example/src/main/scala/example/endpoint/CliExamples.scala index da86cc4295..d54713d240 100644 --- a/zio-http-example/src/main/scala/example/endpoint/CliExamples.scala +++ b/zio-http-example/src/main/scala/example/endpoint/CliExamples.scala @@ -81,21 +81,21 @@ object TestCliApp extends zio.cli.ZIOCliDefault with TestCliEndpoints { object TestCliServer extends zio.ZIOAppDefault with TestCliEndpoints { val getUserRoute = - getUser.implement { + getUser.implementHandler { Handler.fromFunctionZIO { case (id, _) => ZIO.succeed(User(id, "Juanito", Some("juanito@test.com"))).debug("Hello") } } val getUserPostsRoute = - getUserPosts.implement { + getUserPosts.implementHandler { Handler.fromFunction { case (userId, postId, name) => List(Post(userId, postId, name)) } } val createUserRoute = - createUser.implement { + createUser.implementHandler { Handler.fromFunction { user => user.name } diff --git a/zio-http-example/src/main/scala/example/endpoint/EndpointWithMultipleErrorsUsingEither.scala b/zio-http-example/src/main/scala/example/endpoint/EndpointWithMultipleErrorsUsingEither.scala index 4fe6e24ba5..063eb5e4b5 100644 --- a/zio-http-example/src/main/scala/example/endpoint/EndpointWithMultipleErrorsUsingEither.scala +++ b/zio-http-example/src/main/scala/example/endpoint/EndpointWithMultipleErrorsUsingEither.scala @@ -56,7 +56,7 @@ object EndpointWithMultipleErrorsUsingEither extends ZIOAppDefault { ZIO.fail(Left(AuthenticationError("User is not authenticated", 123))) } - val routes = endpoint.implement(getBookHandler).toRoutes @@ Middleware.debug + val routes = endpoint.implementHandler(getBookHandler).toRoutes @@ Middleware.debug def run = Server.serve(routes).provide(Server.default) } diff --git a/zio-http-example/src/main/scala/example/endpoint/EndpointWithMultipleUnifiedErrors.scala b/zio-http-example/src/main/scala/example/endpoint/EndpointWithMultipleUnifiedErrors.scala index a77305c81e..257ac314c8 100644 --- a/zio-http-example/src/main/scala/example/endpoint/EndpointWithMultipleUnifiedErrors.scala +++ b/zio-http-example/src/main/scala/example/endpoint/EndpointWithMultipleUnifiedErrors.scala @@ -62,7 +62,7 @@ object EndpointWithMultipleUnifiedErrors extends ZIOAppDefault { ZIO.fail(AuthenticationError("User is not authenticated", 123)) } - val routes = endpoint.implement(getBookHandler).toRoutes @@ Middleware.debug + val routes = endpoint.implementHandler(getBookHandler).toRoutes @@ Middleware.debug def run = Server.serve(routes).provide(Server.default) } diff --git a/zio-http-example/src/main/scala/example/endpoint/style/DeclarativeProgrammingExample.scala b/zio-http-example/src/main/scala/example/endpoint/style/DeclarativeProgrammingExample.scala index 29bc65f70e..eaf3748f0e 100644 --- a/zio-http-example/src/main/scala/example/endpoint/style/DeclarativeProgrammingExample.scala +++ b/zio-http-example/src/main/scala/example/endpoint/style/DeclarativeProgrammingExample.scala @@ -40,7 +40,7 @@ object DeclarativeProgrammingExample extends ZIOAppDefault { val getBookHandler: Handler[Any, NotFoundError, String, Book] = handler(BookRepo.find(_)) - val routes = endpoint.implement(getBookHandler).toRoutes @@ Middleware.debug + val routes = endpoint.implementHandler(getBookHandler).toRoutes @@ Middleware.debug def run = Server.serve(routes).provide(Server.default) } diff --git a/zio-http/jvm/src/test/scala/zio/http/StaticFileRoutesSpec.scala b/zio-http/jvm/src/test/scala/zio/http/StaticFileRoutesSpec.scala index f257c019ed..c0ae4010e1 100644 --- a/zio-http/jvm/src/test/scala/zio/http/StaticFileRoutesSpec.scala +++ b/zio-http/jvm/src/test/scala/zio/http/StaticFileRoutesSpec.scala @@ -16,7 +16,6 @@ package zio.http -import java.lang.System import java.nio.file.{Files, Path => NIOPath} import zio._ @@ -32,7 +31,7 @@ object StaticFileRoutesSpec extends HttpRunnableSpec { private def deleteTempFile(tempPath: NIOPath) = ZIO.attempt(Files.deleteIfExists(tempPath)).ignore private val createAndDeleteTempFile = createTempFile.flatMap(f => deleteTempFile(f).as(f)) - override def spec = suite("StaticFileServerSpec") { + override def spec = suite("StaticFileRoutesSpec") { serve.as(List(staticSpec)) } .provideSome[DynamicServer & Server & Client](Scope.default) @@ -78,7 +77,9 @@ object StaticFileRoutesSpec extends HttpRunnableSpec { assert(response.status)(equalTo(Status.Ok)) && assert(response.header(Header.ContentLength))(isSome(equalTo(Header.ContentLength(7L)))) && assert(body)(equalTo("foo\nbar")) && - assert(response.header(Header.ContentType))(isSome(equalTo(Header.ContentType(MediaType.text.plain)))) + assert(response.header(Header.ContentType))( + isSome(equalTo(Header.ContentType(MediaType.text.plain, charset = Some(Charsets.Utf8)))), + ) } }, test("serve a non-existing resource") { diff --git a/zio-http/jvm/src/test/scala/zio/http/endpoint/AuthSpec.scala b/zio-http/jvm/src/test/scala/zio/http/endpoint/AuthSpec.scala index f697d5162c..739f211682 100644 --- a/zio-http/jvm/src/test/scala/zio/http/endpoint/AuthSpec.scala +++ b/zio-http/jvm/src/test/scala/zio/http/endpoint/AuthSpec.scala @@ -26,7 +26,9 @@ object AuthSpec extends ZIOSpecDefault { test("Auth with context") { val endpoint = Endpoint(Method.GET / "test").out[String](MediaType.text.`plain`) val routes = - Routes(endpoint.implement(handler((_: Unit) => ZIO.serviceWith[AuthContext](_.value)))) @@ basicAuthContext + Routes( + endpoint.implementHandler(handler((_: Unit) => ZIO.serviceWith[AuthContext](_.value))), + ) @@ basicAuthContext val response = routes.run( Request( method = Method.GET, diff --git a/zio-http/jvm/src/test/scala/zio/http/endpoint/BadRequestSpec.scala b/zio-http/jvm/src/test/scala/zio/http/endpoint/BadRequestSpec.scala index 009c6a56e3..aa0cc3999b 100644 --- a/zio-http/jvm/src/test/scala/zio/http/endpoint/BadRequestSpec.scala +++ b/zio-http/jvm/src/test/scala/zio/http/endpoint/BadRequestSpec.scala @@ -17,7 +17,7 @@ object BadRequestSpec extends ZIOSpecDefault { val endpoint = Endpoint(Method.GET / "test") .query(QueryCodec.queryInt("age")) .out[Unit] - val route = endpoint.implement(handler((_: Int) => ())) + val route = endpoint.implementHandler(handler((_: Int) => ())) val request = Request(method = Method.GET, url = url"/test?age=1&age=2").addHeader(Header.Accept(MediaType.text.`html`)) val expectedBody = @@ -38,7 +38,7 @@ object BadRequestSpec extends ZIOSpecDefault { val endpoint = Endpoint(Method.GET / "test") .query(QueryCodec.queryInt("age")) .out[Unit] - val route = endpoint.implement(handler((_: Int) => ())) + val route = endpoint.implementHandler(handler((_: Int) => ())) val request = Request(method = Method.GET, url = url"/test?age=1&age=2") .addHeader(Header.Accept(MediaType.application.json)) @@ -53,7 +53,7 @@ object BadRequestSpec extends ZIOSpecDefault { val endpoint = Endpoint(Method.GET / "test") .query(QueryCodec.queryInt("age")) .out[Unit] - val route = endpoint.implement(handler((_: Int) => ())) + val route = endpoint.implementHandler(handler((_: Int) => ())) val request = Request(method = Method.GET, url = url"/test?age=1&age=2") .addHeader(Header.Accept(MediaType.application.`atf`)) @@ -69,7 +69,7 @@ object BadRequestSpec extends ZIOSpecDefault { .query(QueryCodec.queryInt("age")) .out[Unit] .emptyErrorResponse - val route = endpoint.implement(handler((_: Int) => ())) + val route = endpoint.implementHandler(handler((_: Int) => ())) val request = Request(method = Method.GET, url = url"/test?age=1&age=2") .addHeader(Header.Accept(MediaType.application.`atf`)) @@ -83,7 +83,7 @@ object BadRequestSpec extends ZIOSpecDefault { val endpoint = Endpoint(Method.GET / "test") .query(QueryCodec.queryInt("age")) .out[Unit] - val route = endpoint.implement(handler((_: Int) => ())) + val route = endpoint.implementHandler(handler((_: Int) => ())) val request = Request(method = Method.GET, url = url"/test?age=1&age=2") .addHeader(Header.Accept(MediaType.application.json)) @@ -99,7 +99,7 @@ object BadRequestSpec extends ZIOSpecDefault { .query(QueryCodec.queryInt("age")) .out[Unit] .outCodecError(default) - val route = endpoint.implement(handler((_: Int) => ())) + val route = endpoint.implementHandler(handler((_: Int) => ())) val request = Request(method = Method.GET, url = url"/test?age=1&age=2") .addHeader(Header.Accept(MediaType.application.json)) diff --git a/zio-http/jvm/src/test/scala/zio/http/endpoint/CustomErrorSpec.scala b/zio-http/jvm/src/test/scala/zio/http/endpoint/CustomErrorSpec.scala index 0b59d3a610..b42382f1af 100644 --- a/zio-http/jvm/src/test/scala/zio/http/endpoint/CustomErrorSpec.scala +++ b/zio-http/jvm/src/test/scala/zio/http/endpoint/CustomErrorSpec.scala @@ -39,7 +39,7 @@ object CustomErrorSpec extends ZIOHttpSpec { Endpoint(GET / "users" / int("userId")) .out[String] .outError[String](Status.Custom(customCode)) - .implement { + .implementHandler { Handler.fromFunctionZIO { userId => ZIO.fail(s"path(users, $userId)") } @@ -66,7 +66,7 @@ object CustomErrorSpec extends ZIOHttpSpec { HttpCodec.error[TestError.UnexpectedError](Status.InternalServerError), HttpCodec.error[TestError.InvalidUser](Status.NotFound), ) - .implement { + .implementHandler { Handler.fromFunctionZIO { userId => if (userId == myUserId) ZIO.fail(TestError.InvalidUser(userId)) else ZIO.fail(TestError.UnexpectedError("something went wrong")) @@ -100,7 +100,7 @@ object CustomErrorSpec extends ZIOHttpSpec { .in[User](Doc.p("User schema with id")) .out[String] .emptyErrorResponse - .implement { + .implementHandler { Handler.fromFunctionZIO { _ => ZIO.succeed("User ID is greater than 0") } diff --git a/zio-http/jvm/src/test/scala/zio/http/endpoint/MultipartSpec.scala b/zio-http/jvm/src/test/scala/zio/http/endpoint/MultipartSpec.scala index 01b559012b..f3ad67df34 100644 --- a/zio-http/jvm/src/test/scala/zio/http/endpoint/MultipartSpec.scala +++ b/zio-http/jvm/src/test/scala/zio/http/endpoint/MultipartSpec.scala @@ -55,7 +55,7 @@ object MultipartSpec extends ZIOHttpSpec { HttpCodec.content[Int]("height", MediaType.text.`plain`) ++ HttpCodec.content[ImageMetadata]("metadata"), ) - .implement { + .implementHandler { Handler.succeed( ( ZStream.fromChunk(bytes), @@ -111,7 +111,7 @@ object MultipartSpec extends ZIOHttpSpec { HttpCodec.content[Int](MediaType.text.`plain`) ++ HttpCodec.content[ImageMetadata], ) - .implement { + .implementHandler { Handler.succeed( ( ZStream.fromChunk(bytes), @@ -158,7 +158,7 @@ object MultipartSpec extends ZIOHttpSpec { .in[String]("title") .in[ImageMetadata]("metadata", Doc.p("Image metadata with description and creation date and time")) .out[(Long, String, ImageMetadata)] - .implement { + .implementHandler { Handler.fromFunctionZIO { case (stream, title, metadata) => stream.runCount.map(count => (count, title, metadata)) } @@ -238,7 +238,7 @@ object MultipartSpec extends ZIOHttpSpec { } } val route = - endpoint.implement(Handler.identity[Any]) + endpoint.implementHandler(Handler.identity[Any]) val form = Form( @@ -294,9 +294,9 @@ object MultipartSpec extends ZIOHttpSpec { ) for { result <- (endpoint - .implement(handler { (id: Int) => - (Book("John's Book", List("John Doe")), ZStream.from(Chunk.fromArray("the book file".getBytes))) - }) + .implementPurely(_ => + (Book("John's Book", List("John Doe")), ZStream.from(Chunk.fromArray("the book file".getBytes))), + ) .toRoutes @@ Middleware.debug).run(path = Path.root / "books" / "123") } yield assertTrue( result.status == Status.Ok, diff --git a/zio-http/jvm/src/test/scala/zio/http/endpoint/NotFoundSpec.scala b/zio-http/jvm/src/test/scala/zio/http/endpoint/NotFoundSpec.scala index 1594d5fb6b..79ed17e155 100644 --- a/zio-http/jvm/src/test/scala/zio/http/endpoint/NotFoundSpec.scala +++ b/zio-http/jvm/src/test/scala/zio/http/endpoint/NotFoundSpec.scala @@ -43,7 +43,7 @@ object NotFoundSpec extends ZIOHttpSpec { Routes( Endpoint(GET / "users" / int("userId")) .out[String] - .implement { + .implementHandler { Handler.fromFunction { userId => s"path(users, $userId)" } @@ -51,7 +51,7 @@ object NotFoundSpec extends ZIOHttpSpec { Endpoint(GET / "users" / int("userId") / "posts" / int("postId")) .query(query("name")) .out[String] - .implement { + .implementHandler { Handler.fromFunction { case (userId, postId, name) => s"path(users, $userId, posts, $postId) query(name=$name)" } @@ -68,7 +68,7 @@ object NotFoundSpec extends ZIOHttpSpec { Routes( Endpoint(GET / "users" / int("userId")) .out[String] - .implement { + .implementHandler { Handler.fromFunction { userId => s"path(users, $userId)" } @@ -76,7 +76,7 @@ object NotFoundSpec extends ZIOHttpSpec { Endpoint(GET / "users" / int("userId") / "posts" / int("postId")) .query(query("name")) .out[String] - .implement { + .implementHandler { Handler.fromFunction { case (userId, postId, name) => s"path(users, $userId, posts, $postId) query(name=$name)" } diff --git a/zio-http/jvm/src/test/scala/zio/http/endpoint/QueryParameterSpec.scala b/zio-http/jvm/src/test/scala/zio/http/endpoint/QueryParameterSpec.scala index 884fbb99bf..768de94dff 100644 --- a/zio-http/jvm/src/test/scala/zio/http/endpoint/QueryParameterSpec.scala +++ b/zio-http/jvm/src/test/scala/zio/http/endpoint/QueryParameterSpec.scala @@ -34,7 +34,7 @@ object QueryParameterSpec extends ZIOHttpSpec { Routes( Endpoint(GET / "users" / int("userId")) .out[String] - .implement { + .implementHandler { Handler.fromFunction { userId => s"path(users, $userId)" } @@ -42,7 +42,7 @@ object QueryParameterSpec extends ZIOHttpSpec { Endpoint(GET / "users" / int("userId") / "posts" / int("postId")) .query(query("name")) .out[String] - .implement { + .implementHandler { Handler.fromFunction { case (userId, postId, name) => s"path(users, $userId, posts, $postId) query(name=$name)" } @@ -63,7 +63,7 @@ object QueryParameterSpec extends ZIOHttpSpec { Endpoint(GET / "users" / int("userId")) .query(query("details").optional) .out[String] - .implement { + .implementHandler { Handler.fromFunction { case (userId, details) => s"path(users, $userId, $details)" } @@ -83,7 +83,7 @@ object QueryParameterSpec extends ZIOHttpSpec { .query(query("key").optional) .query(query("value").optional) .out[String] - .implement { + .implementHandler { Handler.fromFunction { case (userId, key, value) => s"path(users, $userId, $key, $value)" } @@ -103,7 +103,7 @@ object QueryParameterSpec extends ZIOHttpSpec { Endpoint(GET / "users" / int("userId")) .query(queryAll("key")) .out[String] - .implement { + .implementHandler { Handler.fromFunction { case (userId, keys) => s"""path(users, $userId, ${keys.mkString(", ")})""" } @@ -132,7 +132,7 @@ object QueryParameterSpec extends ZIOHttpSpec { Endpoint(GET / "users" / int("userId")) .query(queryAll("key").optional) .out[String] - .implement { + .implementHandler { Handler.fromFunction { case (userId, keys) => s"""path(users, $userId, $keys)""" } @@ -162,7 +162,7 @@ object QueryParameterSpec extends ZIOHttpSpec { Endpoint(GET / "users" / int("userId")) .query(queryAll("key") & queryAll("value")) .out[String] - .implement { + .implementHandler { Handler.fromFunction { case (userId, keys, values) => s"""path(users, $userId, $keys, $values)""" } @@ -187,7 +187,7 @@ object QueryParameterSpec extends ZIOHttpSpec { Endpoint(GET / "users" / int("userId")) .query(queryAll("multi") & query("single")) .out[String] - .implement { + .implementHandler { Handler.fromFunction { case (userId, multi, single) => s"""path(users, $userId, $multi, $single)""" } @@ -208,7 +208,7 @@ object QueryParameterSpec extends ZIOHttpSpec { Endpoint(GET / "users" / int("userId")) .query(queryAll("left") | queryAllBool("right")) .out[String] - .implement { + .implementHandler { Handler.fromFunction { case (userId, eitherOfParameters) => s"path(users, $userId, $eitherOfParameters)" } @@ -238,7 +238,7 @@ object QueryParameterSpec extends ZIOHttpSpec { Endpoint(GET / "users" / int("userId")) .query(queryAll("left") | queryAll("right")) .out[String] - .implement { + .implementHandler { Handler.fromFunction { case (userId, queryParams) => s"path(users, $userId, $queryParams)" } @@ -267,7 +267,7 @@ object QueryParameterSpec extends ZIOHttpSpec { Endpoint(GET / "users" / int("userId")) .query(queryAll("left") | query("right")) .out[String] - .implement { + .implementHandler { Handler.fromFunction { case (userId, queryParams) => s"path(users, $userId, $queryParams)" } @@ -295,7 +295,7 @@ object QueryParameterSpec extends ZIOHttpSpec { Endpoint(GET / "users") .query(queryAllInt("ints")) .out[String] - .implement { + .implementHandler { Handler.fromFunction { case queryParams => s"path(users, $queryParams)" } @@ -313,7 +313,7 @@ object QueryParameterSpec extends ZIOHttpSpec { Endpoint(GET / "users") .query(queryAllInt("ints")) .out[String] - .implement { + .implementHandler { Handler.fromFunction { case queryParams => s"path(users, $queryParams)" } @@ -330,7 +330,7 @@ object QueryParameterSpec extends ZIOHttpSpec { Endpoint(GET / "users") .query(queryInt("ints")) .out[String] - .implement { + .implementHandler { Handler.fromFunction { case queryParams => s"path(users, $queryParams)" } diff --git a/zio-http/jvm/src/test/scala/zio/http/endpoint/RequestSpec.scala b/zio-http/jvm/src/test/scala/zio/http/endpoint/RequestSpec.scala index 12af7bba14..1973fcab9d 100644 --- a/zio-http/jvm/src/test/scala/zio/http/endpoint/RequestSpec.scala +++ b/zio-http/jvm/src/test/scala/zio/http/endpoint/RequestSpec.scala @@ -44,7 +44,7 @@ object RequestSpec extends ZIOHttpSpec { Endpoint(GET / "users" / int("userId")) .header(HeaderCodec.name[java.util.UUID]("X-Correlation-ID")) .out[String] - .implement { + .implementHandler { Handler.fromFunction { case (userId, correlationId) => s"path(users, $userId) header(correlationId=$correlationId)" } @@ -52,7 +52,7 @@ object RequestSpec extends ZIOHttpSpec { Endpoint(GET / "users" / int("userId") / "posts" / int("postId")) .header(HeaderCodec.name[java.util.UUID]("X-Correlation-ID")) .out[String] - .implement { + .implementHandler { Handler.fromFunction { case (userId, postId, correlationId) => s"path(users, $userId, posts, $postId) header(correlationId=$correlationId)" } @@ -78,7 +78,7 @@ object RequestSpec extends ZIOHttpSpec { .query(query("id")) .out[Int](MediaType.text.`plain`) val routes = - endpoint.implement { + endpoint.implementHandler { Handler.succeed(id) } @@ -100,7 +100,7 @@ object RequestSpec extends ZIOHttpSpec { .query(query("id")) .out[Int](MediaType.text.`plain`) val routes = - endpoint.implement { + endpoint.implementHandler { Handler.succeed(id) } @@ -122,7 +122,7 @@ object RequestSpec extends ZIOHttpSpec { .query(query("id")) .out[Int](Status.NotFound) val routes = - endpoint.implement { + endpoint.implementHandler { Handler.succeed(id) } @@ -140,7 +140,7 @@ object RequestSpec extends ZIOHttpSpec { Endpoint(GET / "posts") .query(queryInt("id")) .out[Int] - val routes = endpoint.implement { Handler.succeed(id) } + val routes = endpoint.implementHandler { Handler.succeed(id) } for { response <- routes.toRoutes.runZIO( Request.get(url"/posts?id=$notAnId").addHeader(Header.Accept(MediaType.application.`json`)), @@ -159,7 +159,7 @@ object RequestSpec extends ZIOHttpSpec { .header(HeaderCodec.name[java.util.UUID]("X-Correlation-ID")) .out[Int] val routes = - endpoint.implement { + endpoint.implementHandler { Handler.succeed(id) } @@ -178,7 +178,7 @@ object RequestSpec extends ZIOHttpSpec { .header(HeaderCodec.name[java.util.UUID]("X-Correlation-ID")) .out[Int] val routes = - endpoint.implement { + endpoint.implementHandler { Handler.succeed(id) } @@ -195,7 +195,7 @@ object RequestSpec extends ZIOHttpSpec { Routes( Endpoint(GET / "users" / int("userId")) .out[String] - .implement { + .implementHandler { Handler.fromFunction { userId => s"path(users, $userId)" } @@ -204,7 +204,7 @@ object RequestSpec extends ZIOHttpSpec { .query(query("name")) .query(query("age")) .out[String] - .implement { + .implementHandler { Handler.fromFunction { case (userId, postId, name, age) => s"path(users, $userId, posts, $postId) query(name=$name, age=$age)" } @@ -225,7 +225,7 @@ object RequestSpec extends ZIOHttpSpec { Endpoint(GET / "users") .query(queryInt("userId") | query("userId")) .out[String] - .implement { + .implementHandler { Handler.fromFunction { userId => val value = userId.fold(_.toString, identity) s"path(users) query(userId=$value)" @@ -240,11 +240,11 @@ object RequestSpec extends ZIOHttpSpec { test("broad api") { check(Gen.int, Gen.int, Gen.int, Gen.int) { (userId, postId, commentId, replyId) => val broadUsers = - Endpoint(GET / "users").out[String](Doc.p("Created user id")).implement { + Endpoint(GET / "users").out[String](Doc.p("Created user id")).implementHandler { Handler.succeed("path(users)") } val broadUsersId = - Endpoint(GET / "users" / int("userId")).out[String].implement { + Endpoint(GET / "users" / int("userId")).out[String].implementHandler { Handler.fromFunction { userId => s"path(users, $userId)" } @@ -252,7 +252,7 @@ object RequestSpec extends ZIOHttpSpec { val boardUsersPosts = Endpoint(GET / "users" / int("userId") / "posts") .out[String] - .implement { + .implementHandler { Handler.fromFunction { userId => s"path(users, $userId, posts)" } @@ -260,7 +260,7 @@ object RequestSpec extends ZIOHttpSpec { val boardUsersPostsId = Endpoint(GET / "users" / int("userId") / "posts" / int("postId")) .out[String] - .implement { + .implementHandler { Handler.fromFunction { case (userId, postId) => s"path(users, $userId, posts, $postId)" } @@ -271,7 +271,7 @@ object RequestSpec extends ZIOHttpSpec { "users" / int("userId") / "posts" / int("postId") / "comments", ) .out[String] - .implement { + .implementHandler { Handler.fromFunction { case (userId, postId) => s"path(users, $userId, posts, $postId, comments)" } @@ -282,15 +282,15 @@ object RequestSpec extends ZIOHttpSpec { "users" / int("userId") / "posts" / int("postId") / "comments" / int("commentId"), ) .out[String] - .implement { + .implementHandler { Handler.fromFunction { case (userId, postId, commentId) => s"path(users, $userId, posts, $postId, comments, $commentId)" } } val broadPosts = - Endpoint(GET / "posts").out[String].implement(Handler.succeed("path(posts)")) + Endpoint(GET / "posts").out[String].implementHandler(Handler.succeed("path(posts)")) val broadPostsId = - Endpoint(GET / "posts" / int("postId")).out[String].implement { + Endpoint(GET / "posts" / int("postId")).out[String].implementHandler { Handler.fromFunction { postId => s"path(posts, $postId)" } @@ -298,7 +298,7 @@ object RequestSpec extends ZIOHttpSpec { val boardPostsComments = Endpoint(GET / "posts" / int("postId") / "comments") .out[String] - .implement { + .implementHandler { Handler.fromFunction { postId => s"path(posts, $postId, comments)" } @@ -306,15 +306,15 @@ object RequestSpec extends ZIOHttpSpec { val boardPostsCommentsId = Endpoint(GET / "posts" / int("postId") / "comments" / int("commentId")) .out[String] - .implement { + .implementHandler { Handler.fromFunction { case (postId, commentId) => s"path(posts, $postId, comments, $commentId)" } } val broadComments = - Endpoint(GET / "comments").out[String].implement(Handler.succeed("path(comments)")) + Endpoint(GET / "comments").out[String].implementHandler(Handler.succeed("path(comments)")) val broadCommentsId = - Endpoint(GET / "comments" / int("commentId")).out[String].implement { + Endpoint(GET / "comments" / int("commentId")).out[String].implementHandler { Handler.fromFunction { commentId => s"path(comments, $commentId)" } @@ -322,7 +322,7 @@ object RequestSpec extends ZIOHttpSpec { val broadUsersComments = Endpoint(GET / "users" / int("userId") / "comments") .out[String] - .implement { + .implementHandler { Handler.fromFunction { userId => s"path(users, $userId, comments)" } @@ -330,7 +330,7 @@ object RequestSpec extends ZIOHttpSpec { val broadUsersCommentsId = Endpoint(GET / "users" / int("userId") / "comments" / int("commentId")) .out[String] - .implement { + .implementHandler { Handler.fromFunction { case (userId, commentId) => s"path(users, $userId, comments, $commentId)" } @@ -341,7 +341,7 @@ object RequestSpec extends ZIOHttpSpec { "users" / int("userId") / "posts" / int("postId") / "comments" / int("commentId") / "replies", ) .out[String] - .implement { + .implementHandler { Handler.fromFunction { case (userId, postId, commentId) => s"path(users, $userId, posts, $postId, comments, $commentId, replies)" } @@ -353,7 +353,7 @@ object RequestSpec extends ZIOHttpSpec { "replies" / int("replyId"), ) .out[String] - .implement { + .implementHandler { Handler.fromFunction { case (userId, postId, commentId, replyId) => s"path(users, $userId, posts, $postId, comments, $commentId, replies, $replyId)" } @@ -411,7 +411,7 @@ object RequestSpec extends ZIOHttpSpec { check(Gen.alphaNumericString, Gen.alphaNumericString) { (queryValue, headerValue) => val headerOrQuery = HeaderCodec.name[String]("X-Header") | QueryCodec.query("header") val endpoint = Endpoint(GET / "test").out[String].inCodec(headerOrQuery) - val routes = endpoint.implement(Handler.identity).toRoutes + val routes = endpoint.implementHandler(Handler.identity).toRoutes val request = Request.get( URL .decode(s"/test?header=$queryValue") @@ -446,7 +446,7 @@ object RequestSpec extends ZIOHttpSpec { val headerOrQuery = HeaderCodec.name[String]("X-Header") | StatusCodec.status(Status.Created) val endpoint = Endpoint(GET / "test").query(QueryCodec.queryBool("Created")).outCodec(headerOrQuery) val routes = - endpoint.implement { + endpoint.implementHandler { Handler.fromFunction { created => if (created) Right(()) else Left("not created") } @@ -485,7 +485,7 @@ object RequestSpec extends ZIOHttpSpec { .in[NewPost](Doc.p("New post")) .out[PostCreated](Status.Created, MediaType.application.`json`) val routes = - endpoint.implement(Handler.succeed(PostCreated(postId))).toRoutes + endpoint.implementHandler(Handler.succeed(PostCreated(postId))).toRoutes val request = Request .post( @@ -513,7 +513,7 @@ object RequestSpec extends ZIOHttpSpec { .in[NewPost] .out[Int] val routes = - endpoint.implement(Handler.succeed(postId)).toRoutes + endpoint.implementHandler(Handler.succeed(postId)).toRoutes for { response <- routes.runZIO( @@ -532,7 +532,7 @@ object RequestSpec extends ZIOHttpSpec { check(Gen.chunkOfBounded(1, 1024)(Gen.byte)) { bytes => val route = Endpoint(GET / "test-byte-stream") .outStream[Byte](Doc.p("Test data")) - .implement(Handler.succeed(ZStream.fromChunk(bytes).rechunk(16))) + .implementHandler(Handler.succeed(ZStream.fromChunk(bytes).rechunk(16))) .toRoutes for { @@ -556,7 +556,7 @@ object RequestSpec extends ZIOHttpSpec { check(Gen.chunkOfBounded(1, 1024)(Gen.byte)) { bytes => val route = Endpoint(GET / "test-byte-stream") .outStream[Byte](Status.Ok, MediaType.image.png) - .implement(Handler.succeed(ZStream.fromChunk(bytes).rechunk(16))) + .implementHandler(Handler.succeed(ZStream.fromChunk(bytes).rechunk(16))) .toRoutes for { @@ -581,7 +581,7 @@ object RequestSpec extends ZIOHttpSpec { val route = Endpoint(POST / "test-byte-stream") .inStream[Byte] .out[Long] - .implement { + .implementHandler { Handler.fromFunctionZIO { byteStream => byteStream.runCount } diff --git a/zio-http/jvm/src/test/scala/zio/http/endpoint/RoundtripSpec.scala b/zio-http/jvm/src/test/scala/zio/http/endpoint/RoundtripSpec.scala index d22d583cc1..e8429f6a7f 100644 --- a/zio-http/jvm/src/test/scala/zio/http/endpoint/RoundtripSpec.scala +++ b/zio-http/jvm/src/test/scala/zio/http/endpoint/RoundtripSpec.scala @@ -149,7 +149,7 @@ object RoundtripSpec extends ZIOHttpSpec { Endpoint(GET / "users" / int("userId") / "posts" / int("postId")).out[Post] val usersPostHandler = - usersPostAPI.implement { + usersPostAPI.implementHandler { Handler.fromFunction { case (userId, postId) => Post(postId, "title", "body", userId) } @@ -169,7 +169,7 @@ object RoundtripSpec extends ZIOHttpSpec { .header(HeaderCodec.accept) val usersPostHandler = - usersPostAPI.implement { + usersPostAPI.implementHandler { Handler.fromFunction { case (userId, postId, _) => Post(postId, "title", "body", userId) } @@ -190,7 +190,7 @@ object RoundtripSpec extends ZIOHttpSpec { .header(HeaderCodec.accept) val usersPostHandler = - usersPostAPI.implement { + usersPostAPI.implementHandler { Handler.fromFunction { case (userId, postId, _) => Post(postId, "title", "body", userId) } @@ -212,7 +212,7 @@ object RoundtripSpec extends ZIOHttpSpec { .out[Post] val handler = - api.implement { + api.implementHandler { Handler.fromFunction { case (id, userId, name, details) => Post(id, name.getOrElse("-"), details.getOrElse("-"), userId) } @@ -245,7 +245,7 @@ object RoundtripSpec extends ZIOHttpSpec { .out[String] ?? Doc.p("doc") @nowarn("msg=dead code") - val handler = api.implement { + val handler = api.implementHandler { Handler.fromFunction { case (accountId, name, instanceName, args, env) => throw new RuntimeException("I can't code") s"$accountId, $name, $instanceName, $args, $env" @@ -268,7 +268,7 @@ object RoundtripSpec extends ZIOHttpSpec { .in[Post] .out[String] - val route = api.implement { + val route = api.implementHandler { Handler.fromFunction { case (userId, post) => s"userId: $userId, post: $post" } @@ -283,7 +283,7 @@ object RoundtripSpec extends ZIOHttpSpec { }, test("byte stream input") { val api = Endpoint(PUT / "upload").inStream[Byte].out[Long] - val route = api.implement { + val route = api.implementHandler { Handler.fromFunctionZIO { bytes => bytes.runCount } @@ -300,7 +300,7 @@ object RoundtripSpec extends ZIOHttpSpec { }, test("byte stream output") { val api = Endpoint(GET / "download").query(QueryCodec.queryInt("count")).outStream[Byte] - val route = api.implement { + val route = api.implementHandler { Handler.fromFunctionZIO { count => Random.nextBytes(count).map(chunk => ZStream.fromChunk(chunk).rechunk(1024)) } @@ -320,7 +320,7 @@ object RoundtripSpec extends ZIOHttpSpec { .in[Post]("post") .out[String] - val route = api.implement { + val route = api.implementHandler { Handler.fromFunction { case (name, value, post) => s"name: $name, value: $value, post: $post" } @@ -337,7 +337,7 @@ object RoundtripSpec extends ZIOHttpSpec { val api = Endpoint(POST / "test") .outError[String](Status.Custom(999)) - val route = api.implement(Handler.fail("42")) + val route = api.implementHandler(Handler.fail("42")) testEndpointError( api, @@ -358,7 +358,7 @@ object RoundtripSpec extends ZIOHttpSpec { Endpoint(GET / "users" / int("userId")).out[Int] @@ alwaysFailingMiddleware val endpointRoute = - endpoint.implement(Handler.identity) + endpoint.implementHandler(Handler.identity) val routes = endpointRoute.toRoutes @@ -397,7 +397,7 @@ object RoundtripSpec extends ZIOHttpSpec { Endpoint(GET / "users" / int("userId")).out[Int] @@ alwaysFailingMiddlewareWithAnotherSignature val endpointRoute = - endpoint.implement(Handler.identity) + endpoint.implementHandler(Handler.identity) val routes = endpointRoute.toRoutes @@ -439,7 +439,7 @@ object RoundtripSpec extends ZIOHttpSpec { Endpoint(GET / "users" / int("userId")).out[Int].outError[String](Status.Custom(999)) val endpointRoute = - endpoint.implement { + endpoint.implementHandler { Handler.fromFunctionZIO { id => ZIO.fail(id) } @@ -482,7 +482,7 @@ object RoundtripSpec extends ZIOHttpSpec { .inStream[Byte]("file") .out[String] - val route = api.implement { + val route = api.implementHandler { Handler.fromFunctionZIO { case (name, value, file) => file.runCount.map { n => s"name: $name, value: $value, count: $n" @@ -506,7 +506,7 @@ object RoundtripSpec extends ZIOHttpSpec { .inStream[Byte]("file") .out[String] - val route = api.implement { + val route = api.implementHandler { Handler.fromFunctionZIO { case (name, metadata, file) => file.runCount.map { n => s"name: $name, metadata: $metadata, count: $n" diff --git a/zio-http/jvm/src/test/scala/zio/http/endpoint/openapi/SwaggerUISpec.scala b/zio-http/jvm/src/test/scala/zio/http/endpoint/openapi/SwaggerUISpec.scala index a7bfbb7f61..77f0edc009 100644 --- a/zio-http/jvm/src/test/scala/zio/http/endpoint/openapi/SwaggerUISpec.scala +++ b/zio-http/jvm/src/test/scala/zio/http/endpoint/openapi/SwaggerUISpec.scala @@ -15,7 +15,7 @@ object SwaggerUISpec extends ZIOSpecDefault { test("should return the swagger ui page") { val getUser = Endpoint(Method.GET / "users" / int("userId")).out[Int] - val getUserRoute = getUser.implement { Handler.fromFunction[Int] { id => id } } + val getUserRoute = getUser.implementHandler { Handler.fromFunction[Int] { id => id } } val getUserPosts = Endpoint(Method.GET / "users" / int("userId") / "posts" / int("postId")) @@ -23,7 +23,7 @@ object SwaggerUISpec extends ZIOSpecDefault { .out[List[String]] val getUserPostsRoute = - getUserPosts.implement[Any] { + getUserPosts.implementHandler[Any] { Handler.fromFunctionZIO[(Int, Int, String)] { case (id1: Int, id2: Int, query: String) => ZIO.succeed(List(s"API2 RESULT parsed: users/$id1/posts/$id2?name=$query")) } diff --git a/zio-http/shared/src/main/scala/zio/http/endpoint/Endpoint.scala b/zio-http/shared/src/main/scala/zio/http/endpoint/Endpoint.scala index 475d7e2840..8905a974c6 100644 --- a/zio-http/shared/src/main/scala/zio/http/endpoint/Endpoint.scala +++ b/zio-http/shared/src/main/scala/zio/http/endpoint/Endpoint.scala @@ -158,7 +158,32 @@ final case class Endpoint[PathInput, Input, Err, Output, Middleware <: EndpointM ): Endpoint[PathInput, combiner.Out, Err, Output, Middleware] = copy(input = self.input ++ codec) - def implement[Env](original: Handler[Env, Err, Input, Output])(implicit trace: Trace): Route[Env, Nothing] = { + def implement[Env](f: Input => ZIO[Env, Err, Output])(implicit + trace: Trace, + ): Route[Env, Nothing] = + implementHandler(Handler.fromFunctionZIO(f)) + + def implementEither(f: Input => Either[Err, Output])(implicit + trace: Trace, + ): Route[Any, Nothing] = + implementHandler[Any](Handler.fromFunctionHandler[Input](in => Handler.fromEither(f(in)))) + + def implementPurely(f: Input => Output)(implicit + trace: Trace, + ): Route[Any, Nothing] = + implementHandler[Any](Handler.fromFunctionHandler[Input](in => Handler.succeed(f(in)))) + + def implementAs(output: Output)(implicit + trace: Trace, + ): Route[Any, Nothing] = + implementHandler[Any](Handler.succeed(output)) + + def implementAsError(err: Err)(implicit + trace: Trace, + ): Route[Any, Nothing] = + implementHandler[Any](Handler.fail(err)) + + def implementHandler[Env](original: Handler[Env, Err, Input, Output])(implicit trace: Trace): Route[Env, Nothing] = { import HttpCodecError.asHttpCodecError val handlers = self.alternatives.map { case (endpoint, condition) =>