如何将Akka HTTP(使用自定义指令)迁移到HTTP4S

发布于 2025-02-09 10:11:42 字数 2812 浏览 2 评论 0原文

假设我使用akka http:

  • post方法
  • 定义此路线,如果request> request中有特定的标头我会删除它,但我会添加一个新的header 具有相同的值(就像我在request中更换标题)一样。我在这里使用自定义指令
  • 将其提取为案例类(YOMEDATA)
  • 最终在完成块中,我有一些代码,它使用request> request(带有>标题在步骤2中处理的标题

是这样的:

  val someRoute = replaceHeaders {
      post {
        extractRequest { req =>
          entity(as[SomeData]) { someData =>
            complete {
              // some code here that uses `req` (defined 3 lines above)
            }
          }
        }
      }
    }

用于替换标题我可以定义自定义指令,类似于此:

  def replaceHeaders: Directive0 =
    mapRequest(req =>
      req.headers.find(_.is(headerToReplace)) match {
          case Some(header) =>
            req
              .removeHeader(...)
              .addHeader(...(header.value()))
          case None => req
      }
    )

在内部的第一个代码中完整块我可以访问request,特别是我可以访问标题已由replace> replace> replactheaders Directive < /代码>。

如何使用http4s库进行相同的操作?因为没有像AKKA HTTP中的自定义指令。 我知道我可以创建一个函数来执行类似的操作:

  def replaceHeaders(request: Request[IO]): Headers = {
    val searchHeader = "SomeHeader"
    val newHeader = "NewHeader"

    request.headers.get(CaseInsensitiveString(searchHeader)) match {
      case Some(headerFound) =>
        request.headers
          .filterNot(_.name == CaseInsensitiveString(searchHeader))
          .put(Header(newHeader, headerFound.value))
      case None =>
        request.headers
    }
  }

  val routes: HttpRoutes[IO] = {
    val dsl = Http4sDsl[IO]
    import dsl._

    HttpRoutes.of[IO] {
      case req @ POST -> Root =>
        // replace one header for another
        val newHeaders = replaceHeaders(req)

        IO {
          Response[IO](Status.Ok)
            .withHeaders(newHeaders)
            .withEntity[String]("Process ok.")
        }

    }
  }

但是在这种情况下,我有一个新的标题的集合:val newheaders = replaceheaders(req)。 但是akka http更加灵活,当我更改标题时,这些都可以作为request> request> except> extractrequest request> request的一部分可用。 /代码>。 之后的每个块Extractrequest访问request> request时,将具有标题更新。 但是,在http4s(至少在我的代码中),我必须明确使用newheaders才能访问新的headers

如何在http4s中执行相同的操作?

Let's say I define this route using Akka Http:

  • POST method
  • If there's a specific header in the request I will remove it but I will add a new header with the same value (it is like I'm replacing a header in the request). I'm using a custom directive here.
  • Extract the body as a case class (SomeData)
  • Finally inside the complete block I have some code that uses the request (with the headers processed in step 2)

It would be something like this:

  val someRoute = replaceHeaders {
      post {
        extractRequest { req =>
          entity(as[SomeData]) { someData =>
            complete {
              // some code here that uses `req` (defined 3 lines above)
            }
          }
        }
      }
    }

For replacing headers I can define a custom directive, similar to this:

  def replaceHeaders: Directive0 =
    mapRequest(req =>
      req.headers.find(_.is(headerToReplace)) match {
          case Some(header) =>
            req
              .removeHeader(...)
              .addHeader(...(header.value()))
          case None => req
      }
    )

In the first code inside the complete block I have access to the request, in particular I have access to the headers that has been processed by replaceHeaders directive.

How can I do the same using http4s library? Because there are no customized directive as in Akka Http.
I know I can create a function to do something similar:

  def replaceHeaders(request: Request[IO]): Headers = {
    val searchHeader = "SomeHeader"
    val newHeader = "NewHeader"

    request.headers.get(CaseInsensitiveString(searchHeader)) match {
      case Some(headerFound) =>
        request.headers
          .filterNot(_.name == CaseInsensitiveString(searchHeader))
          .put(Header(newHeader, headerFound.value))
      case None =>
        request.headers
    }
  }

  val routes: HttpRoutes[IO] = {
    val dsl = Http4sDsl[IO]
    import dsl._

    HttpRoutes.of[IO] {
      case req @ POST -> Root =>
        // replace one header for another
        val newHeaders = replaceHeaders(req)

        IO {
          Response[IO](Status.Ok)
            .withHeaders(newHeaders)
            .withEntity[String]("Process ok.")
        }

    }
  }

But in this case I have a new collection of headers: val newHeaders = replaceHeaders(req).
But Akka Http is more flexible, when I make changes to the headers these are immediately available as part of the request after extractRequest. Every block after extractRequest when accessing the request will have the headers updated.
But in the case of http4s (at least in my code) I have to explicitly use newHeaders to access the new headers.

How can I do the same in http4s?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文