diff --git a/modules/restserver/src/main/scala/docspell/restserver/http4s/ClientHost.scala b/modules/restserver/src/main/scala/docspell/restserver/http4s/ClientHost.scala new file mode 100644 index 00000000..2c06dd15 --- /dev/null +++ b/modules/restserver/src/main/scala/docspell/restserver/http4s/ClientHost.scala @@ -0,0 +1,29 @@ +package docspell.restserver.http4s + +import org.http4s._ +import org.http4s.headers._ +import org.http4s.util.CaseInsensitiveString + +/** Obtain the host name of the client from the request. + */ +object ClientHost { + + def get[F[_]](req: Request[F]): Option[String] = + xForwardedFor(req) + .orElse(xForwardedHost(req)) + .orElse(host(req)) + + private def host[F[_]](req: Request[F]): Option[String] = + req.headers.get(Host).map(_.host) + + private def xForwardedFor[F[_]](req: Request[F]): Option[String] = + req.headers + .get(`X-Forwarded-For`) + .flatMap(_.values.head) + .flatMap(inet => Option(inet.getHostName).orElse(Option(inet.getHostAddress))) + + private def xForwardedHost[F[_]](req: Request[F]): Option[String] = + req.headers + .get(CaseInsensitiveString("X-Forwarded-Host")) + .map(_.value) +} diff --git a/modules/restserver/src/main/scala/docspell/restserver/routes/LoginRoutes.scala b/modules/restserver/src/main/scala/docspell/restserver/routes/LoginRoutes.scala index d707d8b8..78b39b8b 100644 --- a/modules/restserver/src/main/scala/docspell/restserver/routes/LoginRoutes.scala +++ b/modules/restserver/src/main/scala/docspell/restserver/routes/LoginRoutes.scala @@ -7,6 +7,7 @@ import docspell.backend.auth._ import docspell.restapi.model._ import docspell.restserver._ import docspell.restserver.auth._ +import docspell.restserver.http4s.ClientHost import org.http4s._ import org.http4s.circe.CirceEntityDecoder._ @@ -23,7 +24,7 @@ object LoginRoutes { for { up <- req.as[UserPass] res <- S.loginUserPass(cfg.auth)(Login.UserPass(up.account, up.password)) - remote = req.from.map(_.getHostName()) + remote = ClientHost.get(req) resp <- makeResponse(dsl, cfg, remote, res, up.account) } yield resp } @@ -37,10 +38,10 @@ object LoginRoutes { case req @ POST -> Root / "session" => Authenticate .authenticateRequest(S.loginSession(cfg.auth))(req) - .flatMap(res => makeResponse(dsl, cfg, req.from.map(_.getHostName), res, "")) + .flatMap(res => makeResponse(dsl, cfg, ClientHost.get(req), res, "")) case req @ POST -> Root / "logout" => - Ok().map(_.addCookie(CookieData.deleteCookie(cfg, req.from.map(_.getHostName)))) + Ok().map(_.addCookie(CookieData.deleteCookie(cfg, ClientHost.get(req)))) } }