org.http4s.util.CaseInsensitiveString Scala Examples
The following examples show how to use org.http4s.util.CaseInsensitiveString.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example.
Example 1
Source File: HmacAuthMiddleware.scala From iotchain with MIT License | 5 votes |
package jbok.network.http.server.middleware import java.time.{Duration, Instant} import cats.data.{Kleisli, OptionT} import cats.effect.Sync import jbok.network.http.server.authentication.HMAC import org.http4s.headers.Authorization import org.http4s.util.CaseInsensitiveString import org.http4s.{AuthScheme, Credentials, HttpRoutes, Request, Response, Status} import tsec.mac.jca.{HMACSHA256, MacSigningKey} import scala.concurrent.duration.{FiniteDuration, _} sealed abstract class HmacAuthError(val message: String) extends Exception(message) object HmacAuthError { case object NoAuthHeader extends HmacAuthError("Could not find an Authorization header") case object NoDatetimeHeader extends HmacAuthError("Could not find an X-Datetime header") case object BadMAC extends HmacAuthError("Bad MAC") case object InvalidMacFormat extends HmacAuthError("The MAC is not a valid Base64 string") case object InvalidDatetime extends HmacAuthError("The datetime is not a valid UTC datetime string") case object Timeout extends HmacAuthError("The request time window is closed") } object HmacAuthMiddleware { val defaultDuration: FiniteDuration = 5.minutes private def verifyFromHeader[F[_]]( req: Request[F], key: MacSigningKey[HMACSHA256], duration: FiniteDuration ): Either[HmacAuthError, Unit] = for { authHeader <- req.headers .get(Authorization) .flatMap { t => t.credentials match { case Credentials.Token(scheme, token) if scheme == AuthScheme.Bearer => Some(token) case _ => None } } .toRight(HmacAuthError.NoAuthHeader) datetimeHeader <- req.headers .get(CaseInsensitiveString("X-Datetime")) .toRight(HmacAuthError.NoDatetimeHeader) instant <- HMAC.http.verifyFromHeader( req.method.name, req.uri.renderString, datetimeHeader.value, authHeader, key ) _ <- Either.cond( Instant.now().isBefore(instant.plus(Duration.ofNanos(duration.toNanos))), (), HmacAuthError.Timeout ) } yield () def apply[F[_]: Sync](key: MacSigningKey[HMACSHA256], duration: FiniteDuration = defaultDuration)(routes: HttpRoutes[F]): HttpRoutes[F] = Kleisli { req: Request[F] => verifyFromHeader(req, key, duration) match { case Left(error) => OptionT.some[F](Response[F](Status.Forbidden).withEntity(error.message)) case Right(_) => routes(req) } } }
Example 2
Source File: HttpAttributes.scala From opencensus-scala with Apache License 2.0 | 5 votes |
package io.opencensus.scala.http4s import io.opencensus.scala.http.{RequestExtractor, ResponseExtractor} import org.http4s.util.CaseInsensitiveString import org.http4s.{Request, Response} private[http4s] object HttpAttributes { implicit def requestExtractor[F[_]]: RequestExtractor[Request[F]] = new RequestExtractor[Request[F]] { override def method(req: Request[F]): String = req.method.name override def userAgent(req: Request[F]): Option[String] = req.headers.get(CaseInsensitiveString("User-Agent")).map(_.value) override def path(req: Request[F]): String = req.uri.path.toString override def host(req: Request[F]): String = { val hostHeader = req.headers .get(CaseInsensitiveString("Host")) .map(_.value) req.uri.authority .map(_.host.value) .getOrElse( hostHeader // Having no Host header with a relative URL is invalid according to rfc2616, // but http4s still allows to create such HttpRequests. .getOrElse("") ) } } implicit def responseExtractor[F[_]]: ResponseExtractor[Response[F]] = (res: Response[F]) => res.status.code.toLong }
Example 3
Source File: JdkHttpClient.scala From http4s-jdk-http-client with Apache License 2.0 | 5 votes |
package org.http4s.client.jdkhttpclient import java.net.URI import java.net.http.HttpRequest.BodyPublishers import java.net.http.HttpResponse.BodyHandlers import java.net.http.{HttpClient, HttpRequest, HttpResponse} import java.nio.ByteBuffer import java.util import java.util.concurrent.Flow import cats.ApplicativeError import cats.effect._ import cats.implicits._ import fs2.concurrent.SignallingRef import fs2.interop.reactivestreams._ import fs2.{Chunk, Stream} import org.http4s.client.Client import org.http4s.client.jdkhttpclient.compat.CollectionConverters._ import org.http4s.internal.fromCompletionStage import org.http4s.util.CaseInsensitiveString import org.http4s.{Header, Headers, HttpVersion, Request, Response, Status} import org.reactivestreams.FlowAdapters object JdkHttpClient { def simple[F[_]](implicit F: ConcurrentEffect[F], CS: ContextShift[F]): F[Client[F]] = F.delay(HttpClient.newHttpClient()).map(apply(_)) def convertHttpVersionFromHttp4s[F[_]]( version: HttpVersion )(implicit F: ApplicativeError[F, Throwable]): F[HttpClient.Version] = version match { case HttpVersion.`HTTP/1.1` => HttpClient.Version.HTTP_1_1.pure[F] case HttpVersion.`HTTP/2.0` => HttpClient.Version.HTTP_2.pure[F] case _ => F.raiseError(new IllegalArgumentException("invalid HTTP version")) } // see jdk.internal.net.http.common.Utils#DISALLOWED_HEADERS_SET private val restrictedHeaders = Set( "connection", "content-length", "date", "expect", "from", "host", "upgrade", "via", "warning" ).map(CaseInsensitiveString(_)) }
Example 4
Source File: AuthedHttp4s.scala From pure-movie-server with Apache License 2.0 | 5 votes |
package pms.algebra.http import pms.core.Fail import pms.effects._ import pms.effects.implicits._ import pms.algebra.user._ import org.http4s._ import org.http4s.dsl._ import org.http4s.server._ import org.http4s.util.CaseInsensitiveString object AuthedHttp4s { def userTokenAuthMiddleware[F[_]: Async](authAlgebra: UserAuthAlgebra[F]): AuthMiddleware[F, AuthCtx] = { val tokenVerification: Kleisli[F, Request[F], Attempt[AuthCtx]] = verifyToken[F](authAlgebra) AuthMiddleware(tokenVerification, onFailure) } private val `X-Auth-Token` = CaseInsensitiveString("X-AUTH-TOKEN") private val challenges: NonEmptyList[Challenge] = NonEmptyList.of( Challenge( scheme = "Basic", realm = "Go to POST /pms/api/user/login to get valid token", ) ) private val wwwHeader = headers.`WWW-Authenticate`(challenges) private def onFailure[F[_]: Async]: AuthedRoutes[Throwable, F] = Kleisli[OptionT[F, *], AuthedRequest[F, Throwable], Response[F]] { _: AuthedRequest[F, Throwable] => val fdsl = Http4sDsl[F] import fdsl._ OptionT.liftF[F, Response[F]](Unauthorized(wwwHeader)) } private def verifyToken[F[_]: Async](authAlgebra: UserAuthAlgebra[F]): Kleisli[F, Request[F], Attempt[AuthCtx]] = Kleisli { req: Request[F] => val optHeader = req.headers.get(`X-Auth-Token`) optHeader match { case None => Attempt .raiseError[AuthCtx](Fail.unauthorized(s"No ${`X-Auth-Token`} provided")) .pure[F] case Some(header) => authAlgebra .authenticate(AuthenticationToken(header.value)) .map(Attempt.pure) .handleError(Attempt.raiseError) } } }
Example 5
Source File: SessionManagerSpec.scala From pizza-auth-3 with MIT License | 5 votes |
package moe.pizza.auth.webapp import moe.pizza.auth.interfaces.UserDatabase import org.http4s._ import org.http4s.dsl._ import org.http4s.util.CaseInsensitiveString import org.scalatest.mock.MockitoSugar import org.scalatest.{FlatSpec, MustMatchers} import moe.pizza.auth.webapp.Utils._ class SessionManagerSpec extends FlatSpec with MustMatchers with MockitoSugar { val emptyservice = HttpService { case req @ GET -> Root => Ok(req.getSession.toString) case req @ GET -> Root / "flash" => val newsession = req.flash(Alerts.info, "this is an alert") Ok(req.getSession.toString).attachSessionifDefined(newsession) case req @ GET -> Root / "logout" => Ok(req.getSession.toString).clearSession() } val ud = mock[UserDatabase] val svc = new SessionManager("keygoeshere", ud).apply(emptyservice) "when wrapping a service it" should "add a session cookie" in { val r = svc.apply(new Request(uri = Uri.uri("/"))).run r.status must equal(Ok) val session = r.headers.get(CaseInsensitiveString("set-cookie")).get session.value.startsWith("authsession=") must equal(true) val bodytxt = EntityDecoder.decodeString(r)(Charset.`UTF-8`).run bodytxt must equal("Some(HydratedSession(List(),None,None,None))") } "when wrapping a service it" should "add a session cookie and use it to store state between calls" in { val r = svc.apply(new Request(uri = Uri.uri("/flash"))).run r.status must equal(Ok) val session = r.headers.get(CaseInsensitiveString("set-cookie")).get session.value.startsWith("authsession=") must equal(true) val cookie = session.value val r2 = svc .apply( new Request(uri = Uri.uri("/"), headers = Headers(Header("Cookie", cookie)))) .run r.status must equal(Ok) val bodytxt = EntityDecoder.decodeString(r2)(Charset.`UTF-8`).run bodytxt must equal( "Some(HydratedSession(List(Alert(info,this is an alert)),None,None,None))") } "when wrapping a service it" should "be able to remove sessions" in { val r = svc.apply(new Request(uri = Uri.uri("/logout"))).run r.status must equal(Ok) val removal = r.headers.get(CaseInsensitiveString("set-cookie")).get assert(removal.value.startsWith("authsession=;")) } }
Example 6
Source File: Http4sExtras.scala From nexus with Apache License 2.0 | 5 votes |
package ch.epfl.bluebrain.nexus.cli.utils import cats.implicits._ import ch.epfl.bluebrain.nexus.cli.sse._ import org.http4s.Credentials.Token import org.http4s.Request import org.http4s.ServerSentEvent.EventId import org.http4s.dsl.impl.{/, Root} import org.http4s.headers.{`Content-Type`, `Last-Event-Id`, Authorization} import org.http4s.util.CaseInsensitiveString import scala.util.{Success, Try} trait Http4sExtras { protected class Var[A](cast: String => Try[A]) { def unapply(str: String): Option[A] = if (!str.isEmpty) cast(str).toOption else None } object OrgUuidVar extends Var(str => Try(java.util.UUID.fromString(str)).map(OrgUuid.apply)) object ProjectUuidVar extends Var(str => Try(java.util.UUID.fromString(str)).map(ProjectUuid.apply)) object OrgLabelVar extends Var(str => Success(OrgLabel(str))) object ProjectLabelVar extends Var(str => Success(ProjectLabel(str))) object optbearer { def unapply[F[_]](request: Request[F]): Option[(Request[F], Option[BearerToken])] = request.headers.get(Authorization) match { case Some(Authorization(Token(authScheme, token))) if authScheme === CaseInsensitiveString("bearer") => Some((request, Some(BearerToken(token)))) case _ => Some((request, None)) } } object bearer { def unapply[F[_]](request: Request[F]): Option[(Request[F], BearerToken)] = optbearer.unapply(request) match { case Some((_, Some(token))) => Some((request, token)) case _ => None } } object db { def unapply[F[_]](request: Request[F]): Option[(Request[F], String)] = request.uri.params.get("db").map(request -> _) } object contentType { def unapply[F[_]](request: Request[F]): Option[(Request[F], `Content-Type`)] = request.headers.get(`Content-Type`) match { case Some(ct: `Content-Type`) => Some((request, ct)) case _ => None } } object optLastEventId { def unapply[F[_]](request: Request[F]): Option[(Request[F], Option[Offset])] = request.headers.get(`Last-Event-Id`) match { case Some(`Last-Event-Id`(EventId(value))) => Some((request, Offset(value))) case _ => Some((request, None)) } } object lastEventId { def unapply[F[_]](request: Request[F]): Option[(Request[F], Offset)] = optLastEventId.unapply(request) match { case Some((_, Some(offset))) => Some((request, offset)) case _ => None } } val v1: / = Root / "v1" } object Http4sExtras extends Http4sExtras
Example 7
Source File: AuthExampleApp.scala From caliban with Apache License 2.0 | 5 votes |
package caliban.http4s import caliban.GraphQL._ import caliban.schema.GenericSchema import caliban.{ Http4sAdapter, RootResolver } import org.http4s.HttpRoutes import org.http4s.dsl.Http4sDsl import org.http4s.implicits._ import org.http4s.server.blaze.BlazeServerBuilder import org.http4s.server.{ Router, ServiceErrorHandler } import org.http4s.util.CaseInsensitiveString import zio._ import zio.interop.catz._ import zio.interop.catz.implicits._ import scala.concurrent.ExecutionContext object AuthExampleApp extends CatsApp { // Simple service that returns the token coming from the request type Auth = Has[Auth.Service] object Auth { trait Service { def token: String } } type AuthTask[A] = RIO[Auth, A] case class MissingToken() extends Throwable // http4s middleware that extracts a token from the request and eliminate the Auth layer dependency object AuthMiddleware { def apply(route: HttpRoutes[AuthTask]): HttpRoutes[Task] = Http4sAdapter.provideLayerFromRequest( route, _.headers.get(CaseInsensitiveString("token")) match { case Some(value) => ZLayer.succeed(new Auth.Service { override def token: String = value.value }) case None => ZLayer.fail(MissingToken()) } ) } // http4s error handler to customize the response for our throwable object dsl extends Http4sDsl[Task] import dsl._ val errorHandler: ServiceErrorHandler[Task] = _ => { case MissingToken() => Forbidden() } // our GraphQL API val schema: GenericSchema[Auth] = new GenericSchema[Auth] {} import schema._ case class Query(token: RIO[Auth, String]) private val resolver = RootResolver(Query(ZIO.access[Auth](_.get[Auth.Service].token))) private val api = graphQL(resolver) override def run(args: List[String]): ZIO[ZEnv, Nothing, ExitCode] = (for { interpreter <- api.interpreter route = AuthMiddleware(Http4sAdapter.makeHttpService(interpreter)) _ <- BlazeServerBuilder[Task](ExecutionContext.global) .withServiceErrorHandler(errorHandler) .bindHttp(8088, "localhost") .withHttpApp(Router[Task]("/api/graphql" -> route).orNotFound) .resource .toManaged .useForever } yield ()).exitCode }
Example 8
Source File: StatusService.scala From zio-telemetry with Apache License 2.0 | 5 votes |
package zio.telemetry.opentelemetry.example.http import io.circe.Encoder import io.circe.syntax._ import io.opentelemetry.OpenTelemetry import io.opentelemetry.context.propagation.HttpTextFormat import io.opentelemetry.context.propagation.HttpTextFormat.Getter import io.opentelemetry.trace.Span import org.http4s._ import org.http4s.circe.jsonEncoderOf import org.http4s.dsl.Http4sDsl import org.http4s.util.CaseInsensitiveString import zio.interop.catz._ import zio.telemetry.opentelemetry.Tracing import zio.telemetry.opentelemetry.TracingSyntax._ import zio.telemetry.opentelemetry.example.http.{ Status => ServiceStatus } object StatusService { val dsl: Http4sDsl[AppTask] = Http4sDsl[AppTask] import dsl._ implicit def encoder[A: Encoder]: EntityEncoder[AppTask, A] = jsonEncoderOf[AppTask, A] val httpTextFormat: HttpTextFormat = OpenTelemetry.getPropagators.getHttpTextFormat val getter: Getter[Headers] = (carrier, key) => carrier.get(CaseInsensitiveString(key)).map(_.value).orNull val routes: HttpRoutes[AppTask] = HttpRoutes.of[AppTask] { case request @ GET -> Root / "status" => val response = for { _ <- Tracing.addEvent("event from backend before response") response <- Ok(ServiceStatus.up("backend").asJson) _ <- Tracing.addEvent("event from backend after response") } yield response response.spanFrom(httpTextFormat, request.headers, getter, "/status", Span.Kind.SERVER) } }
Example 9
Source File: Http4sDecodeInputsContext.scala From tapir with Apache License 2.0 | 5 votes |
package sttp.tapir.server.http4s import org.http4s.Request import org.http4s.util.CaseInsensitiveString import sttp.model.{Method, QueryParams} import sttp.tapir.model.ServerRequest import sttp.tapir.server.internal.DecodeInputsContext class Http4sDecodeInputsContext[F[_]](req: Request[F]) extends DecodeInputsContext { override def method: Method = Method(req.method.name.toUpperCase) override def nextPathSegment: (Option[String], DecodeInputsContext) = { val nextStart = req.pathInfo.dropWhile(_ == '/') val segment = nextStart.split("/", 2) match { case Array("") => None case Array(s) => Some(s) case Array(s, _) => Some(s) } // if the routes are mounted within a context (e.g. using a router), we have to match against what comes // after the context. This information is stored in the the PathInfoCaret attribute val oldCaret = req.attributes.lookup(Request.Keys.PathInfoCaret).getOrElse(0) val segmentSlashLength = segment.map(_.length).getOrElse(0) + 1 val reqWithNewCaret = req.withAttribute(Request.Keys.PathInfoCaret, oldCaret + segmentSlashLength) (segment, new Http4sDecodeInputsContext(reqWithNewCaret)) } override def header(name: String): List[String] = req.headers.get(CaseInsensitiveString(name)).map(_.value).toList override def headers: Seq[(String, String)] = req.headers.toList.map(h => (h.name.value, h.value)) override def queryParameter(name: String): Seq[String] = queryParameters.getMulti(name).getOrElse(Nil) override val queryParameters: QueryParams = QueryParams.fromMultiMap(req.multiParams) override def bodyStream: Any = req.body override def serverRequest: ServerRequest = new Http4sServerRequest(req) }
Example 10
Source File: CorrelationIdMiddleware.scala From scala-server-toolkit with MIT License | 5 votes |
package com.avast.sst.http4s.server.middleware import java.util.UUID import cats.data.{Kleisli, OptionT} import cats.effect.Sync import cats.syntax.functor._ import com.avast.sst.http4s.server.middleware.CorrelationIdMiddleware.CorrelationId import io.chrisdavenport.vault.Key import org.http4s.util.CaseInsensitiveString import org.http4s.{Header, HttpRoutes, Request, Response} import org.slf4j.LoggerFactory class CorrelationIdMiddleware[F[_]: Sync]( correlationIdHeaderName: CaseInsensitiveString, attributeKey: Key[CorrelationId], generator: () => String ) { private val logger = LoggerFactory.getLogger(this.getClass) private val F = Sync[F] def wrap(routes: HttpRoutes[F]): HttpRoutes[F] = Kleisli[OptionT[F, *], Request[F], Response[F]] { request => request.headers.get(correlationIdHeaderName) match { case Some(header) => val requestWithAttribute = request.withAttribute(attributeKey, CorrelationId(header.value)) routes(requestWithAttribute).map(r => r.withHeaders(r.headers.put(header))) case None => for { newCorrelationId <- OptionT.liftF(F.delay(generator())) _ <- log(newCorrelationId) requestWithAttribute = request.withAttribute(attributeKey, CorrelationId(newCorrelationId)) response <- routes(requestWithAttribute) } yield response.withHeaders(response.headers.put(Header(correlationIdHeaderName.value, newCorrelationId))) } } def retrieveCorrelationId(request: Request[F]): Option[CorrelationId] = request.attributes.lookup(attributeKey) private def log(newCorrelationId: String) = { OptionT.liftF { F.delay { if (logger.isDebugEnabled()) { logger.debug(s"Generated new correlation ID: $newCorrelationId") } } } } } object CorrelationIdMiddleware { final case class CorrelationId(value: String) extends AnyVal @SuppressWarnings(Array("scalafix:Disable.toString")) def default[F[_]: Sync]: F[CorrelationIdMiddleware[F]] = { Key.newKey[F, CorrelationId].map { attributeKey => new CorrelationIdMiddleware(CaseInsensitiveString("Correlation-ID"), attributeKey, () => UUID.randomUUID().toString) } } }
Example 11
Source File: CorrelationIdMiddlewareTest.scala From scala-server-toolkit with MIT License | 5 votes |
package com.avast.sst.http4s.server.middleware import java.net.InetSocketAddress import cats.effect.{ContextShift, IO, Resource, Timer} import com.avast.sst.http4s.server.Http4sRouting import org.http4s.client.blaze.BlazeClientBuilder import org.http4s.dsl.Http4sDsl import org.http4s.server.blaze.BlazeServerBuilder import org.http4s.util.CaseInsensitiveString import org.http4s.{Header, HttpRoutes, Request, Uri} import org.scalatest.funsuite.AsyncFunSuite import scala.concurrent.ExecutionContext @SuppressWarnings(Array("scalafix:Disable.get", "scalafix:Disable.toString", "scalafix:Disable.createUnresolved")) class CorrelationIdMiddlewareTest extends AsyncFunSuite with Http4sDsl[IO] { implicit private val cs: ContextShift[IO] = IO.contextShift(ExecutionContext.global) implicit private val timer: Timer[IO] = IO.timer(ExecutionContext.global) test("CorrelationIdMiddleware fills Request attributes and HTTP response header") { val test = for { middleware <- Resource.liftF(CorrelationIdMiddleware.default[IO]) routes = Http4sRouting.make { middleware.wrap { HttpRoutes.of[IO] { case req @ GET -> Root / "test" => val id = middleware.retrieveCorrelationId(req) Ok("test").map(_.withHeaders(Header("Attribute-Value", id.toString))) } } } server <- BlazeServerBuilder[IO](ExecutionContext.global) .bindSocketAddress(InetSocketAddress.createUnresolved("127.0.0.1", 0)) .withHttpApp(routes) .resource client <- BlazeClientBuilder[IO](ExecutionContext.global).resource } yield (server, client) test .use { case (server, client) => client .run( Request[IO](uri = Uri.unsafeFromString(s"http://${server.address.getHostString}:${server.address.getPort}/test")) .withHeaders(Header("Correlation-Id", "test-value")) ) .use { response => IO.delay { assert(response.headers.get(CaseInsensitiveString("Correlation-Id")).get.value === "test-value") assert(response.headers.get(CaseInsensitiveString("Attribute-Value")).get.value === "Some(CorrelationId(test-value))") } } } .unsafeToFuture() } }