Skip to content

Commit 3643317

Browse files
committed
Respond with 401 in case of missing Authorization header
1 parent d8f9c69 commit 3643317

File tree

4 files changed

+36
-5
lines changed

4 files changed

+36
-5
lines changed
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package zio.http.endpoint
2+
3+
import zio.ZIO
4+
import zio.test._
5+
6+
import zio.http._
7+
import zio.http.codec._
8+
9+
object UnauthorizedSpec extends ZIOSpecDefault {
10+
override def spec =
11+
suite("UnauthorizedSpec")(
12+
test("should 401 Unauthorized when required authorization header is missing") {
13+
val endpoint = Endpoint(Method.GET / "test")
14+
.header(HeaderCodec.authorization)
15+
.out[Unit]
16+
val route = endpoint.implement(_ => ZIO.unit)
17+
val request =
18+
Request(method = Method.GET, url = url"/test")
19+
for {
20+
response <- route.toRoutes.runZIO(request)
21+
} yield assertTrue(Status.Unauthorized == response.status)
22+
},
23+
)
24+
}

zio-http/shared/src/main/scala/zio/http/codec/HttpCodecError.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ object HttpCodecError {
3333
final case class MissingHeader(headerName: String) extends HttpCodecError {
3434
def message = s"Missing header $headerName"
3535
}
36+
final case object MissingAuthorizationHeader extends HttpCodecError {
37+
def message = "Missing header Authorization"
38+
}
3639
final case class MalformedMethod(expected: zio.http.Method, actual: zio.http.Method) extends HttpCodecError {
3740
def message = s"Expected $expected but found $actual"
3841
}

zio-http/shared/src/main/scala/zio/http/codec/internal/EncoderDecoder.scala

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,10 @@ private[codec] object EncoderDecoder {
384384
.getOrElse(throw HttpCodecError.MalformedHeader(codec.name, codec.textCodec))
385385

386386
case None =>
387-
throw HttpCodecError.MissingHeader(codec.name)
387+
if (codec.name == Header.Authorization.name)
388+
throw HttpCodecError.MissingAuthorizationHeader
389+
else
390+
throw HttpCodecError.MissingHeader(codec.name)
388391
},
389392
)
390393

zio-http/shared/src/main/scala/zio/http/endpoint/Endpoint.scala

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import zio.schema.Schema
2727

2828
import zio.http.Header.Accept.MediaTypeWithQFactor
2929
import zio.http._
30-
import zio.http.codec._
30+
import zio.http.codec.{StatusCodec, _}
3131
import zio.http.endpoint.Endpoint.{OutErrors, defaultMediaTypes}
3232

3333
/**
@@ -340,9 +340,10 @@ final case class Endpoint[PathInput, Input, Err, Output, Auth <: AuthType](
340340
case Some(HttpCodecError.CustomError("SchemaTransformationFailure", message))
341341
if maybeUnauthedResponse.isDefined && message.endsWith(" auth required") =>
342342
maybeUnauthedResponse.get
343-
case Some(_) =>
343+
case Some(HttpCodecError.MissingAuthorizationHeader) =>
344+
Handler.succeed(Response.unauthorized)
345+
case Some(error) =>
344346
Handler.fromFunctionZIO { (request: zio.http.Request) =>
345-
val error = cause.defects.head.asInstanceOf[HttpCodecError]
346347
val response = {
347348
val outputMediaTypes =
348349
(
@@ -355,7 +356,7 @@ final case class Endpoint[PathInput, Input, Err, Output, Auth <: AuthType](
355356
}
356357
ZIO.succeed(response)
357358
}
358-
case None =>
359+
case None =>
359360
Handler.failCause(cause)
360361
}
361362
}

0 commit comments

Comments
 (0)