-
Notifications
You must be signed in to change notification settings - Fork 134
Description
Issue related to:
AsyncHttpClient Version 1.6.0 onward
Context:
We interact with a server that always responds first with a 100 continue status code. Before version 1.6 we were able to handle this case with something like this:
extension EventLoopFuture where Value == HTTPClient.Response {
func handleContinueStatusCode(client: HTTPClient, request: HTTPClient.Request) -> EventLoopFuture<HTTPClient.Response> {
let resp = self.eventLoop.makePromise(of: HTTPClient.Response.self)
self.whenSuccess { response in
if response.status == .continue {
let next = client.execute(request.method, url: "\(request.url)")
.handleContinuationStatusCode(client: client, request: request)
resp.completeWith(next)
}
else {
resp.succeed(response)
}
}
...
}
After version 1.6 the client started to throw the new httpEndReceivedAfterHeadWith1xx error thown here
async-http-client/Sources/AsyncHTTPClient/ConnectionPool/HTTPRequestStateMachine.swift
Lines 531 to 538 in 1361ecc
| case .running(_, .waitingForHead): | |
| // If we receive a http response header with a status code of 1xx, we ignore the header | |
| // except for 101, which we consume. | |
| // If the remote closes the connection after sending a 1xx (not 101) response head, we | |
| // will receive a response end from the parser. We need to protect against this case. | |
| let error = HTTPClientError.httpEndReceivedAfterHeadWith1xx | |
| self.state = .failed(error) | |
| return .failRequest(error, .close) |
Now we are exactly in this situation and we changed the code above with:
extension EventLoopFuture where Value == HTTPClient.Response {
func handleContinueStatusCode(client: HTTPClient, request: HTTPClient.Request) -> EventLoopFuture<HTTPClient.Response> {
let resp = self.eventLoop.makePromise(of: HTTPClient.Response.self)
self.whenFailure { error in
if let error = error as? HTTPClientError, error == .httpEndReceivedAfterHeadWith1xx {
let next = client.execute(request.method, url: "\(request.url)")
.handleContinuationStatusCode(client: client, request: request)
resp.completeWith(next)
}
else {
resp.fail(error)
}
}
...
}
But this doesn't work anymore.
As a quirk fix for our case, we found that modifying the handling of the error at line 538 with
return .failRequest(error, .none)
The handleContinueStatusCode start to work again. But we don't know what other impacts this change has.
For an additional Insight I add here the curl of the request that fails:
curl --location --request POST 'https://sandbox.cedacri.it/psd2/v1.2/bg/03105/v1/consents' \
--header 'x-request-id: 3c528418-c8dc-4627-95e2-3e05e93411d8' \
--header 'psu-ip-address: 127.0.0.1' \
--header 'tpp-redirect-uri: http://localhost' \
--header 'Content-Type: application/json' \
--data-raw '{"validUntil":"1970-01-01","access":{"availableAccounts":"allAccounts"},"frequencyPerDay":1,"recurringIndicator":false,"combinedServiceIndicator":false}' -v
Swift version:
Swift version 5.5 (swift-5.5-RELEASE)
Target: x86_64-unknown-linux-gnu