/
package.scala
91 lines (78 loc) · 3.15 KB
/
package.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
package org.http4s
import scala.util.control.NonFatal
import cats.arrow.Choice
import cats.data._
import cats.implicits._
import fs2._
import fs2.interop.cats._
import org.http4s.headers.{Connection, `Content-Length`}
import org.http4s.syntax.string._
import org.log4s.getLogger
package object server {
/**
* A middleware is a function of one [[Service]] to another, possibly of a
* different [[Request]] and [[Response]] type. http4s comes with several
* middlewares for composing common functionality into services.
*
* @tparam A the request type of the original service
* @tparam B the response type of the original service
* @tparam C the request type of the resulting service
* @tparam D the response type of the resulting service
*/
type Middleware[A, B, C, D] = Service[A, B] => Service[C, D]
object Middleware {
def apply[A, B, C, D](f: (C, Service[A, B]) => Task[D]): Middleware[A, B, C, D] = {
service => Service.lift {
req => f(req, service)
}
}
}
/**
* An HTTP middleware converts an [[HttpService]] to another.
*/
type HttpMiddleware = Middleware[Request, MaybeResponse, Request, MaybeResponse]
/**
* An HTTP middleware that authenticates users.
*/
type AuthMiddleware[T] = Middleware[AuthedRequest[T], MaybeResponse, Request, MaybeResponse]
/**
* Old name for SSLConfig
*/
@deprecated("Use SSLConfig", "2016-12-31")
type SSLBits = SSLConfig
object AuthMiddleware {
def apply[T](authUser: Service[Request, T]): AuthMiddleware[T] = {
service => service.compose(AuthedRequest(authUser.run))
}
def apply[Err, T](
authUser: Service[Request, Either[Err, T]],
onFailure: Service[AuthedRequest[Err], MaybeResponse]
): AuthMiddleware[T] = {
service: Service[AuthedRequest[T], MaybeResponse] =>
Choice[Service]
.choice(onFailure, service)
.local({ authed: AuthedRequest[Either[Err, T]] =>
authed.authInfo.bimap(
err => AuthedRequest(err, authed.req),
suc => AuthedRequest(suc, authed.req)
)
})
.compose(AuthedRequest(authUser.run))
}
}
private[this] val messageFailureLogger = getLogger("org.http4s.server.message-failures")
private[this] val serviceErrorLogger = getLogger("org.http4s.server.service-errors")
type ServiceErrorHandler = Request => PartialFunction[Throwable, Task[Response]]
val DefaultServiceErrorHandler: ServiceErrorHandler = req => {
case mf: MessageFailure =>
messageFailureLogger.debug(mf)(s"""Message failure handling request: ${req.method} ${req.pathInfo} from ${req.remoteAddr.getOrElse("<unknown>")}""")
mf.toHttpResponse(req.httpVersion)
case NonFatal(t) =>
serviceErrorLogger.error(t)(s"""Error servicing request: ${req.method} ${req.pathInfo} from ${req.remoteAddr.getOrElse("<unknown>")}""")
Task.now(Response(Status.InternalServerError, req.httpVersion,
Headers(
Connection("close".ci),
`Content-Length`.zero
)))
}
}