Where communities thrive

  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
Repo info
  • 18:01
    amesgen commented #6420
  • 17:25
    armanbilge labeled #6420
  • 17:25
    armanbilge labeled #6420
  • 17:25
    armanbilge opened #6420
  • 15:23
    matthughes commented #2483
  • 15:23
    matthughes commented #2483
  • 15:17
    armanbilge labeled #6419
  • 15:14
    matthughes opened #6419
  • 13:35

    rossabaker on v1.0.0-M33


  • 13:29

    rossabaker on main

    Refresh the README for modern d… Merge pull request #682 from ht… Merge branch 'series/0.23' (compare)

  • 12:52
    MonikaJassova starred http4s/http4s
  • 12:26
    rossabaker closed #683
  • 12:25

    rossabaker on 0.23

    Refresh the README for modern d… Merge pull request #682 from ht… (compare)

  • 12:25
    rossabaker closed #682
  • 06:12
    armanbilge commented #5812
  • 05:21
    armanbilge commented #5812
  • 05:10
    armanbilge labeled #5812
  • 04:00
    rossabaker commented #683
  • 03:59

    rossabaker on merge-core-1.0

    Update to http4s-1.0.0-M33 (compare)

  • 03:59
    rossabaker synchronize #683
Jonathan Frawley
But for that, I get:
[error] 41 |              contents <- part.body.through(utf8Decode).runFoldMonoid
[error]    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[error]    |value runFoldMonoid is not a member of fs2.Stream[cats.effect.IO, String]
Any advice / pointers would be appreciated!
Petr Nejedly

Hi there. Migrating from 0.22.xx to 0.23.7 is giving me some inconsistent behaviour in the Router area.

with a code like this:

