标签: http4s

如何记录对 http4s 客户端的所有请求

我想记录我的应用程序发出的所有请求。该应用程序进行了多次调用,如下所示:

val client: Client = org.http4s.client.blaze.SimpleHttp1Client(...)
client.fetch(Request(method = GET, uri = aUri))
Run Code Online (Sandbox Code Playgroud)

有没有办法让客户端将所有请求都记录到文件中?

(使用 v0.12.4)

scala http4s

10
推荐指数
1
解决办法
2397
查看次数

http4s - 以 String 或 InputStream 形式获取请求正文

我正在尝试定义HttpService接收 json 并将其解析为带有json4s库的案例类:

import org.http4s._
import org.http4s.dsl._
import org.json4s._
import org.json4s.native.JsonMethods._

case class Request(firstName: String, secondName: String)

HttpService {
  case req @ POST -> Root =>
    val request = parse(<map req.body or req.bodyAsText to JsonInput>).extract[Request]
    Ok()
}
Run Code Online (Sandbox Code Playgroud)

我怎样才能org.json4s.JsonInputreq.bodyreq.bodyAsText

我知道,json4s也有StringInputStreamInput从继承JsonInput的使用StringInputStream,所以我认为我需要转换req.bodyInputStreamreq.bodyAsTextString,但我还是不明白如何。

我是 Scala 的新手,我还没有完全理解一些概念,例如scalaz.stream.Process.

scala scalaz-stream http4s

7
推荐指数
2
解决办法
5713
查看次数

单元测试 http4s 路由器 websocket 端点

这个想法是能够对路由器服务上的 websocket 端点进行单元测试。任何其他类型的端点都可以很容易地使用 a 进行测试Request,但我无法找出一种轻松测试 websocket 响应的方法,因为使用 a 击中端点Request会给您一个 501 错误,因为您没有任何相应的套接字握手。

这是我正在使用的路由器

def router(averages: IO[SomeAverages]): HttpRoutes[F] =
    HttpRoutes.of[F] {
        case GET -> Root =>
            val toClient: Stream[F, WebSocketFrame] = {
                Stream
                  .awakeEvery[F](5.seconds)
                  .map(_ => {
                      val avg = averages.unsafeRunSync
                      WebSocketFrame.Text(avg.toString)
                  })
            }
            val fromClient: Pipe[F, WebSocketFrame, Unit] = _.evalMap {
                case WebSocketFrame.Text(t, _) => F.delay(println(t))
                case f => F.delay(println(s"Unknown type: $f"))
            }
            WebSocketBuilder[F].build(toClient, fromClient)
    }
Run Code Online (Sandbox Code Playgroud)

这个想法是让类似于下面的代码的东西与 websockets 一起工作

val server = Server.initServer[IO]
val router = server.router …
Run Code Online (Sandbox Code Playgroud)

unit-testing scala websocket scala-cats http4s

7
推荐指数
0
解决办法
300
查看次数

从 Scala 源代码 (http4s) 生成 Swagger/OpenAPI 规范

所以我不是 swagger 专家,但所有使用 swagger 的系统都要求您拥有 JSON 或 YAML 中的 swagger 规范来定义 API 的所有端点(等)。

我的问题是:有没有办法根据实际的源代码生成这些规范文件?我在问,因为当您开始添加属性或返回略有不同的结果时,似乎很难保持端点代码和文档同步。

所以当我有这个代码时(使用 http4s 和 RhoService):

