簡體   English   中英

如何使 akka-http 將 GET 請求轉發到 POST 請求並更改屬性?

[英]How to make akka-http to forward a GET request to a POST request and change attributes?

我正在使用 akka-http 處理獲取請求,並且我想轉發到同一主機但更改以下參數:

  • 將 GET 轉換為 POST
  • 將端口從8080更改為8081
  • 擦除參數並發送 JSON。 我已經創建了要發送的 JSON 值。

我查閱了這個頁面和這個答案 我正在使用extract(_.request) { request => ,然后使用StatusCodes.MovedPermanently創建redirect(

val routes: Route = {
    get {
      (path(IntNumber) & parameterSeq) { (adId: Int, params: Seq[(String, String)]) =>
        // handling requests as: "http://localhost:8080/2?c=5&b=2", make sure to use the request between quotes
        println(s"The ad ID: $adId contains the parameters: ${params.map(paramString).mkString(", ")}")

        val bid = getBid(adId, params)
        println(s"bid request: ${bid.toJson.prettyPrint}")

        // HOW TO REDIRECT TO ANOTHER PORT, CHANGE THE METHOD FROM GET TO POST, AND SEND A JSON PAYLOAD?
        val newRequest = HttpRequest(
          HttpMethods.POST,
          uri = "/",
          entity = HttpEntity(ContentTypes.`application/json`, bid.toJson.toString)
        )

        redirect(
          newRequest
            .uri
            .withHost("localhost")
            .withPort(8082),
          StatusCodes.MovedPermanently
        )
        // complete(StatusCodes.OK)

      } ~ pathEndOrSingleSlash {
        complete(StatusCodes.BadRequest)
      } ~ {
        complete(StatusCodes.Forbidden)
      }
    }
  }

但是,當我向 akka-http 應用程序發送 get $ http GET "localhost:8080/3?b=5&c=10&d=19&c=10"時,端口8082上的服務器沒有響應。

$ http GET "localhost:8080/3?b=5&c=10&d=19&c=10"
HTTP/1.1 301 Moved Permanently
Content-Length: 92
Content-Type: text/html; charset=UTF-8
Date: Fri, 19 Feb 2021 15:49:21 GMT
Location: //localhost:8082/
Server: akka-http/10.2.2

This and all future requests should be directed to <a href="//localhost:8082/">this URI</a>.

要測試服務器是否正常工作,我可以發送POST請求並收到答案:

$ http POST localhost:8082 < src/main/resources/bidders-request-10.json 
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Date: Fri, 19 Feb 2021 15:51:02 GMT
Server: Apache-Coyote/1.1
Transfer-Encoding: chunked

{
    "bid": 0,
    "content": "b:$price$",
    "id": "10"
}

所以,我通過創建一個執行Http().singleRequest(HttpRequest(uri = "https://akka.io"))的參與者來解決這個例子 我擁有的工作解決方案是:

import akka.actor.{Actor, ActorLogging, ActorSystem, Props}
import akka.http.scaladsl.Http
import akka.http.scaladsl.model._
import akka.util.ByteString
import spray.json._
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport

object MyselfClient {
  def main(args: Array[String]): Unit = {
    val system = ActorSystem("AuctionClientSystem")
    val auctionClientActor = system.actorOf(Props[AuctionClientActor], "auctionClientActor")
    auctionClientActor ! BidRequest(1, Bid(2, List(("c", "5"), ("b", "2"))))
  }
}

case class BidRequest(requestId: Int, bid: Bid)

class AuctionClientActor extends Actor with ActorLogging
      with BidJsonProtocol with SprayJsonSupport {

  import akka.pattern.pipe
  import context.dispatcher

  implicit val system = context.system
  val http = Http(system)

  def receive = {
    case bidRequest@BidRequest(requestId, bid) =>
      println(s"received bid request: $bidRequest")
      val content = bidRequest.bid.toJson.toString
        .replace("[[", "{")
        .replace("]]", "}")
        .replace("\",\"", "\": \"")
        .replace("[", "")
        .replace("]", "")
      println(content)
      // create the request
      val httpRequest = HttpRequest(
        HttpMethods.POST,
        uri = Uri("http://localhost:8081"),
        entity = HttpEntity(
          ContentTypes.`application/json`,
          content
          // """{"id": 10, "attributes" : { "a": "1", "b": "0" }}""".stripMargin
        )
      )
      // send the request
      http.singleRequest(httpRequest).pipeTo(self)
    case HttpResponse(StatusCodes.OK, headers, entity, _) =>
      entity.dataBytes.runFold(ByteString(""))(_ ++ _).foreach { body =>
        println("Got response, body: " + body.utf8String)
      }
    case resp@HttpResponse(code, _, _, _) =>
      println("Request failed, response code: " + code)
      resp.discardEntityBytes()
  }
}

我只是不知道如何使 Spray JSON 不使用[] 然后我正在使用.replace("[[", "{")進行那個討厭的對話。 但是,該解決方案已經奏效。 噴霧 JSON 我正在尋找一種更好的轉換方法。 我想還有另一種形式可以創建沒有[]的案例 class 。

import spray.json._

case class Bid(id: Int, attributes: List[(String, String)])

trait BidJsonProtocol extends DefaultJsonProtocol {
  implicit val bidFormat = jsonFormat2(Bid)
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM