Open
Description
We are observing an unexpected 502 responses when using async http client. Using curl on the same URL results in a successful request.
Example:
curl -vs https://www.eurohome.es/ical-rent/404.html > /dev/null
* Host www.eurohome.es:443 was resolved.
* IPv6: (none)
* IPv4: 81.88.57.88
* Trying 81.88.57.88:443...
* Connected to www.eurohome.es (81.88.57.88) port 443
[... snip ...]
* SSL certificate verify ok.
* using HTTP/2
* [HTTP/2] [1] OPENED stream for https://www.eurohome.es/ical-rent/404.html
* [HTTP/2] [1] [:method: GET]
* [HTTP/2] [1] [:scheme: https]
* [HTTP/2] [1] [:authority: www.eurohome.es]
* [HTTP/2] [1] [:path: /ical-rent/404.html]
* [HTTP/2] [1] [user-agent: curl/8.7.1]
* [HTTP/2] [1] [accept: */*]
> GET /ical-rent/404.html HTTP/2
> Host: www.eurohome.es
> User-Agent: curl/8.7.1
> Accept: */*
>
* Request completely sent off
< HTTP/2 404
< cache-control: private
< content-type: text/html; charset=utf-8
< server: Microsoft-IIS/10.0
< set-cookie: dadaproaffinity=7ff23aa7431c1694d43dffd9ed6cc9c9a2bc852f274fb026be889a5345c6d8d4;Path=/;Domain=www.eurohome.es
< x-powered-by: ASP.NET
< x-powered-by: ARR/3.0
< date: Thu, 05 Dec 2024 16:20:32 GMT
< content-length: 4894
<
{ [4894 bytes data]
* Connection #0 to host www.eurohome.es left intact
But running the same request through AsyncHTTPClient gives as 502 - Bad Gateway
response.
swift run downloader https://www.eurohome.es/ical-rent/404.html -v
HTTPClientResponse(version: HTTP/2.0, status: 502 Bad Gateway, headers: [("content-type", "text/html"), ("server", "Microsoft-IIS/10.0"), ("date", "Thu, 05 Dec 2024 16:22:13 GMT"), ("content-length", "1477")], body: /* snip */)
The request will succeed (ie with a 404 code) when forcing http1Only
on the client. Note though, that curl is able to successfully use http2.
Reproducer code
import AsyncHTTPClient
import ArgumentParser
import NIOHTTP1
import NIOCore
@main
struct Downloader: AsyncParsableCommand {
@Argument
var url: String
@Option(name: .customShort("X"))
var method: String = "GET"
@Flag(name: .short)
var verbose: Bool = false
@Flag
var http1Only: Bool = false
func run() async throws {
var config = HTTPClient.Configuration()
if http1Only {
config.httpVersion = .http1Only
}
let client = HTTPClient(configuration: config)
defer {
Task { try? await client.shutdown() }
}
var request = HTTPClientRequest(url: self.url)
request.method = HTTPMethod(rawValue: self.method)
if verbose {
print(request)
}
let response = try await client.execute(request, deadline: NIODeadline.now() + .seconds(30))
if verbose {
print(response)
}
for try await chunk in response.body {
print(String(decoding: chunk.readableBytesView, as: UTF8.self), terminator: "")
}
}
}
Metadata
Metadata
Assignees
Labels
No labels