我正在接收一個 ajax POST 請求,需要將正文資料作為 ByteBuffer 處理,并使用 Http4s (0.23.7) 以 Array[Byte] 進行回應。到目前為止,我已經能夠把事情放在一起,盡管它還沒有作業:
// http4s/fs2/cats imports...
import java.nio.ByteBuffer
import java.nio.channels.Channels
HttpRoutes.of[IO] {
case ajaxRequest@POST -> Root / "ajax" / path =>
val stream: fs2.Stream[IO, IO[Array[Byte]]] =
ajaxRequest.body
// 1. Convert body to InputStream (to enable converting to ByteBuffer)
.through(fs2.io.toInputStream)
.map { inputStream =>
// 2. Create and populate ByteBuffer
val byteBuffer = ByteBuffer.allocate(inputStream.available)
Channels.newChannel(inputStream).read(byteBuffer)
// 3. Process byteBuffer with library code
val futResult: Future[Array[Byte]] = getRpcResult(path, byteBuffer)
// 4. Convert Future to IO (?)
val ioResult: IO[Array[Byte]] = IO.fromFuture(IO(futResult))
ioResult
}
// 5. Convert stream to Response - how?
Ok(stream)
// 6. Set octet-stream content type
.map(_.withContentType(
`Content-Type`(MediaType.application.`octet-stream`, Charset.`UTF-8`)
).putHeaders(`Cache-Control`(NonEmptyList.of(`no-cache`()))))
}
一些問題:
- 使用 Http4s/fs2 是否有一些完全不同的方式來做到這一點?
- 是否有更簡單的方法將 ajaxRequest.body 轉換為 ByteBuffer(步驟 1-2)?
- 我是否需要將 Future 轉換為 IO(步驟 4)?
- 如何將流轉換為 Ok 回應(第 5 步)?
作為參考,以下是我在 Play 和 Akka-Http 中的做法:
// Play
def ajax(path: String): Action[RawBuffer] = {
Action.async(parse.raw) { implicit ajaxRequest =>
val byteBuffer = ajaxRequest.body.asBytes(parse.UNLIMITED).get.asByteBuffer
getRpcResult(path, byteBuffer).map(Ok(_))
}
}
// Akka-Http
path("ajax" / Remaining)(path =>
post {
extractRequest { req =>
req.entity match {
case HttpEntity.Strict(_, byteString) =>
complete(getRpcResult(path, byteString.asByteBuffer))
}
}
}
)
提前感謝您的任何建議!
uj5u.com熱心網友回復:
以下代碼是在我的頭頂上并按照檔案撰寫的,因為我現在無法對其進行測驗。
(因此它可能有一些錯別字/錯誤;如果您找到了,請隨時編輯答案,謝謝!)
HttpRoutes.of[IO] {
case ajaxRequest @ POST -> Root / "ajax" / path =>
val response =
ajaxRequest.as[Array[Byte]].flatMap { byteArray =>
IO.fromFuture(IO(
getRpcResult(path, ByteBuffer.wrap(byteArray))
))
}
Ok(response)
}
讓我們擴展一些事情。
- http4s支持
Array[Byte]開箱即用的讀寫,因此無需做任何有趣的事情。 - 是的,您需要將 a 轉換
Future為IO; 而你的做法是錯誤的,因為Future已經失控了。此外,如果您知道什么IO是,它解決了什么問題以及為什么http4s不使用Future; 你甚至不會問這個問題。 - 您應該將其隱藏
Future在適當的界面中。這更多是一般的設計建議,而不是特定于http4s 的建議。這不僅會使代碼更漂亮,而且會使以后更容易替換遺留模塊或在測驗中使用假實作。
無論如何,對于查看您的代碼和您提出的問題,很明顯您不熟悉型別級別堆疊,也不熟悉“程式作為值”范式。
因此,首先,我鼓勵您加入Typelevel Discord服務器,因為通過該平臺幫助您可能比在StackOverflow上更容易。
其次,我建議您問問自己為什么要使用該堆疊?是為了自學嗎?那么很好,但是,請遵循適當的學習路徑,而不是僅僅嘗試隨機代碼(畢竟,這是一種全新的編程范式);是為了作業?好的,但話又說回來,尋求支持,因為如果沒有適當的指導,您將一事無成,最終會討厭這個美妙的生態系統;是不是另有原因?再一次,考慮什么是主要驅動因素并遵循適當的計劃。
此外,您可能想看看fs2-grpc 之類的東西是否有用,這樣您就不需要在記憶體中緩沖所有請求/回應,而是以兩種方式流式傳輸所有內容。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/394691.html
