我想记录我的应用程序发出的所有请求。该应用程序进行了多次调用,如下所示:
val client: Client = org.http4s.client.blaze.SimpleHttp1Client(...)
client.fetch(Request(method = GET, uri = aUri))
Run Code Online (Sandbox Code Playgroud)
有没有办法让客户端将所有请求都记录到文件中?
(使用 v0.12.4)
我正在尝试定义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.JsonInput从req.body或req.bodyAsText?
我知道,json4s也有StringInput和StreamInput从继承JsonInput的使用String和InputStream,所以我认为我需要转换req.body到InputStream或req.bodyAsText至String,但我还是不明白如何。
我是 Scala 的新手,我还没有完全理解一些概念,例如scalaz.stream.Process.
这个想法是能够对路由器服务上的 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) 所以我不是 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) 扩展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但是我无法弄清楚如何适应它。
我有一个使用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) 每当我在 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) 我尝试使用以下代码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) 使用 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 没有表单数据
谢谢
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 与所有不同端点/请求的复杂性,我希望找到一种将给定案例类编码为表单的方法。最好的方法是什么?
我努力了:
显式指定Content-Type但这不起作用,因为继承类型优先
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)
这里的问题是 …
http4s ×10
scala ×9
cats-effect ×2
http4s-circe ×2
scala-cats ×2
circe ×1
curl ×1
fs2 ×1
http-post ×1
openapi ×1
swagger ×1
swagger-2.0 ×1
unit-testing ×1
websocket ×1