akka-http - 如何使用 Akka HTTP 或 Alpakka 访问 unix 域套接字上的 REST API?

标签 akka-http alpakka

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

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

其中 REST 命令在/containers/json 路径中表示。我很高兴看到 Alpakka Unix Domain Socket 适配器,但你似乎只能发送和接收原始字节。有什么优雅的方法可以做到这一点吗?或者我是否必须手动构建 HTTP header 并手动管理所有困难的内容?

最佳答案

这是一个工作片段(另请参阅 akka/akka-http#2139 中的其余讨论):

构建.sbt:

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",
)

DockerSockMain.scala:

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()
    }
}

关于akka-http - 如何使用 Akka HTTP 或 Alpakka 访问 unix 域套接字上的 REST API?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51565935/

相关文章:

带有 Http AKKA 和案例类的 JSON 响应

scala - Spray-Json:将 None 序列化为 null

json - Akka HTTP流JSON反序列化

scala - 使用流的内容更改源中的具体化值

elasticsearch - 在 ES : index name is only evaluated on starting execution 中使用 Alpakka 索引的 Akka Streams

java - 如何减少 Alpakka 的 Kafka 日志文件大小

scala - 如何在akka-http中有条件地添加路由路径?

http2 - Akka-HTTP 可以做 HTTP/2.0 吗?

java - MongoSink 响应后提交给 kafka 消费者 - alpakka mongo 连接器

scala - 使用 alpakka-elasticsearch 客户端进行 Elasticsearch 多查询