代码之家  ›  专栏  ›  技术社区  ›  Murray Todd Williams

如何使用akka http或alpakka访问Unix域套接字上的REST API?

  •  2
  • Murray Todd Williams  · 技术社区  · 8 年前

    我想使用/var/lib/docker.sock unix域套接字访问docker api。我看到过一些示例,您可以使用(现代版本的)curl调用API,如下所示:

    curl --unix-socket /var/run/docker.sock http:/containers/json
    

    其中rest命令用/containers/json路径表示。我很高兴看到Alpakka Unix域套接字适配器,但您似乎只能发送和接收原始字节。有什么优雅的方法可以做到这一点吗?或者我必须手动构建一个HTTP头,并手动管理所有困难的东西?

    3 回复  |  直到 8 年前
        1
  •  1
  •   dvim    8 年前
        2
  •  1
  •   jrudolph    8 年前

    akka/akka-http#2139

    val scalaV = "2.12.6"
    val akkaV = "2.5.14"
    val akkaHttpV = "10.1.3"
    
    libraryDependencies ++= Seq(
      "com.typesafe.akka" %% "akka-http" % akkaHttpV,
      "com.typesafe.akka" %% "akka-http-spray-json" % akkaHttpV,
      "com.typesafe.akka" %% "akka-stream" % akkaV,
      "com.lightbend.akka" %% "akka-stream-alpakka-unix-domain-socket" % "0.20",
    )
    

    import java.io.File
    import java.net.InetSocketAddress
    
    import akka.actor.ActorSystem
    import akka.http.scaladsl.ClientTransport
    import akka.http.scaladsl.Http
    import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport
    import akka.http.scaladsl.model.HttpRequest
    import akka.http.scaladsl.model.HttpResponse
    import akka.http.scaladsl.settings.ClientConnectionSettings
    import akka.http.scaladsl.settings.ConnectionPoolSettings
    import akka.http.scaladsl.unmarshalling.Unmarshal
    import akka.stream.ActorMaterializer
    import akka.stream.alpakka.unixdomainsocket.scaladsl.UnixDomainSocket
    import akka.stream.scaladsl.Flow
    import akka.util.ByteString
    import spray.json.JsValue
    
    import scala.concurrent.Future
    
    object DockerSockMain extends App {
      object DockerSockTransport extends ClientTransport {
        override def connectTo(host: String, port: Int, settings: ClientConnectionSettings)(implicit system: ActorSystem): Flow[ByteString, ByteString, Future[Http.OutgoingConnection]] = {
          // ignore everything for now
    
          UnixDomainSocket().outgoingConnection(new File("/var/run/docker.sock"))
            .mapMaterializedValue { _ =>
              // Seems that the UnixDomainSocket.OutgoingConnection is never completed? It works anyway if we just assume it is completed
              // instantly
              Future.successful(Http.OutgoingConnection(InetSocketAddress.createUnresolved(host, port), InetSocketAddress.createUnresolved(host, port)))
            }
        }
      }
    
      implicit val system = ActorSystem()
      implicit val mat = ActorMaterializer()
      import system.dispatcher
    
      val settings = ConnectionPoolSettings(system).withTransport(DockerSockTransport)
    
      import SprayJsonSupport._
      def handleResponse(response: HttpResponse): Future[String] =
        // TODO: create docker json model classes and directly marshal to them
        Unmarshal(response).to[JsValue].map(_.prettyPrint)
    
      Http().singleRequest(HttpRequest(uri = "http://localhost/images/json"), settings = settings)
        .flatMap(handleResponse)
        .onComplete { res =>
          println(s"Got result: [$res]")
          system.terminate()
        }
    }
    
        3
  •  0
  •   Murray Todd Williams    8 年前

    GET /v1.24/containers/json HTTP/1.1\n
    Host: localhost\n
    \n\n
    

    StackOverflow question here