Skip to content

Commit b25943a

Browse files
authored
Fix HTTP/1.0 support (#431)
Use `HTTPResponseHead.isKeepAlive` instead of relying on our own keep-alive test.
1 parent bef8878 commit b25943a

File tree

3 files changed

+34
-1
lines changed

3 files changed

+34
-1
lines changed

Diff for: Sources/AsyncHTTPClient/ConnectionPool/HTTP1.1/HTTP1ConnectionStateMachine.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ struct HTTP1ConnectionStateMachine {
256256
let action = requestStateMachine.channelRead(part)
257257

258258
if case .head(let head) = part, close == false {
259-
close = head.headers[canonicalForm: "connection"].contains(where: { $0.lowercased() == "close" })
259+
close = !head.isKeepAlive
260260
}
261261
state = .inRequest(requestStateMachine, close: close)
262262
return state.modify(with: action)

Diff for: Tests/AsyncHTTPClientTests/HTTP1ConnectionStateMachineTests+XCTest.swift

+2
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ extension HTTP1ConnectionStateMachineTests {
2828
("testPOSTRequestWithWriteAndReadBackpressure", testPOSTRequestWithWriteAndReadBackpressure),
2929
("testResponseReadingWithBackpressure", testResponseReadingWithBackpressure),
3030
("testAConnectionCloseHeaderInTheRequestLeadsToConnectionCloseAfterRequest", testAConnectionCloseHeaderInTheRequestLeadsToConnectionCloseAfterRequest),
31+
("testAHTTP1_0ResponseWithoutKeepAliveHeaderLeadsToConnectionCloseAfterRequest", testAHTTP1_0ResponseWithoutKeepAliveHeaderLeadsToConnectionCloseAfterRequest),
32+
("testAHTTP1_0ResponseWithKeepAliveHeaderLeadsToConnectionBeingKeptAlive", testAHTTP1_0ResponseWithKeepAliveHeaderLeadsToConnectionBeingKeptAlive),
3133
("testAConnectionCloseHeaderInTheResponseLeadsToConnectionCloseAfterRequest", testAConnectionCloseHeaderInTheResponseLeadsToConnectionCloseAfterRequest),
3234
("testNIOTriggersChannelActiveTwice", testNIOTriggersChannelActiveTwice),
3335
("testIdleConnectionBecomesInactive", testIdleConnectionBecomesInactive),

Diff for: Tests/AsyncHTTPClientTests/HTTP1ConnectionStateMachineTests.swift

+31
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,37 @@ class HTTP1ConnectionStateMachineTests: XCTestCase {
9797
let responseBody = ByteBuffer(bytes: [1, 2, 3, 4])
9898
XCTAssertEqual(state.channelRead(.body(responseBody)), .wait)
9999
XCTAssertEqual(state.channelRead(.end(nil)), .succeedRequest(.close, .init([responseBody])))
100+
XCTAssertEqual(state.channelInactive(), .fireChannelInactive)
101+
}
102+
103+
func testAHTTP1_0ResponseWithoutKeepAliveHeaderLeadsToConnectionCloseAfterRequest() {
104+
var state = HTTP1ConnectionStateMachine()
105+
XCTAssertEqual(state.channelActive(isWritable: true), .fireChannelActive)
106+
let requestHead = HTTPRequestHead(version: .http1_1, method: .GET, uri: "/")
107+
let metadata = RequestFramingMetadata(connectionClose: false, body: .none)
108+
XCTAssertEqual(state.runNewRequest(head: requestHead, metadata: metadata), .sendRequestHead(requestHead, startBody: false))
109+
110+
let responseHead = HTTPResponseHead(version: .http1_0, status: .ok, headers: ["content-length": "4"])
111+
XCTAssertEqual(state.channelRead(.head(responseHead)), .forwardResponseHead(responseHead, pauseRequestBodyStream: false))
112+
let responseBody = ByteBuffer(bytes: [1, 2, 3, 4])
113+
XCTAssertEqual(state.channelRead(.body(responseBody)), .wait)
114+
XCTAssertEqual(state.channelRead(.end(nil)), .succeedRequest(.close, .init([responseBody])))
115+
XCTAssertEqual(state.channelInactive(), .fireChannelInactive)
116+
}
117+
118+
func testAHTTP1_0ResponseWithKeepAliveHeaderLeadsToConnectionBeingKeptAlive() {
119+
var state = HTTP1ConnectionStateMachine()
120+
XCTAssertEqual(state.channelActive(isWritable: true), .fireChannelActive)
121+
let requestHead = HTTPRequestHead(version: .http1_1, method: .GET, uri: "/")
122+
let metadata = RequestFramingMetadata(connectionClose: false, body: .none)
123+
XCTAssertEqual(state.runNewRequest(head: requestHead, metadata: metadata), .sendRequestHead(requestHead, startBody: false))
124+
125+
let responseHead = HTTPResponseHead(version: .http1_0, status: .ok, headers: ["content-length": "4", "connection": "keep-alive"])
126+
XCTAssertEqual(state.channelRead(.head(responseHead)), .forwardResponseHead(responseHead, pauseRequestBodyStream: false))
127+
let responseBody = ByteBuffer(bytes: [1, 2, 3, 4])
128+
XCTAssertEqual(state.channelRead(.body(responseBody)), .wait)
129+
XCTAssertEqual(state.channelRead(.end(nil)), .succeedRequest(.informConnectionIsIdle, .init([responseBody])))
130+
XCTAssertEqual(state.channelInactive(), .fireChannelInactive)
100131
}
101132

102133
func testAConnectionCloseHeaderInTheResponseLeadsToConnectionCloseAfterRequest() {

0 commit comments

Comments
 (0)