Skip to content

Commit df4e247

Browse files
authored
Removed “Connection” headers (#26)
1 parent ddee38c commit df4e247

File tree

2 files changed

+29
-6
lines changed

2 files changed

+29
-6
lines changed

Sources/MockServer/main.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,10 @@ internal final class HTTPHandler: ChannelInboundHandler {
125125
func writeResponse(context: ChannelHandlerContext, status: HTTPResponseStatus, headers: [(String, String)]? = nil, body: String? = nil) {
126126
var headers = HTTPHeaders(headers ?? [])
127127
headers.add(name: "Content-Length", value: "\(body?.utf8.count ?? 0)")
128-
headers.add(name: "Connection", value: self.keepAlive ? "keep-alive" : "close")
128+
if !self.keepAlive {
129+
// We only need to add a "Connection" header if we really want to close the connection
130+
headers.add(name: "Connection", value: "close")
131+
}
129132
let head = HTTPResponseHead(version: HTTPVersion(major: 1, minor: 1), status: status, headers: headers)
130133

131134
context.write(wrapOutboundOut(.head(head))).whenFailure { error in

Sources/SwiftAwsLambda/HttpClient.swift

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ internal final class HTTPClient {
111111
}
112112

113113
internal struct Response: Equatable {
114+
public var version: HTTPVersion
114115
public var status: HTTPResponseStatus
115116
public var headers: HTTPHeaders
116117
public var body: ByteBuffer?
@@ -150,7 +151,20 @@ private final class HTTPHandler: ChannelDuplexHandler {
150151
if let body = request.body {
151152
head.headers.add(name: "Content-Length", value: String(body.readableBytes))
152153
}
153-
head.headers.add(name: "Connection", value: self.keepAlive ? "keep-alive" : "close")
154+
// We don't add a "Connection" header here if we want to keep the connection open,
155+
// HTTP/1.1 defines specifies the following in RFC 2616, Section 8.1.2.1:
156+
//
157+
// An HTTP/1.1 server MAY assume that a HTTP/1.1 client intends to
158+
// maintain a persistent connection unless a Connection header including
159+
// the connection-token "close" was sent in the request. If the server
160+
// chooses to close the connection immediately after sending the
161+
// response, it SHOULD send a Connection header including the
162+
// connection-token close.
163+
//
164+
// See also UnaryHandler.channelRead below.
165+
if !self.keepAlive {
166+
head.headers.add(name: "Connection", value: "close")
167+
}
154168

155169
context.write(self.wrapOutboundOut(HTTPClientRequestPart.head(head))).flatMap { _ -> EventLoopFuture<Void> in
156170
if let body = request.body {
@@ -184,10 +198,10 @@ private final class HTTPHandler: ChannelDuplexHandler {
184198
case .end:
185199
switch self.readState {
186200
case .head(let head):
187-
context.fireChannelRead(wrapInboundOut(HTTPClient.Response(status: head.status, headers: head.headers, body: nil)))
201+
context.fireChannelRead(wrapInboundOut(HTTPClient.Response(version: head.version, status: head.status, headers: head.headers, body: nil)))
188202
self.readState = .idle
189203
case .body(let head, let body):
190-
context.fireChannelRead(wrapInboundOut(HTTPClient.Response(status: head.status, headers: head.headers, body: body)))
204+
context.fireChannelRead(wrapInboundOut(HTTPClient.Response(version: head.version, status: head.status, headers: head.headers, body: body)))
191205
self.readState = .idle
192206
default:
193207
preconditionFailure("invalid read state \(self.readState)")
@@ -238,8 +252,14 @@ private final class UnaryHandler: ChannelDuplexHandler {
238252
guard let pending = self.pending else {
239253
preconditionFailure("invalid state, no pending request")
240254
}
241-
let serverKeepAlive = response.headers.first(name: "connection")?.lowercased() == "keep-alive"
242-
if !self.keepAlive || !serverKeepAlive {
255+
256+
// As defined in RFC 2616 Section 8.1.2:
257+
// [...] unless otherwise indicated, the client SHOULD assume
258+
// that the server will maintain a persistent connection, even
259+
// after error responses from the server.
260+
let serverCloseConnection = response.headers.first(name: "connection")?.lowercased() == "close"
261+
262+
if !self.keepAlive || serverCloseConnection || response.version != .init(major: 1, minor: 1) {
243263
pending.promise.futureResult.whenComplete { _ in
244264
_ = context.channel.close()
245265
}

0 commit comments

Comments
 (0)