Provide a nicer setup helper for HTTP connections
This commit is contained in:
parent
4154a3bcbc
commit
3614d09a4b
|
@ -110,8 +110,48 @@ private protocol AnyHTTPDecoder: class {
|
|||
func popRequestMethod() -> HTTPMethod?
|
||||
}
|
||||
|
||||
public extension ChannelPipeline {
|
||||
/// Configure a `ChannelPipeline` for use as a HTTP server.
|
||||
///
|
||||
/// - parameters:
|
||||
/// - first: Whether to add the HTTP server at the head of the channel pipeline,
|
||||
/// or at the tail.
|
||||
/// - returns: An `EventLoopFuture` that will fire when the pipeline is configured.
|
||||
public func addHTTPServerHandlers(first: Bool = false) -> EventLoopFuture<Void> {
|
||||
return addHandlers(HTTPResponseEncoder(), HTTPRequestDecoder(), first: first)
|
||||
}
|
||||
|
||||
/// Configure a `ChannelPipeline` for use as a HTTP client.
|
||||
///
|
||||
/// - parameters:
|
||||
/// - first: Whether to add the HTTP client at the head of the channel pipeline,
|
||||
/// or at the tail.
|
||||
/// - returns: An `EventLoopFuture` that will fire when the pipeline is configured.
|
||||
public func addHTTPClientHandlers(first: Bool = false) -> EventLoopFuture<Void> {
|
||||
return addHandlers(HTTPRequestEncoder(), HTTPResponseDecoder(), first: first)
|
||||
}
|
||||
|
||||
/// Adds the provided channel handlers to the pipeline in the order given, taking account
|
||||
/// of the behaviour of `ChannelHandler.add(first:)`.
|
||||
private func addHandlers(_ handlers: ChannelHandler..., first: Bool) -> EventLoopFuture<Void> {
|
||||
var handlers = handlers
|
||||
if first {
|
||||
handlers = handlers.reversed()
|
||||
}
|
||||
|
||||
return EventLoopFuture<Void>.andAll(handlers.map { add(handler: $0) }, eventLoop: eventLoop)
|
||||
}
|
||||
}
|
||||
|
||||
/// A `ChannelInboundHandler` used to decode HTTP requests. See the documentation
|
||||
/// on `HTTPDecoder` for more.
|
||||
///
|
||||
/// While the `HTTPRequestDecoder` does not currently have a specific ordering requirement in the
|
||||
/// `ChannelPipeline` (unlike `HTTPResponseDecoder`), it is possible that it will develop one. For
|
||||
/// that reason, applications should try to ensure that the `HTTPRequestDecoder` *later* in the
|
||||
/// `ChannelPipeline` than the `HTTPResponseEncoder`.
|
||||
///
|
||||
/// Rather than set this up manually, consider using `ChannelPipeline.addHTTPServerHandlers`.
|
||||
public final class HTTPRequestDecoder: HTTPDecoder<HTTPServerRequestPart> {
|
||||
public convenience init() {
|
||||
self.init(type: HTTPServerRequestPart.self)
|
||||
|
@ -120,6 +160,12 @@ public final class HTTPRequestDecoder: HTTPDecoder<HTTPServerRequestPart> {
|
|||
|
||||
/// A `ChannelInboundHandler` used to decode HTTP responses. See the documentation
|
||||
/// on `HTTPDecoder` for more.
|
||||
///
|
||||
/// The `HTTPResponseDecoder` must be placed later in the channel pipeline than the `HTTPRequestEncoder`,
|
||||
/// as it needs to see the outbound messages in order to keep track of what the HTTP request methods
|
||||
/// were for accurate decoding.
|
||||
///
|
||||
/// Rather than set this up manually, consider using `ChannelPipeline.addHTTPClientHandlers`.
|
||||
public final class HTTPResponseDecoder: HTTPDecoder<HTTPClientResponsePart>, ChannelOutboundHandler {
|
||||
public typealias OutboundIn = HTTPClientRequestPart
|
||||
public typealias OutboundOut = HTTPClientRequestPart
|
||||
|
|
|
@ -331,11 +331,9 @@ let bootstrap = ServerBootstrap(group: group)
|
|||
|
||||
// Set the handlers that are applied to the accepted Channels
|
||||
.handler(childHandler: ChannelInitializer(initChannel: { channel in
|
||||
return channel.pipeline.add(handler: HTTPResponseEncoder()).then(callback: { v2 in
|
||||
return channel.pipeline.add(handler: HTTPRequestDecoder()).then(callback: { v2 in
|
||||
return channel.pipeline.add(handler: HTTPHandler(htdocsPath: htdocs))
|
||||
})
|
||||
})
|
||||
return channel.pipeline.addHTTPServerHandlers().then {
|
||||
return channel.pipeline.add(handler: HTTPHandler(htdocsPath: htdocs))
|
||||
}
|
||||
}))
|
||||
|
||||
// Enable TCP_NODELAY and SO_REUSEADDR for the accepted Channels
|
||||
|
|
|
@ -341,10 +341,8 @@ class HTTPServerClientTest : XCTestCase {
|
|||
// Set the handlers that are appled to the accepted Channels
|
||||
.handler(childHandler: ChannelInitializer(initChannel: { channel in
|
||||
// Ensure we not read faster then we can write by adding the BackPressureHandler into the pipeline.
|
||||
channel.pipeline.add(handler: HTTPRequestDecoder()).then {
|
||||
channel.pipeline.add(handler: HTTPResponseEncoder()).then {
|
||||
channel.pipeline.add(handler: httpHandler)
|
||||
}
|
||||
channel.pipeline.addHTTPServerHandlers().then {
|
||||
channel.pipeline.add(handler: httpHandler)
|
||||
}
|
||||
})).bind(to: "127.0.0.1", on: 0).wait()
|
||||
|
||||
|
@ -354,10 +352,8 @@ class HTTPServerClientTest : XCTestCase {
|
|||
|
||||
let clientChannel = try ClientBootstrap(group: group)
|
||||
.handler(handler: ChannelInitializer(initChannel: { channel in
|
||||
channel.pipeline.add(handler: HTTPRequestEncoder()).then {
|
||||
channel.pipeline.add(handler: HTTPResponseDecoder()).then {
|
||||
channel.pipeline.add(handler: accumulation)
|
||||
}
|
||||
channel.pipeline.addHTTPClientHandlers().then {
|
||||
channel.pipeline.add(handler: accumulation)
|
||||
}
|
||||
}))
|
||||
.connect(to: serverChannel.localAddress!)
|
||||
|
@ -403,10 +399,8 @@ class HTTPServerClientTest : XCTestCase {
|
|||
// Set the handlers that are appled to the accepted Channels
|
||||
.handler(childHandler: ChannelInitializer(initChannel: { channel in
|
||||
// Ensure we not read faster then we can write by adding the BackPressureHandler into the pipeline.
|
||||
channel.pipeline.add(handler: HTTPRequestDecoder()).then {
|
||||
channel.pipeline.add(handler: HTTPResponseEncoder()).then {
|
||||
channel.pipeline.add(handler: httpHandler)
|
||||
}
|
||||
channel.pipeline.addHTTPServerHandlers().then {
|
||||
channel.pipeline.add(handler: httpHandler)
|
||||
}
|
||||
})).bind(to: "127.0.0.1", on: 0).wait()
|
||||
|
||||
|
@ -416,10 +410,8 @@ class HTTPServerClientTest : XCTestCase {
|
|||
|
||||
let clientChannel = try ClientBootstrap(group: group)
|
||||
.handler(handler: ChannelInitializer(initChannel: { channel in
|
||||
channel.pipeline.add(handler: HTTPRequestEncoder()).then {
|
||||
channel.pipeline.add(handler: HTTPResponseDecoder()).then {
|
||||
channel.pipeline.add(handler: accumulation)
|
||||
}
|
||||
channel.pipeline.addHTTPClientHandlers().then {
|
||||
channel.pipeline.add(handler: accumulation)
|
||||
}
|
||||
}))
|
||||
.connect(to: serverChannel.localAddress!)
|
||||
|
@ -465,10 +457,8 @@ class HTTPServerClientTest : XCTestCase {
|
|||
let serverChannel = try ServerBootstrap(group: group)
|
||||
.option(option: ChannelOptions.Socket(SocketOptionLevel(SOL_SOCKET), SO_REUSEADDR), value: 1)
|
||||
.handler(childHandler: ChannelInitializer(initChannel: { channel in
|
||||
channel.pipeline.add(handler: HTTPRequestDecoder()).then {
|
||||
channel.pipeline.add(handler: HTTPResponseEncoder()).then {
|
||||
channel.pipeline.add(handler: httpHandler)
|
||||
}
|
||||
channel.pipeline.addHTTPServerHandlers().then {
|
||||
channel.pipeline.add(handler: httpHandler)
|
||||
}
|
||||
})).bind(to: "127.0.0.1", on: 0).wait()
|
||||
|
||||
|
@ -478,10 +468,8 @@ class HTTPServerClientTest : XCTestCase {
|
|||
|
||||
let clientChannel = try ClientBootstrap(group: group)
|
||||
.handler(handler: ChannelInitializer(initChannel: { channel in
|
||||
channel.pipeline.add(handler: HTTPRequestEncoder()).then {
|
||||
channel.pipeline.add(handler: HTTPResponseDecoder()).then {
|
||||
channel.pipeline.add(handler: accumulation)
|
||||
}
|
||||
channel.pipeline.addHTTPClientHandlers().then {
|
||||
channel.pipeline.add(handler: accumulation)
|
||||
}
|
||||
}))
|
||||
.connect(to: serverChannel.localAddress!)
|
||||
|
@ -529,10 +517,8 @@ class HTTPServerClientTest : XCTestCase {
|
|||
// Set the handlers that are appled to the accepted Channels
|
||||
.handler(childHandler: ChannelInitializer(initChannel: { channel in
|
||||
// Ensure we not read faster then we can write by adding the BackPressureHandler into the pipeline.
|
||||
channel.pipeline.add(handler: HTTPRequestDecoder()).then {
|
||||
channel.pipeline.add(handler: HTTPResponseEncoder()).then {
|
||||
channel.pipeline.add(handler: httpHandler)
|
||||
}
|
||||
channel.pipeline.addHTTPServerHandlers().then {
|
||||
channel.pipeline.add(handler: httpHandler)
|
||||
}
|
||||
})).bind(to: "127.0.0.1", on: 0).wait()
|
||||
|
||||
|
@ -573,10 +559,8 @@ class HTTPServerClientTest : XCTestCase {
|
|||
let serverChannel = try ServerBootstrap(group: group)
|
||||
.option(option: ChannelOptions.Socket(SocketOptionLevel(SOL_SOCKET), SO_REUSEADDR), value: 1)
|
||||
.handler(childHandler: ChannelInitializer(initChannel: { channel in
|
||||
channel.pipeline.add(handler: HTTPRequestDecoder()).then {
|
||||
channel.pipeline.add(handler: HTTPResponseEncoder()).then {
|
||||
channel.pipeline.add(handler: httpHandler)
|
||||
}
|
||||
channel.pipeline.addHTTPServerHandlers().then {
|
||||
channel.pipeline.add(handler: httpHandler)
|
||||
}
|
||||
})).bind(to: "127.0.0.1", on: 0).wait()
|
||||
defer {
|
||||
|
@ -585,10 +569,8 @@ class HTTPServerClientTest : XCTestCase {
|
|||
|
||||
let clientChannel = try ClientBootstrap(group: group)
|
||||
.handler(handler: ChannelInitializer(initChannel: { channel in
|
||||
channel.pipeline.add(handler: HTTPRequestEncoder()).then {
|
||||
channel.pipeline.add(handler: HTTPResponseDecoder()).then {
|
||||
channel.pipeline.add(handler: accumulation)
|
||||
}
|
||||
channel.pipeline.addHTTPClientHandlers().then {
|
||||
channel.pipeline.add(handler: accumulation)
|
||||
}
|
||||
}))
|
||||
.connect(to: serverChannel.localAddress!)
|
||||
|
@ -622,10 +604,8 @@ class HTTPServerClientTest : XCTestCase {
|
|||
let serverChannel = try ServerBootstrap(group: group)
|
||||
.option(option: ChannelOptions.Socket(SocketOptionLevel(SOL_SOCKET), SO_REUSEADDR), value: 1)
|
||||
.handler(childHandler: ChannelInitializer(initChannel: { channel in
|
||||
channel.pipeline.add(handler: HTTPRequestDecoder()).then {
|
||||
channel.pipeline.add(handler: HTTPResponseEncoder()).then {
|
||||
channel.pipeline.add(handler: httpHandler)
|
||||
}
|
||||
channel.pipeline.addHTTPServerHandlers().then {
|
||||
channel.pipeline.add(handler: httpHandler)
|
||||
}
|
||||
})).bind(to: "127.0.0.1", on: 0).wait()
|
||||
defer {
|
||||
|
@ -634,10 +614,8 @@ class HTTPServerClientTest : XCTestCase {
|
|||
|
||||
let clientChannel = try ClientBootstrap(group: group)
|
||||
.handler(handler: ChannelInitializer(initChannel: { channel in
|
||||
channel.pipeline.add(handler: HTTPRequestEncoder()).then {
|
||||
channel.pipeline.add(handler: HTTPResponseDecoder()).then {
|
||||
channel.pipeline.add(handler: accumulation)
|
||||
}
|
||||
channel.pipeline.addHTTPClientHandlers().then {
|
||||
channel.pipeline.add(handler: accumulation)
|
||||
}
|
||||
}))
|
||||
.connect(to: serverChannel.localAddress!)
|
||||
|
|
|
@ -31,11 +31,9 @@ private func serverHTTPChannel(group: EventLoopGroup, handlers: [ChannelHandler]
|
|||
return try! ServerBootstrap(group: group)
|
||||
.option(option: ChannelOptions.Socket(SocketOptionLevel(SOL_SOCKET), SO_REUSEADDR), value: 1)
|
||||
.handler(childHandler: ChannelInitializer(initChannel: { channel in
|
||||
channel.pipeline.add(handler: HTTPRequestDecoder()).then {
|
||||
channel.pipeline.add(handler: HTTPResponseEncoder()).then {
|
||||
let futureResults = handlers.map { channel.pipeline.add(handler: $0) }
|
||||
return EventLoopFuture<Void>.andAll(futureResults, eventLoop: channel.eventLoop)
|
||||
}
|
||||
channel.pipeline.addHTTPServerHandlers().then {
|
||||
let futureResults = handlers.map { channel.pipeline.add(handler: $0) }
|
||||
return EventLoopFuture<Void>.andAll(futureResults, eventLoop: channel.eventLoop)
|
||||
}
|
||||
})).bind(to: "127.0.0.1", on: 0).wait()
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue