この前の土日に Swift-NIO を使って HTTP Client を書いてみたが、うまく動かなかった。
Bootstrap
基本的には Netty と同じ。 ClientBootstrap
のイニシャライザーを呼び出して、 EventLoopGroup
と ChannelOption
と ChannelInitializer
(Channel -> EventLoopFuture
のこと)を渡して、 connect(host:port:)
すればつながるはず。
import NIO let eventLoopGroup = MultiTHreadedEventLoopGroup(numberOfThreads: 1) let bootstrap = ClientBootstrap(group:eventLoopGroup) .channelOption(ChannelOptions.socket(SocketOptionLevel(SOL_SOCKET), SO_REUSEADDR), value: 1) .channelInitializer(channelInitializer()) let future = bootstrap.connect(host: "api.github.com", port: 443) future.then { channel in var httpHeadPart = HTTPRequestHead(version: HTTPVersion(major:1, minor: 1), method: HTTPMethod.GET, uri: "http://api.github.com/search/repositories?q=swift&per_page=3") httpHeadPart.headers = HTTPHeaders([ ("Host", "api.github.com"), ("Connection", "close"), ("Accept-Encoding", "gzip"), ("User-Agent", "Swift-NIO"), ("Accept", "application/json") ]) return channel.writeAndFlush(HTTPClientRequestPart.head(httpRequestPart)) }
ChannelInitializer
ここもわりとすんなり書けた。
Netty の HttpObjectAggregator
に該当するものがないようにも思われるが、 ユーザーコードが受け取るのは HTTPClientResponsePart
(= HTTPPart<HTTPResponseHead, ByteBuffer>
) となる模様。型からすると、レスポンスが集約されているように思われる。
func channelInitializer() -> (Channel) -> EventLoopFuture<Swift.Void> { return { channel in let pipeline = channel.pipeline let sslHandler = try! OpenSSLClientHandler(context: sslContext) _ = pipeline.add(handler: sslHandler, first: true) _ = pipeline.addHTTPClientHandlers() return pipeline.add(handler: MyClientHandler(), first: false) } }
これでいけるはずだと思っていたが、実際には TLS のところで unableToValiadteCertificate
Error
が発生してしまって、何もできない…