问题描述
我正在使用 akka-http 处理 get 请求,我想转发到同一台主机,但更改以下参数:
- 将 GET 转换为 POST
- 将端口从
8080
更改为8081
- 擦除参数并发送 JSON。我已经创建了要发送的 JSON 值。
我咨询了这个 page 和这个 answer。我正在使用 extract(_.request) { request =>
提取请求,然后使用 redirect(
创建一个 StatusCodes.MovedPermanently
。
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 应用程序 $ http GET "localhost:8080/3?b=5&c=10&d=19&c=10"
发送 get 时,端口 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"))
之类的角色来解决 this example。我的工作解决方案是:
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("[[","{")
进行令人讨厌的对话。但是,该解决方案已经在起作用。我正在寻找一种更好的方法来转换它。我想还有另一种形式可以创建没有 [
和 ]
的案例类。
import spray.json._
case class Bid(id: Int,attributes: List[(String,String)])
trait BidJsonProtocol extends DefaultJsonProtocol {
implicit val bidFormat = jsonFormat2(Bid)
}