I tried the following code using http4s v0.19.0
:
import cats.effect._
def usingHttp4s(uri: String, bearerToken: String)(implicit cs: ContextShift[IO]): String = {
import scala.concurrent.ExecutionContext
import org.http4s.client.dsl.io._
import org.http4s.headers._
import org.http4s.Method._
import org.http4s._
import org.http4s.client._
import org.http4s.client.middleware._
val blockingEC = ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(5))
val middlewares = Seq(
RequestLogger[IO](logHeaders = true, logBody = true, redactHeadersWhen = _ => false)(_),
FollowRedirect[IO](maxRedirects = 5)(_)
)
val client = middlewares.foldRight(JavaNetClientBuilder(blockingEC).create[IO])(_.apply(_))
val req = GET(
Uri.unsafeFromString(uri),
Authorization(Credentials.Token(AuthScheme.Bearer, bearerToken))
)
client.expect[String](req).unsafeRunSync()
}
I get the following error:
[error] (run-main-0) org.http4s.client.UnexpectedStatus: unexpected HTTP status: 401 Unauthorized
[error] org.http4s.client.UnexpectedStatus: unexpected HTTP status: 401 Unauthorized
Not only that, my program never exited (do I have to close some client!?) and it also never printed the request even though I hooked up a logging middleware
I next tried @li-haoyi's request library and this returned no error:
def usingLiHaoyiRequest(uri: String, bearerToken: String): String =
requests.get(uri, headers = Iterable("Authorization" -> s"Bearer $bearerToken")).text()
The above code works for the same uri
and same baseToken
so it can't be that my token is wrong. To be doubly sure, I tried curl:
curl -L -H "Authorization: Bearer ${BEARER}" ${URI}
This problem also happens in http4s v0.18.19
(Even with explicit Json
and accept headers):
import io.circle.Json
def usingHttp4s(uri: String, bearerToken: String): Json = {
import org.http4s.client.dsl.io._
import org.http4s.headers._
import org.http4s.Method._
import org.http4s._
import org.http4s.client.blaze.Http1Client
import org.http4s.client.middleware._
import org.http4s.circe._
import org.http4s.MediaType._
val program = for {
c <- Http1Client[IO]()
client = FollowRedirect(maxRedirects = 5)(c)
req = GET(
Uri.unsafeFromString(uri),
Authorization(Credentials.Token(AuthScheme.Bearer, bearerToken)),
Accept(`application/json`)
)
res <- client.expect[Json](req)
} yield res
program.unsafeRunSync()
}
So my question is:
- How come both
requests
andcurl
work buthttp4s
gives me 401 for same request? - Why does my
http4s
version never exit? - Why does the request logger middleware does not log request?
As described in the gitter room, the bug is in
http4s
which does not forward authorization header to redirects but both curl and requests do (as long as forwarding is to same sub-domain).