http4s-steward[bot] on http4s-scala-xml-0.23.11
http4s-steward[bot] on http4s-scala-xml-0.23.12
Update http4s-scala-xml to 0.23… (compare)
http4s-steward[bot] on http4s-server-0.23.13
Update http4s-circe, http4s-dsl… (compare)
http4s-steward[bot] on scala-library-2.12.15
http4s-steward[bot] on scala-library-2.12.16
Update scala-library, scala-ref… (compare)
http4s-steward[bot] on silencer-lib-1.7.8
http4s-steward[bot] on silencer-lib-1.7.9
Update silencer-lib, silencer-p… (compare)
typelevel-steward[bot] on swagger-ui-4.11.1
Update swagger-ui to 4.11.1 (compare)
class SwaggerSpecEndpoint[F[+ _] : Effect](swaggerSpec: Swagger)(implicit F: Monad[F]) extends Http4sDsl[F] {
lazy val response: F[Response[F]] = {
val fOk = Ok.apply(
Json
.mapper()
.writerWithDefaultPrettyPrinter()
.writeValueAsString(swaggerSpec.toJModel)
)
F.map(fOk) { ok =>
ok.copy(headers = ok.headers.put(`Content-Type`(MediaType.application.json)))
}
}
val service: HttpRoutes[F] = HttpRoutes.of[F] {
case _ @GET -> Root / "swagger.json" => response
}
}
object SwaggerSpecEndpoint {
def endpoint[F[+ _] : Effect](swagger: SwaggerSupport[F], swaggerFormats: SwaggerFormats)(
routes: Seq[RhoRoute[F, _]]
): SwaggerSpecEndpoint[F] = {
import swagger._
val swaggerSpec: Swagger = createSwagger(
swaggerFormats,
security = List(SecurityRequirement("JWT", Nil)),
securityDefinitions = Map("JWT" -> ApiKeyAuthDefinition(auth.JWT_AUTH_HEADER, In.HEADER, "JWT".some))
)(routes)
new SwaggerSpecEndpoint[F](swaggerSpec)
}
}
rootServices = Metrics[F](metricsOps)(
GZip(
CORS(authEndpoint.service, corsConfig) <+> snsService.routes <+>
authService.authenticated(authContext.toService(CORS(coreApi, corsConfig))) <+>
swaggerSpecEndpoint.service <+> CORS(home.service, corsConfig) <+> home.noop
)
)
val authenticated: AuthMiddleware[F, User] =
AuthMiddleware.withFallThrough(authUser)
val authUser: Kleisli[OptionT[F, ?], Request[F], User]
class Routes[F[+_]: Sync](service: FooService[F]) extends RhoRoutes[F] {
private def handleError(t: Throwable): F[BaseResult[F]] = t match {
case e: CustomError =>
BadGateway(e)
case _ =>
InternalServerError(UnexpectedError)
}
GET / "api" +? param[Int]("id") |>> { id: Int =>
service
.getFoo(id)
.flatMap { foo =>
Ok(foo).widen[BaseResult[F]]
}
.handleErrorWith(handleError)
}
}
widen
InternalServerError(someEmptyFooInstance)
but it wouldn't compile either
val authUser: Kleisli[IO, Request[IO], Either[String, User]] = Kleisli { req =>
IO(Right(User("Bob", UUID.randomUUID())))
}
val onFailure: AuthedRoutes[String, IO] = Kleisli(req => OptionT.liftF(Forbidden(req.authInfo)))
val middleware = AuthMiddleware(authUser, onFailure)
object Auth extends AuthedContext[IO, User]
object BobRoutes extends RhoRoutes[IO] {
GET +? param("foo", "bar") >>> Auth.auth |>> { (foo: String, user: User) =>
Ok(s"Bob with id ${user.id}, foo $foo")
}
}
val service = middleware.apply(Auth.toService(BobRoutes.toRoutes()))
This code is copied from AuthedContext.scala
. But the Forbidden
part is still "not found" after import bulk of things to make other part of code works... By the way, how to make service
available for BlazeServerBuilder
, or convert to HttpApp
...?
Many thx!
val jwtStatelessAuthenticator =
JWTAuthenticator.pstateless.inHeader[F, User, HMACSHA256](
signingKey = signingKey,
settings = TSecJWTSettings(JWT_AUTH_HEADER, FiniteDuration(24L * 3600L, TimeUnit.SECONDS), None)
)
val authUser: Kleisli[OptionT[F, ?], Request[F], User] = Kleisli({ req =>
if (userAuthentication) {
jwtStatelessAuthenticator
.extractAndValidate(req)
.map(_.identity)
} else {
OptionT.pure[F](User.dummy)
}
})
private[auth] val defaultNotAuthenticated: AuthedRequest[F, String] => OptionT[F, Response[F]] =
req => OptionT.liftF(Forbidden(req.authInfo))
val onAuthFailure: AuthedRoutes[String, F] = Kleisli(defaultNotAuthenticated)
val authenticated: AuthMiddleware[F, User] =
AuthMiddleware.withFallThrough(authUser)
F[_]
instead of IO
. Is RhoRoutes suitable for that? I guess it is, although all the example code / documentation uses IO
. The reason I'm asking for is I have a route that returns different status codes based on some intermediate results and it works fine with IO
but I can't get it to be of the required F[Result[...]]
type with F[_]:ConcurrentEffect
, instead it just defaults to Any
As far as Intellij's shw implicits feature goes I can't see any difference. My ConcurrentEffect
is being picked up instead of ioEffect
which seems to be fine.
Hello there. Is it possible to get this feature backported to the 0.19.x releases series? We are stuck using the 0.20.x Http4s series right now, and we're trying to build some functionality that depends on the content-type headers:
Happy to open a PR against a branch if one is opened for me.
@zarthross is this something you can help me out with? We're using Rho internally but this is kind of a roadblock for us. We want to have a route support multiple content-types (e.g. json and proto), and we want to use the content-type header to control that. The Swagger document will unfortunately not work properly for this use case without that backport.
We are using 0.19.x because our team is still supporting Scala 2.11 at this time (and that cannot be changed until other vendor changes are completed).
Hello, I updated ther dependencies in my project,
cats-core = 2.1.1
cats-effect = 2.1.2
rho-swagger = 0.20.0
http4s-blaze-server = 0.21.0
now, I have a problem in start the project, the error is
Could not find an instance of Applicative for [x]F[x]
[error] server <- BlazeServerBuilder[F]
[error] ^
Any suggestions to solve this error?, The code is this
import cats.effect.{ConcurrentEffect, ContextShift, ExitCode, IO, IOApp, Resource, Timer}
import co.yyyy.xxxxAPI
import org.http4s.server.Server
import org.http4s.server.blaze.BlazeServerBuilder
object Main extends IOApp {
def run(args: List[String]): IO[ExitCode] =
AppServer.create.use(_ => IO.never).as(ExitCode.Success)
}
object AppServerSwagger {
def create[F[+_]: ConcurrentEffect: ContextShift: Timer]: Resource[F, Server[F]] =
for {
server <- BlazeServerBuilder[F]
.withHttpApp(xxxxAPI[F].httpApi)
.bindLocal(8085)
.resource
} yield server
}
Any error message
[error] found : cats.effect.Resource[[x]F[x],Nothing]
[error] required: cats.effect.Resource[F,org.http4s.server.Server[F]]
[error] config <- Resource.liftF(parser.decodePathF[F, DefaultConfig]("app"))
[error] ^