【问题标题】:Forwarding HTTP/REST Request to another REST server in Spray在 Spray 中将 HTTP/REST 请求转发到另一个 REST 服务器
【发布时间】:2015-01-17 00:13:25
【问题描述】:

我有一堆现有的 REST 服务(下面的 #1 和 #2)在仅在内部使用的不同端点上运行。现在我想使用 Spray 在外部公开其中一些 REST API(API-1 和 API-2),因为这个外部端点还将提供一些额外的 API(API-3、API-4)。

是否有一种简单/推荐的方法可以将外部 REST 请求转发到我的新端点到现有 REST 端点?

【问题讨论】:

  • 不是 100% 我理解这个问题 - 但如果你只是想要简单的转发,为什么不把 Apache 或一些网络服务器放在前面,让它通过代理通行证呢?反向代理/负载均衡器在路由流量方面可能比喷雾服务器做得更好。
  • 如果我只想要路由,我可以这样做。但是,我需要在 new REST 服务中提供一些额外的 API(API-3、API-4),并将调用包装到 existing API(API-1 , API-2)。
  • 您仍然可以使用 nginx/apache 之类的东西来支持您的场景,而无需在 scala 代码中进行代理。您可以在 webserver 配置中设置规则以支持仅代理某些 url(API 1 和 2),然后让其余的(3 和 4)落入您的底层喷雾服务器。我们用 nginx 做这件事。
  • @cmbaxter - 这很有帮助。如果可能的话,你能给我一些开始配置 nginx 的地方吗?
  • 这里是 proxy_pass 指令的文档。应作为起点。 nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass

标签: scala rest http akka spray


【解决方案1】:

听起来你想要的是建议的proxyTo 指令:

path("foo") {
  get {
    proxyTo("http://oldapi.example.com")
  }
}

(或者,更有可能是proxyToUnmatchedPath)。有一个问题悬而未决:

https://github.com/spray/spray/issues/145

看起来有人一直在研究这个;这是喷雾叉中的提交:

https://github.com/bthuillier/spray/commit/d31fc1b5e1415e1b908fe7d1f01f364a727e2593

但提交似乎尚未在主 Spray 存储库中。您可以在问题页面上询问其状态。

另外,这里有一篇来自 CakeSolutions 的博客文章,介绍了如何手动进行代理:

http://www.cakesolutions.net/teamblogs/http-proxy-with-spray

该页面上的一条评论指出,Spray 有一个名为 ProxySettings 的未记录的东西,并指向以下测试:

https://github.com/spray/spray/blob/master/spray-can-tests/src/test/scala/spray/can/client/ProxySpec.scala

更新; Soumya 已在 Spray 用户 Google 群组上向 Spray 团队询问了此事:

https://groups.google.com/forum/#!topic/spray-user/MlUn-y4X8RE

【讨论】:

    【解决方案2】:

    CakeSolution blog 的帮助下,我能够代理一个单一 服务。在以下示例中,代理在 http://localhost:20000 上运行,而实际 REST 端点在 http://localhost:7001 上运行。

    不确定如何使用这种方法代理多个服务。

    我喜欢@cmbaxter 使用 Nginx 作为代理的解决方案,但我仍然很好奇是否有办法扩展以下方法以在 Spray 中执行此操作。

    import akka.actor.{ActorRef, Props}
    import akka.io.IO
    import akka.util.Timeout
    import spray.can.Http
    import spray.can.Http.ClientConnectionType
    import spray.http.HttpResponse
    import spray.routing.{RequestContext, HttpServiceActor, Route}
    
    
    import scala.concurrent.duration._
    import akka.pattern.ask
    
    
    object ProxyRESTService {
    
       def main(args: Array[String]) {
    
       //create an actor system
       implicit val actorSystem = akka.actor.ActorSystem("proxy-actor-system")
       implicit val timeout: Timeout = Timeout(5 seconds)
       implicit val dis = actorSystem.dispatcher
    
       //host on which proxy is running
       val proxyHost = "localhost"
       //port on which proxy is listening
       val proxyPort = 20000
    
      //host where REST service is running
      val restServiceHost = "localhost"
      //port where REST service is running
      val restServicePort = 7001
    
      val setup = Http.HostConnectorSetup(
       proxyHost,
       proxyPort,
       connectionType = ClientConnectionType.Proxied(restServiceHost,   restServicePort)
    )
    
    IO(Http)(actorSystem).ask(setup).map {
      case Http.HostConnectorInfo(connector, _) =>
        val service = actorSystem.actorOf(Props(new ProxyService(connector)))
        IO(Http) ! Http.Bind(service, proxyHost, port = proxyPort)
    }
    }
    
    }
    

    .

    class ProxyService(connector: ActorRef) extends HttpServiceActor  {
      implicit val timeout: Timeout = Timeout(5 seconds)
      implicit def executionContext = actorRefFactory.dispatcher
      val route: Route = (ctx: RequestContext) => ctx.complete(connector.ask(ctx.request).mapTo[HttpResponse])
      def receive: Receive = runRoute(route)
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-12-14
      • 1970-01-01
      • 2022-10-23
      • 2020-01-08
      • 1970-01-01
      • 2017-05-07
      • 2012-06-07
      相关资源
      最近更新 更多