@@ -402,6 +402,30 @@ val endpoint3: Endpoint[Unit, Unit, ZNothing, Either[(Article, Header.Date), (Bo
402402 Endpoint (RoutePattern .GET / " resources" )
403403 .outCodec(articleCodec | bookCodec)
404404```
405+
406+ To model streaming responses, such as server-sent events or large file downloads, we can use ZIO Streams as the output type of the endpoint:
407+
408+ ``` scala mdoc:compile-only
409+ import zio .stream ._
410+
411+ val sseEndpoint : Endpoint [Unit , Unit , ZNothing , ZStream [Any , Nothing , ServerSentEvent [String ]], AuthType .None ] =
412+ Endpoint (Method .GET / " server-time" )
413+ .outStream[ServerSentEvent [String ]](MediaType .text.`event-stream`)
414+ ```
415+
416+ This endpoint describes a server-sent events stream that sends the current server time to the client.
417+
418+ <details >
419+ <summary ><b >Full Implementation Showcase</b ></summary >
420+
421+ ``` scala mdoc:passthrough
422+ import utils ._
423+
424+ printSource(" zio-http-example/src/main/scala/example/endpoint/SSEServerTimeExample.scala" )
425+ ```
426+
427+ </details >
428+
405429## Describing Failures
406430
407431For failure outputs, we can describe the output properties using the ` Endpoint#outError* ` methods. Let's see an example:
@@ -512,6 +536,139 @@ val endpoint: Endpoint[Int, (Int, Header.Authorization), BookNotFound | Authenti
512536 .orOutError[AuthenticationError ](Status .Unauthorized )
513537```
514538
539+ ## Describing Authentication Types
540+
541+ Endpoints can specify authentication requirements using the ` Endpoint#auth ` method. ZIO HTTP supports several built-in authentication types and allows for custom authentication schemes. It can be ` AuthType.None ` , ` AuthType.Basic ` , ` AuthType.Bearer ` , ` AuthType.Digest ` , ` AuthType.Custom ` , or unions of these types.
542+
543+ For example, Basic authentication can be specified using ` AuthType.Basic ` :
544+
545+ ``` scala mdoc:invisible
546+ import zio .schema .{DeriveSchema , Schema }
547+
548+ case class Book (title : String , authors : List [String ])
549+ object Book {
550+ implicit val schema = DeriveSchema .gen[Book ]
551+ }
552+ ```
553+
554+ ``` scala mdoc:compile-only
555+ import zio .http ._
556+ import zio .http .endpoint ._
557+
558+ val endpoint = Endpoint (Method .GET / " me" / " favorites" / " books" )
559+ .out[List [Book ]]
560+ .auth(AuthType .Basic )
561+ ```
562+
563+ This describes an endpoint that requires the client to provide HTTP Basic authentication credentials in the ` Authorization ` header.
564+
565+ ### Multiple Authentication Types
566+
567+ An endpoint can accept a union of multiple authentication types, for example:
568+
569+ ``` scala mdoc:compile-only
570+ import zio .http ._
571+ import zio .http .endpoint ._
572+
573+ val endpoint = Endpoint (Method .GET / " me" / " favorites" / " books" )
574+ .out[List [Book ]]
575+ .auth(AuthType .Basic | AuthType .Bearer )
576+ ```
577+
578+ This endpoint accepts either ` Basic ` or ` Bearer ` authentication, providing flexibility for clients.
579+
580+ ### Custom Authentication
581+
582+ For custom authentication schemes, use ` AuthType.Custom ` with an ` HttpCodec ` :
583+
584+ ``` scala mdoc:compile-only
585+ import zio .http ._
586+ import zio .http .endpoint ._
587+ import zio .http .codec .HttpCodec
588+
589+ val endpoint = Endpoint (Method .GET / PathCodec .string(" user_id" ) / " favorites" / " books" )
590+ .out[List [Book ]]
591+ .auth(AuthType .Custom (HttpCodec .query[String ](" token" )))
592+ ```
593+
594+ This endpoint uses a custom authentication scheme that extracts the authentication token from a query parameter.
595+
596+ ### Working with Authentication Context
597+
598+ To extract and use authentication information in your handlers, use ` HandlerAspect.customAuthProviding ` to provide an authentication context:
599+
600+ ``` scala mdoc:compile-only
601+ import zio .http ._
602+ import zio .http .endpoint ._
603+ import zio .Config .Secret
604+
605+ case class AuthContext (username : String )
606+
607+ val authMiddleware = HandlerAspect .customAuthProviding[AuthContext ] { request =>
608+ request.headers.get(Header .Authorization ).flatMap {
609+ case Header .Authorization .Basic (username, password) if Secret (username.reverse) == password =>
610+ Some (AuthContext (username))
611+ case _ =>
612+ None
613+ }
614+ }
615+
616+ val endpoint = Endpoint (Method .GET / " me" / " favorites" / " books" )
617+ .out[List [Book ]]
618+ .auth(AuthType .Basic )
619+
620+ def favoriteBooks (username : String ): Task [List [Book ]] = ???
621+
622+ val routes = Routes (
623+ endpoint.implementHandler(
624+ handler((_ : Unit ) =>
625+ withContext((ctx : AuthContext ) => favoriteBooks(ctx.username).orDie)
626+ )
627+ )
628+ ) @@ authMiddleware
629+ ```
630+
631+ The ` customAuthProviding ` middleware extracts authentication information from the request and provides it as context that can be accessed in handlers using ` withContext ` .
632+
633+ ### Multiple Authentication with Context
634+
635+ You can support multiple authentication types in your middleware:
636+
637+ ``` scala mdoc:compile-only
638+ import zio .http ._
639+ import zio .http .endpoint ._
640+ import zio .Config .Secret
641+
642+ case class AuthContext (username : String )
643+
644+ val multiAuthMiddleware = HandlerAspect .customAuthProviding[AuthContext ] { request =>
645+ request.headers.get(Header .Authorization ).flatMap {
646+ case Header .Authorization .Basic (username, password)
647+ if Secret (username.reverse) == password =>
648+ Some (AuthContext (username))
649+ case Header .Authorization .Bearer (token)
650+ if token == Secret (" admin-token" ) =>
651+ Some (AuthContext (" admin" ))
652+ case _ =>
653+ None
654+ }
655+ }
656+
657+ def favoriteBooks (username : String ): Task [List [Book ]] = ???
658+
659+ val endpoint = Endpoint (Method .GET / " me" / " favorites" / " books" )
660+ .out[List [Book ]]
661+ .auth(AuthType .Basic | AuthType .Bearer )
662+
663+ val routes = Routes (
664+ endpoint.implementHandler(
665+ handler((_ : Unit ) =>
666+ withContext((ctx : AuthContext ) => favoriteBooks(ctx.username).orDie)
667+ )
668+ )
669+ ) @@ multiAuthMiddleware
670+ ```
671+
515672## Transforming Endpoint Input/Output and Error Types
516673
517674To transform the input, output, and error types of an endpoint, we can use the ` Endpoint#transformIn ` , ` Endpoint#transformOut ` , and ` Endpoint#transformError ` methods, respectively. Let's see an example:
@@ -535,6 +692,7 @@ In the above example, we mapped over the input type of the `endpoint` and transf
535692The ` transformOut ` and ` transformError ` methods work similarly to the ` transformIn ` method.
536693
537694## CodecConfig
695+
538696The ` CodecConfig ` is injected when building any ` Endpoint ` API codecs. You can see this in the definition of ` BinaryCodecWithSchema ` :
539697
540698``` scala mdoc:compile-only
0 commit comments