@@ -156,115 +156,161 @@ public final class Server<RequestHandler: HTTPServerRequestHandler> {
156156 configuration: HTTPServerConfiguration ,
157157 handler: RequestHandler
158158 ) async throws {
159- let serverChannel = try await Self . bind ( bindTarget: configuration. bindTarget) {
160- ( channel) -> EventLoopFuture <
161- EventLoopFuture <
162- NIONegotiatedHTTPVersion <
163- NIOAsyncChannel < HTTPRequestPart , HTTPResponsePart > ,
164- (
165- Void ,
166- NIOHTTP2Handler . AsyncStreamMultiplexer < NIOAsyncChannel < HTTPRequestPart , HTTPResponsePart > >
159+ switch configuration. tlSConfiguration. backing {
160+ case . insecure:
161+ try await Self . serveInsecureHTTP1_1 (
162+ bindTarget: configuration. bindTarget,
163+ handler: handler,
164+ logger: logger
165+ )
166+
167+ case . certificateChainAndPrivateKey( let certificateChain, let privateKey) :
168+ try await Self . serveSecureUpgrade (
169+ bindTarget: configuration. bindTarget,
170+ certificateChain: certificateChain,
171+ privateKey: privateKey,
172+ handler: handler,
173+ logger: logger
174+ )
175+ }
176+ }
177+
178+ private static func serveInsecureHTTP1_1(
179+ bindTarget: HTTPServerConfiguration . BindTarget ,
180+ handler: RequestHandler ,
181+ logger: Logger
182+ ) async throws {
183+ switch bindTarget. backing {
184+ case . hostAndPort( let host, let port) :
185+ let serverChannel = try await ServerBootstrap ( group: . singletonMultiThreadedEventLoopGroup)
186+ . serverChannelOption ( . socketOption( . so_reuseaddr) , value: 1 )
187+ . bind ( host: host, port: port) { channel in
188+ channel. pipeline. configureHTTPServerPipeline ( ) . flatMapThrowing {
189+ try channel. pipeline. syncOperations. addHandler ( HTTP1ToHTTPServerCodec ( secure: false ) )
190+ return try NIOAsyncChannel < HTTPRequestPart , HTTPResponsePart > (
191+ wrappingChannelSynchronously: channel,
192+ configuration: . init( isOutboundHalfClosureEnabled: true )
167193 )
168- >
169- >
170- > in
171- channel. eventLoop. makeCompletedFuture {
172- switch configuration. tlSConfiguration. backing {
173- case . insecure:
174- break
194+ }
195+ }
175196
176- case . certificateChainAndPrivateKey( let certificateChain, let privateKey) :
177- let certificateChain =
178- try certificateChain
179- . map {
180- try NIOSSLCertificate (
181- bytes: $0. serializeAsPEM ( ) . derBytes,
182- format: . der
197+ try await withThrowingDiscardingTaskGroup { group in
198+ try await serverChannel. executeThenClose { inbound in
199+ for try await http1Channel in inbound {
200+ group. addTask {
201+ await Self . handleRequestChannel (
202+ logger: logger,
203+ channel: http1Channel,
204+ handler: handler
183205 )
184206 }
185- . map { NIOSSLCertificateSource . certificate ( $0) }
186- let privateKey = NIOSSLPrivateKeySource . privateKey (
187- try NIOSSLPrivateKey (
188- bytes: privateKey. serializeAsPEM ( ) . derBytes,
189- format: . der
207+ }
208+ }
209+ }
210+ }
211+ }
212+
213+ private static func serveSecureUpgrade(
214+ bindTarget: HTTPServerConfiguration . BindTarget ,
215+ certificateChain: [ Certificate ] ,
216+ privateKey: Certificate . PrivateKey ,
217+ handler: RequestHandler ,
218+ logger: Logger
219+ ) async throws {
220+ switch bindTarget. backing {
221+ case . hostAndPort( let host, let port) :
222+ let serverChannel = try await ServerBootstrap ( group: . singletonMultiThreadedEventLoopGroup)
223+ . serverChannelOption ( . socketOption( . so_reuseaddr) , value: 1 )
224+ . bind ( host: host, port: port) { channel in
225+ channel. eventLoop. makeCompletedFuture {
226+ let certificateChain = try certificateChain
227+ . map {
228+ try NIOSSLCertificate (
229+ bytes: $0. serializeAsPEM ( ) . derBytes,
230+ format: . der
231+ )
232+ }
233+ . map { NIOSSLCertificateSource . certificate ( $0) }
234+ let privateKey = NIOSSLPrivateKeySource . privateKey (
235+ try NIOSSLPrivateKey (
236+ bytes: privateKey. serializeAsPEM ( ) . derBytes,
237+ format: . der
238+ )
190239 )
191- )
192240
193- try channel. pipeline. syncOperations
194- . addHandler (
195- NIOSSLServerHandler (
196- context: . init(
197- configuration:
198- . makeServerConfiguration(
241+ try channel. pipeline. syncOperations
242+ . addHandler (
243+ NIOSSLServerHandler (
244+ context: . init(
245+ configuration: . makeServerConfiguration(
199246 certificateChain: certificateChain,
200247 privateKey: privateKey
201248 )
249+ )
202250 )
203251 )
204- )
205- }
206- } . flatMap {
207- channel
208- . configureAsyncHTTPServerPipeline { channel in
209- channel. eventLoop. makeCompletedFuture {
210- try channel. pipeline. syncOperations. addHandler ( HTTP1ToHTTPServerCodec ( secure: false ) )
252+ } . flatMap {
253+ channel. configureAsyncHTTPServerPipeline { channel in
254+ channel. eventLoop. makeCompletedFuture {
255+ try channel. pipeline. syncOperations. addHandler ( HTTP1ToHTTPServerCodec ( secure: true ) )
211256
212- return try NIOAsyncChannel < HTTPRequestPart , HTTPResponsePart > (
213- wrappingChannelSynchronously: channel,
214- configuration: . init( isOutboundHalfClosureEnabled: true )
215- )
216- }
217- } http2ConnectionInitializer: { channel in
218- channel. eventLoop. makeSucceededVoidFuture ( )
219- } http2StreamInitializer: { channel in
220- channel. eventLoop. makeCompletedFuture {
221- try channel. pipeline. syncOperations
222- . addHandler (
223- HTTP2FramePayloadToHTTPServerCodec ( )
257+ return try NIOAsyncChannel < HTTPRequestPart , HTTPResponsePart > (
258+ wrappingChannelSynchronously: channel,
259+ configuration: . init( isOutboundHalfClosureEnabled: true )
224260 )
261+ }
262+ } http2ConnectionInitializer: { channel in
263+ channel. eventLoop. makeSucceededVoidFuture ( )
264+ } http2StreamInitializer: { channel in
265+ channel. eventLoop. makeCompletedFuture {
266+ try channel. pipeline. syncOperations
267+ . addHandler (
268+ HTTP2FramePayloadToHTTPServerCodec ( )
269+ )
225270
226- return try NIOAsyncChannel < HTTPRequestPart , HTTPResponsePart > (
227- wrappingChannelSynchronously: channel,
228- configuration: . init( isOutboundHalfClosureEnabled: true )
229- )
271+ return try NIOAsyncChannel < HTTPRequestPart , HTTPResponsePart > (
272+ wrappingChannelSynchronously: channel,
273+ configuration: . init( isOutboundHalfClosureEnabled: true )
274+ )
275+ }
230276 }
231277 }
232- }
233- }
278+ }
234279
235- try await withThrowingDiscardingTaskGroup { group in
236- try await serverChannel. executeThenClose { inbound in
237- for try await upgradeResult in inbound {
238- group. addTask {
239- do {
240- try await withThrowingDiscardingTaskGroup { connectionGroup in
241- switch try await upgradeResult. get ( ) {
242- case . http1_1 ( let http1 Channel) :
243- connectionGroup. addTask {
244- await Self . handleRequestChannel (
245- logger: logger,
246- channel: http1Channel,
247- handler: handler
248- )
249- }
250- case . http2 ( ( _, let http2 Multiplexer) ) :
251- do {
252- for try await http2StreamChannel in http2Multiplexer. inbound {
253- connectionGroup. addTask {
254- await Self . handleRequestChannel (
255- logger: logger,
256- channel: http2StreamChannel,
257- handler: handler
258- )
280+ try await withThrowingDiscardingTaskGroup { group in
281+ try await serverChannel. executeThenClose { inbound in
282+ for try await upgradeResult in inbound {
283+ group. addTask {
284+ do {
285+ try await withThrowingDiscardingTaskGroup { connectionGroup in
286+ switch try await upgradeResult. get ( ) {
287+ case . http1_1 ( let http1 Channel) :
288+ connectionGroup. addTask {
289+ await Self . handleRequestChannel (
290+ logger: logger,
291+ channel: http1Channel,
292+ handler: handler
293+ )
294+ }
295+ case . http2 ( ( _, let http2 Multiplexer) ) :
296+ do {
297+ for try await http2StreamChannel in http2Multiplexer. inbound {
298+ connectionGroup. addTask {
299+ await Self . handleRequestChannel (
300+ logger: logger,
301+ channel: http2StreamChannel,
302+ handler: handler
303+ )
304+ }
259305 }
306+ } catch {
307+ logger. debug ( " HTTP2 connection closed: \( error) " )
260308 }
261- } catch {
262- logger. debug ( " HTTP2 connection closed: \( error) " )
263309 }
264310 }
311+ } catch {
312+ logger. debug ( " Negotiating ALPN failed: \( error) " )
265313 }
266- } catch {
267- logger. debug ( " Negotiating ALPN failed: \( error) " )
268314 }
269315 }
270316 }
@@ -312,39 +358,8 @@ public final class Server<RequestHandler: HTTPServerRequestHandler> {
312358 // TODO: We need to send a response head here potentially
313359 }
314360 } catch {
315- logger. debug ( " Error thrown while handling connection " )
361+ logger. debug ( " Error thrown while handling connection: \( error ) " )
316362 // TODO: We need to send a response head here potentially
317363 }
318364 }
319-
320- private static func bind(
321- bindTarget: HTTPServerConfiguration . BindTarget,
322- childChannelInitializer: @escaping @Sendable ( any Channel ) -> EventLoopFuture<
323- EventLoopFuture<
324- NIONegotiatedHTTPVersion<
325- NIOAsyncChannel< HTTPRequestPart, HTTPResponsePart> ,
326- ( Void, NIOHTTP2Handler . AsyncStreamMultiplexer< NIOAsyncChannel < HTTPRequestPart , HTTPResponsePart > > )
327- >
328- >
329- >
330- ) async throws -> NIOAsyncChannel<
331- EventLoopFuture<
332- NIONegotiatedHTTPVersion <
333- NIOAsyncChannel < HTTPRequestPart , HTTPResponsePart > ,
334- ( Void , NIOHTTP2Handler . AsyncStreamMultiplexer < NIOAsyncChannel < HTTPRequestPart , HTTPResponsePart > > )
335- >
336- > , Never
337- > {
338- switch bindTarget. backing {
339- case . hostAndPort( let host, let port) :
340- return try await ServerBootstrap ( group: . singletonMultiThreadedEventLoopGroup)
341- . serverChannelOption ( . socketOption( . so_reuseaddr) , value: 1 )
342- . bind (
343- host: host,
344- port: port,
345- childChannelInitializer: childChannelInitializer
346- )
347- }
348-
349- }
350365}
0 commit comments