Skip to content

Commit f1181ce

Browse files
authored
Handle channel closure properly (#20)
1 parent 8e2883c commit f1181ce

File tree

2 files changed

+18
-14
lines changed

2 files changed

+18
-14
lines changed

Sources/HTTPServer/HTTPResponseConcludingAsyncWriter.swift

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -116,9 +116,7 @@ public struct HTTPResponseConcludingAsyncWriter: ConcludingAsyncWriter, ~Copyabl
116116
let responseBodyAsyncWriter = ResponseBodyAsyncWriter(writer: self.writer)
117117
let (result, finalElement) = try await body(responseBodyAsyncWriter)
118118
try await self.writer.write(.end(finalElement))
119-
self.writerState.wrapped.withLock { state in
120-
state.finishedWriting = true
121-
}
119+
self.writerState.wrapped.withLock { $0.finishedWriting = true }
122120
return result
123121
}
124122
}

Sources/HTTPServer/HTTPServer.swift

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ public final class Server<RequestHandler: HTTPServerRequestHandler> {
211211
try await serverChannel.executeThenClose { inbound in
212212
for try await http1Channel in inbound {
213213
group.addTask {
214-
await Self.handleRequestChannel(
214+
try await Self.handleRequestChannel(
215215
logger: logger,
216216
channel: http1Channel,
217217
handler: handler
@@ -302,7 +302,7 @@ public final class Server<RequestHandler: HTTPServerRequestHandler> {
302302
switch try await upgradeResult.get() {
303303
case .http1_1(let http1Channel):
304304
connectionGroup.addTask {
305-
await Self.handleRequestChannel(
305+
try await Self.handleRequestChannel(
306306
logger: logger,
307307
channel: http1Channel,
308308
handler: handler
@@ -312,7 +312,7 @@ public final class Server<RequestHandler: HTTPServerRequestHandler> {
312312
do {
313313
for try await http2StreamChannel in http2Multiplexer.inbound {
314314
connectionGroup.addTask {
315-
await Self.handleRequestChannel(
315+
try await Self.handleRequestChannel(
316316
logger: logger,
317317
channel: http2StreamChannel,
318318
handler: handler
@@ -338,7 +338,7 @@ public final class Server<RequestHandler: HTTPServerRequestHandler> {
338338
logger: Logger,
339339
channel: NIOAsyncChannel<HTTPRequestPart, HTTPResponsePart>,
340340
handler: RequestHandler
341-
) async {
341+
) async throws {
342342
do {
343343
try await channel
344344
.executeThenClose { inbound, outbound in
@@ -380,17 +380,17 @@ public final class Server<RequestHandler: HTTPServerRequestHandler> {
380380
}
381381
)
382382
} catch {
383+
logger.error("Error thrown while handling connection: \(error)")
383384
if !readerState.wrapped.withLock({ $0.finishedReading }) {
384-
// TODO: do something - we didn't finish reading but we threw
385-
// if h2 reset stream; if h1 try draining request?
386-
fatalError("Didn't finish reading but threw.")
385+
logger.error("Did not finish reading but error thrown.")
386+
// TODO: if h2 reset stream; if h1 try draining request?
387387
}
388388
if !writerState.wrapped.withLock({ $0.finishedWriting }) {
389-
// TODO: this means we didn't write a response end and we threw
390-
// we need to do something, possibly just close the connection or
389+
logger.error("Did not write response but error thrown.")
390+
// TODO: we need to do something, possibly just close the connection or
391391
// reset the stream with the appropriate error.
392-
fatalError("Didn't finish writing but threw.")
393392
}
393+
throw error
394394
}
395395

396396
// TODO: handle other state scenarios.
@@ -399,10 +399,16 @@ public final class Server<RequestHandler: HTTPServerRequestHandler> {
399399
// If we finished reading but we didn't write back a response, then RST_STREAM
400400
// is also likely appropriate but unclear about the error.
401401
// For h1, we should close the connection.
402+
403+
// Finish the outbound and wait on the close future to make sure all pending
404+
// writes are actually written.
405+
outbound.finish()
406+
try await channel.channel.closeFuture.get()
402407
}
403408
} catch {
404-
logger.debug("Error thrown while handling connection: \(error)")
409+
logger.error("Error thrown while handling connection: \(error)")
405410
// TODO: We need to send a response head here potentially
411+
throw error
406412
}
407413
}
408414
}

0 commit comments

Comments
 (0)