val r = Router(
  "/ping" -> PingRoutes.routes

class PingRoutes extends Http4sDsl[IO] {
  def routes: HttpRoutes[IO] = {
    HttpRoutes.of[IO] {
      case GET -> Root => Ok("pong")        

I'd expect calls to http://localhost:8080/ping to return pong (and it worked in 0.21.x). Now I'm getting 404.
I can only get it to return pong when the routes are changed to:

case GET -> Root / "ping" => Ok("pong")

So somehow the prefix in Router is not taken into account.

Is this a bug or am I missing something?

Petr Nejedly
Btw, we're using JettyBuilder and bind the app via .mountHttpApp(routes.orNotFound, "/"). What I noticed is that replacing / here with /foo makes it work, ie requests to /foo/ping return pong.
Petr Nejedly
Ah, looks like we're hitting http4s/http4s#5362
Hi all ;) How HttpRoutes[F] gets translated into HttpApp[F]? I mean how you get rid of the OptionT that is nested in Kleisli?
I think I have found a way
  def y1[F[_]: Sync]: Kleisli[OptionT[F, *], Int, Int] = Kleisli { i =>
    OptionT {
      Sync[F].delay {
        if (i < 10) Some(i * 100)
        else None

  def y2[F[_]: Sync](input: Kleisli[OptionT[F, *], Int, Int]): Kleisli[F, Int, Int] = input.mapF { i =>

  override def run = List(y2[IO](y1[IO]).run(11), y2[IO](y1[IO]).run(9)).sequence.map(println).void
does this make sense?
Fabio Labella
Joe Graham
so what's the best way to get a BlazeClient Response body as a String?
2 replies
Son Mai
Hi guys, why do we need IO in Request[IO]? what kind of effect is it here? when is it executed?
Hey folks,ZIO-https claims that it is much faster than http4s .. any ideas? i am just in the middle of choosing framework & libraries for our microservices
Michael Pilquist
Most discussion is on Typelevel Discord: https://discord.gg/bSQBZA3Ced
Gabriel Asman

Hi 👋

We've encountered an unexpected behaviour regarding cookie headers
Basically, when you parse a raw header that contains both valid and invalid headers, we were expecting that the valid ones would be returned, instead the result was an empty list of cookies

In other words

Headers(Header.Raw(ci"Cookie", """key1=value1; key2={"aField":{}}"""))).cookies

returns a ParseFailure (second cookie contains quotes) rather than salvaging the valid one (the first cookie). We can see in the code why that is, but we were thinking that this could be improved (split by semicolon first, only throw away invalid cookies)?

The resulting behaviour would be similar to what happens right now when you pass separate raw cookie headers. I.e:

Request[Id](headers =
          Header.Raw(ci"Cookie", """key1=value1"""),
          Header.Raw(ci"Cookie", """key2={"aField":{}}""")

actually does return the first cookie unharmed, so we don't think it'd be a problem for the parser to separate cookies within the same raw header before validation.

What do people think?


Hi here!

I’m using multiple HTTP clients as part of one application (just for isulation guarantees) and that end up in huge amount of threads.
Could I somehow reuse thread pools for all those clients? I've tryied using shared AsynchronousChannelGroup but that only increase total amount of threads

Daniel Warmuth
Hi, I want to call org.http4s.servlet.syntax.ServletContextOps#mountService to mount a service inside a servlet container. However, I do not understand how or where to create the dispatcher. If I create a dispatcher (via Dispatcher[IO]) use it (via "use"), then it is already closed when the service is called, and I receive "java.lang.IllegalStateException: dispatcher already shutdown
at cats.effect.std.Dispatcher$$anon$2.unsafeToFutureCancelable(Dispatcher.scala:281)". This is probably to be expected given the documentation of Dispatcher: "Once the resource scope exits, all active effects will be canceled, and attempts to submit new effects will throw an exception.".
So how should I create the dispatcher that I need for mountService? Thanks a lot in advance!
Daniel Warmuth
Btw, this has been answered in the much more active Discord channel: https://discord.com/channels/632277896739946517/632286375311573032/940294651724857474
Fabrice Sznajderman
Hi All :)
I have an app based on Http4s ...
I put authentification mecanism as follow :
def api = AuthedRoutes.of[UserInfo,ApiTask] { case POST -> Root / "api" / "hit" as user => for { hitItem <- request.as[HitRequest] _ <- hitService.hit(hitItem.toHit) r <- Created("Hit created") } yield r
I can access to user information.. but I cannot access to request body as before :-/
Fabrice Sznajderman
like the following statement : request.as[HitRequest]
How, with authedRoutes, I can access to the body of request ?
Many thanks for your help
Fabrice Sznajderman
I found what I am looking for .. I dove into http4s code base to understand . In fact, when service become authored service .. the parameter xx@___ on partial function become a ContextRequestinstead of simply Request. This type wrap the request. Then to access to the request's body... you have to do xx.req
Stefanos Mandalas
Hi. I am trying to get http4s to work with graalvm and I get java.lang.IncompatibleClassChangeError. Has anyone come across this issue?
Fabrice Sznajderman
I looked for the Java Error, and it seems that binary code changed without recompiling step.
hope it will be useful
Yogesh Dubey
Hi, I have a catch-all endpoint for static resources (GET -> path). This works correctly for GET requests, i.e I can get the static resources. However, when I use this in a app, the app makes OPTIONS request to the static request URL which fails with a 404. I have CORS setup with OPTIONS method allowed. What am I missing?
do you have withCredentials(true) in your cors config?
Yogesh Dubey
yes, I do have .withAllowCredentials(true)
Ian Agius

Im trying to map certain errors to certain HTTP responses using http4s and I've encountered an issue with Unauthorized (401) response.

Consider the following:

case class ErrorDto(key: String, value: String) extends NoStackTrace

private val errorHandler: PartialFunction[Throwable, F[Response[F]]] = {
    case IdNotFound(id) =>
        NotFound(ErrorDto("ID_NOT_FOUND", id))
    case SessionTimeout(httpSession) =>
        Unauthorized(ErrorDto("LOGGED_OUT", httpSession)) // <----- THIS IS NOT ALLOWED

The problem is that unlike the others, Unauthorized does not take ErrorDto which in turn is sent back as body to the FE but instead takes something like the following (found this in this chat from 2019):

Unauthorized(Challenge(scheme = "MY_SCHEME", realm = "MyRealm", Map.empty))

I tried to add the body information that I would like to have in the Map Map("LOGGED_OUT" -> "Ticket not found") but still, the response is being sent without a body. Do you have any suggestions on how I can go around this please?

Yogesh Dubey
You can respond with a body
Unauthorized.apply( authenticate:WWW-Authenticate= ???, body = ErrorDto("LOGGED_OUT", httpSession) )
@ianagius the syntax is
Unauthorized.apply( authenticate=WWW-Authenticate(NonEmptyList.one(Challenge("MyScheme", "MyRealm"))), body = ErrorDto("LOGGED_OUT", httpSession) )
Ian Agius
thanks a lot @ydubey. Will try it out!

Hi Team,

We have built graphQL server app where we are using http4s as service.
Below is code snippet for it:

import org.http4s.server.blaze.BlazeServerBuilder

server  <- BlazeServerBuilder[ExampleTask]
.bindHttp(8080, "")
             "/"    -> otherRoutes,
             "/"               -> metricsSvc.routes,
             "/api/graphql"    -> CORS(Metrics[ExampleTask](metrics)(Http4sAdapsalesDashboardInterpreter))),

In below case 1 I am getting error: org.http4s.InvalidBodyException: Received premature EOF.

request in case 1 (throws error):

{      target_market_exit_pg(  advertiser_group: ["Union xyz"])
  {  target_with_cprp { target }       

request in case 2 (working fine):

{      target_market_exit_pg(  advertiser_group: ["xyz Union"])
  {  target_with_cprp { target }       

This error seems to be appeared because of keyword "union" (only when any advertiser_group name starts with "union" and no error for case 2 when this keyword is in middle of advertiser name)

Olav Grøndal
I have a quick question. I think the Authorization(Credentials.Token(AuthScheme.Basic, s"$b2keyId:$b2key")) header should be the same as -u "$b2keyid:$b2key" in curl right?
The curl call succeeds - but the request using the header definition above fails with a 401
When I add the -v parameter to curl I see it makes a header like "Authorization: Basic <key>"
What is the difference from the above header definition in http4s?
Olav Grøndal
To answer my own question : Authorization(BasicCredentials(b2keyId, b2key)) is the thing that matches the curl call
Alexey Rykhalskiy
Hi, Folks!
I'm trying to use ScalaJS with http4s-ember-client
The part, dependent on cats/cats-effects/fs2 works well,
but ember client (seems has some JS dependencies) requires precise configuration.
I fugured out all dependencies (buffer, crypto, net, os, punycode, stream, tls)
there is no fatal compilation errors, a lot of warnings. and it doesn't work :(
Does anybody have working configuration for any http client with scalajs ?
Here is my project git@github.com:alexr007/sjs-questions.git
Velichko Anton

Hi, everyone,

I'm trying to download an octet-stream response from the remote server with the http4s blaze client, and constantly receiving the org.http4s.InvalidBodyException: Received premature EOF, while the same request with curl run without any issues. The error looks like http4s/http4s#4404, but reproduces all the time. Maybe someone knows the workaround for that?

I've also tried the okhttp client and it's responding differently compared to blaze but still unsuccessfully.
java.io.IOException: closed
  at okio.RealBufferedSource$inputStream$1.read(RealBufferedSource.kt:154)
  at java.base/java.io.InputStream.read(InputStream.java:218)
Kai Matsuda

Hi, everyone,
I'm using the EmberClientBuilder.default when creating my http4s client. When I hit my https endpoint it seems to be having issues with the underlying certificate manager?

j.l.NullPointerException: null\n\tat s.n.u.IPAddressUtil.textToNumericFormatV4(IPAddressUtil.java:49)\n\tat s.n.u.IPAddressUtil.isIPv4LiteralAddress(IPAddressUtil.java:241)\n\tat s.s.u.HostnameChecker.isIpAddress(HostnameChecker.java:125)\n\tat s.s.u.HostnameChecker.match(HostnameChecker.java:93)\n\tat s.s.s.X509TrustManagerImpl.checkIdentity(X509TrustManagerImpl.java:455)\n\tat s.s.s.X509TrustManagerImpl.checkIdentity(X509TrustManagerImpl.java:436)\n\tat s.s.s.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:252)\n\tat s.s.s.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:136)\n\tat s.s.s.ClientHandshaker.serverCertificate(ClientHandshaker.java:1626)\n\tat s.s.s.ClientHandshaker.processMessage(ClientHandshaker.java:223)\n\tat s.s.ssl.Handshaker.processLoop(Handshaker.java:1037)\n\tat s.s.ssl.Handshaker$1.run(Handshaker.java:970)\n\tat s.s.ssl.Handshaker$1.run(Handshaker.java:967)\n\tat j.s.AccessController.doPrivileged(AccessController.java)\n\tat s.s.s.Handshaker$DelegatedTask.run(Handshaker.java:1459)\n\tat f.i.n.t.SSLEngineTaskRunner$$anon$1.$anonfun$runDelegatedTasks$1(SSLEngineTaskRunner.scala:44)\n\tat s.r.j.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.scala:18)\n\tat c.e.u.WorkerThread.blockOn(WorkerThread.scala:591)\n\tat s.c.package$.blocking(package.scala:124)\n\tat cats.effect.IOFiber.runLoop(IOFiber.scala:967)\n\tat cats.effect.IOFiber.asyncContinueSuccessfulR(IOFiber.scala:1338)\n\tat cats.effect.IOFiber.run(IOFiber.scala:140)\n\tat c.e.u.WorkerThread.run(WorkerThread.scala:523)\nWrapped by: j.l.RuntimeException: Delegated task threw Exception/Error\n\tat s.s.ssl.Handshaker.checkThrown(Handshaker.java:1519)\n\tat s.s.s.SSLEngineImpl.checkTaskThrown(SSLEngineImpl.java:528)\n\tat s.s.s.SSLEngineImpl.readNetRecord(SSLEngineImpl.java:802)\n\tat s.s.s.SSLEngineImpl.unwrap(SSLEngineImpl.java:766)\n\tat j.net.ssl.SSLEngine.unwrap(SSLEngine.java:624)\n\tat f.i.n.t.TLSEngine$$anon$1.$anonfun$unwrapHandshake$1(TLSEngine.scala:250)\n\tat f.i.n.t.InputOutputBuffer$$anon$1.$anonfun$perform$3(InputOutputBuffer.scala:92)\n\tat d.i.n.t.InputOutput...\n

Seems related to this issue in jdk ssl engine?

Kai Matsuda
^ Upgrading from JDK 8 => 11 fixed the above issue. As mentioned I'm guessing it's a bug with the specific implementation of the JDK 8 version of SSLEngine