object HelloWorld {
  val service = new RhoService {
    GET / "hello" / 'name |>> { name: String =>
      Ok(Json.obj("message" -> Json.fromString(s"Hello, ${name}")))
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

如果它可以产生(以某种方式:)

/hello/{name}:
    get:
      tags:
      - "HelloWorld"
      summary: ""
      description: ""
      operationId: "getHellobyName"
      produces:         
      - "application/json"
      parameters:
      - name: "name"
        in: "path"
        description: ""
        required: true
        type: "string"
      responses:
        200:
          description: "successful operation"
          schema:
            $ref: "#/definitions/Hello"           
      security: …
Run Code Online (Sandbox Code Playgroud)

swagger swagger-2.0 openapi http4s

6
推荐指数
2
解决办法
2536
查看次数

如何以编程方式关闭fs2.StreamApp?

扩展StreamApp要求您提供定义stream。它有一个requestShutdown参数。

def stream(args: List[String], requestShutdown: F[Unit]): Stream[F, ExitCode]

我为此提供了实现,并理解args了作为命令行参数传入的实现。但是,我不确定是什么提供了该requestShutdown参数以及我可以使用它做什么。

具体来说,我想在Stream[IO, ExitCode]启动Http4s服务器(永久阻止)的上调用正常关机。

看起来Signal是必需的,必须设置吗?我试图“了解”的基础流如下所示:

for {
   scheduler <- Scheduler[IO](corePoolSize = 1)
   exitCode  <- BlazeBuilder[IO]
                    .bindHttp(port, "0.0.0.0")
                    .mountService(services(scheduler), "/")
                    .serve
    } yield exitCode
Run Code Online (Sandbox Code Playgroud)

我的streamdef在这里,并且StreamAppSpec来自fs2项目中有一些内容,StreamAppSpec但是我无法弄清楚如何适应它。

scala http4s fs2

6
推荐指数
1
解决办法
715
查看次数

在 http4s 版本 19.0.0 中找不到 ContextShift[cats.effect.IO] 的隐式值

我有一个使用ciris进行配置管理的 http4s 项目。

该项目是在GitHub上这里

libraryDependencies ++= Seq(
  "is.cir" %% "ciris-cats",
  "is.cir" %% "ciris-cats-effect",
  "is.cir" %% "ciris-core",
  "is.cir" %% "ciris-enumeratum",
  "is.cir" %% "ciris-refined"
).map(_ % "0.12.1")

libraryDependencies ++= Seq(
  "org.http4s" %% "http4s-dsl",
  "org.http4s" %% "http4s-blaze-server"
).map(_ % "0.18.18")

libraryDependencies ++= Seq(
  "com.ovoenergy" %% "ciris-kubernetes" % "0.5",
  "org.typelevel" %% "kittens" % "1.2.0",
  "eu.timepit" %% "refined-cats" % "0.9.3"
)
Run Code Online (Sandbox Code Playgroud)

当我编译我的项目时,这里出现以下错误

    [info] Compiling 12 Scala sources to /Users/rajkumar.natarajan/Documents/Coding/OS/ciris-example/target/scala-2.12/classes ...
    [error] /Users/rajkumar.natarajan/Documents/Coding/OS/ciris-example/src/main/scala/is/cir/example/application/Http4sApi.scala:24:68: Cannot find an implicit value for ContextShift[cats.effect.IO]: …
Run Code Online (Sandbox Code Playgroud)

scala scala-cats http4s cats-effect

6
推荐指数
1
解决办法
4233
查看次数

如何在 Http4s 中添加自定义错误响应?

每当我在 http4s 应用程序中遇到未知路由时,它都会返回 404 错误页面,内容类型为:text/plain和正文:

未找到

如何强制它始终以Content-Type: application/json 的形式将 body 返回为 JSON ?

{“未找到信息”}

我发现当我组装httpApp 时,我可以映射它并“调整”响应:

val httpApp = Router.publicRoutes[F].orNotFound.map(ErrorTranslator.handle)
Run Code Online (Sandbox Code Playgroud)

其中ErrorTranslator仅检测带有客户端错误状态代码和不是application/json 的Content-Type 的响应,然后将 body 包装到 JSON 中:

object ErrorTranslator {

  val ContentType = "Content-Type"
  val ApplicationJson = "application/json"

  private def translate[F[_]: ConcurrentEffect: Sync](r: Response[F]): Response[F] =
    r.headers.get(CaseInsensitiveString(ContentType)).map(_.value) match {
      case Some(ApplicationJson) => r
      case _                     => r.withEntity(r.bodyAsText.map(ErrorView(_))) //wrap reponse body into enity
    }

  def handle[F[_]: ConcurrentEffect: Sync]: PartialFunction[Response[F], Response[F]] …
Run Code Online (Sandbox Code Playgroud)

scala http4s

6
推荐指数
1
解决办法
709
查看次数

Scala:http4s给予401 Unauthorized相同的请求,可以在curl/requests中使用

我尝试使用以下代码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()
  }
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

[error] (run-main-0) org.http4s.client.UnexpectedStatus: unexpected HTTP status: 401 Unauthorized
[error] org.http4s.client.UnexpectedStatus: unexpected HTTP …
Run Code Online (Sandbox Code Playgroud)

curl scala http4s http4s-circe cats-effect

5
推荐指数
1
解决办法
520
查看次数

org.http4s.client 带有标题和 UriForm 的帖子

使用 org.http4s.client 无法找到如何将标头和 UriForm 与 Post 请求一起发送。

import org.http4s.client.dsl.io._
import org.http4s.Method._

val lstHeader: List[Header] = List(
  Header("Accept", "application/json")
  , Header("Accept-Charset", "utf-8")
  , Header("Accept-Encoding", "gzip")
)

val formData :UrlForm = UrlForm(
  "username" -> "user",
  "enc_password" -> "password",
  "queryParams" -> "{}",
  "optIntoOneTap" -> "false"
)

val req1 = POST(
  formData,
  uri"https://www.instagram.com/accounts/login/ajax/"
)

val req2: Request[IO] = Request[IO](
  Method.POST,
  uri"https://www.instagram.com/accounts/login/ajax/",
  HttpVersion.`HTTP/2.0`,
  Headers(lstHeader)
)
Run Code Online (Sandbox Code Playgroud)

req1 没有我的标题 req2 没有表单数据

谢谢

scala http-post http4s

5
推荐指数
1
解决办法
1555
查看次数

Http4s Client Encode Entity as x-www-form-urlencoded Recursively

I have a request like the following

val request =
    Request[IO](
      method = POST,
      uri = Uri.uri("..."),
      headers = Headers(
        Authorization(BasicCredentials("...", "..."))
      )
    )
    .withEntity(PaymentIntentRequest2(2000, "usd"))
Run Code Online (Sandbox Code Playgroud)

我正在查看源代码,看起来它withEntity继承了嵌套的标头EntityDecoder,因此上面的代码默认为Content-Type: application/json. 好像我明确地传递UrlForm一切都很好。

不幸的是,我所点击的 API 预期数据为,x-www-form-urlencoded并且考虑到目标 API 与所有不同端点/请求的复杂性,我希望找到一种将给定案例类编码为表单的方法。最好的方法是什么?

我努力了:

  1. 显式指定Content-Type但这不起作用,因为继承类型优先

  2. Product构建从到 的隐式泛型转换UrlForm(目前是扩展方法)

implicit class UrlFormEncode[+B <: Product](val u: B) {
    def asUrlForm: UrlForm =
      u.productElementNames
        .zip(u.productIterator)
        .foldLeft(UrlForm()) { (a, b) =>
          a.combine(UrlForm(b._1 -> b._2.toString))
        }
}
Run Code Online (Sandbox Code Playgroud)

这里的问题是 …

scala circe http4s http4s-circe

5
推荐指数
1
解决办法
1211
查看次数