Roy Hashimoto created HTTPCORE-785:
--------------------------------------

             Summary: TLS ALPN overrides FORCE_HTTP_1
                 Key: HTTPCORE-785
                 URL: https://issues.apache.org/jira/browse/HTTPCORE-785
             Project: HttpComponents HttpCore
          Issue Type: Bug
          Components: HttpCore
    Affects Versions: 5.3.5
            Reporter: Roy Hashimoto


When I use a Conscrypt SSLContext, it always uses ALPN to negotiate HTTP2 with 
clients even if version policy HttpVersion.FORCE_HTTP_1 is specified. My 
standalone Kotlin reproduction code is here: 
[https://github.com/rhashimoto/httpcore5-http1-repro/blob/master/src/main/kotlin/Main.kt]

 

This Intellij project contains a self-signed X509 certificate resource with 
CN=localhost. It builds and starts a HTTPS server on port 8443.

 

If I restrict curl 7.88.1 to use HTTP 1.1, things work as expected:

{{$ curl -kv --http1.1 https://localhost:8443/}}
{{*   Trying 127.0.0.1:8443...}}
{{* Connected to localhost (127.0.0.1) port 8443 (#0)}}
{{* ALPN: offers http/1.1}}
{{* TLSv1.3 (OUT), TLS handshake, Client hello (1):}}
{{* TLSv1.3 (IN), TLS handshake, Server hello (2):}}
{{* TLSv1.2 (IN), TLS handshake, Certificate (11):}}
{{* TLSv1.2 (IN), TLS handshake, Server key exchange (12):}}
{{* TLSv1.2 (IN), TLS handshake, Server finished (14):}}
{{* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):}}
{{* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):}}
{{* TLSv1.2 (OUT), TLS handshake, Finished (20):}}
{{* TLSv1.2 (IN), TLS handshake, Finished (20):}}
{{* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256}}
{{* ALPN: server accepted http/1.1}}
{{* Server certificate:}}
{{*  subject: CN=localhost}}
{{*  start date: Sep 18 22:47:40 2025 GMT}}
{{*  expire date: Sep 16 22:47:40 2035 GMT}}
{{*  issuer: CN=localhost}}
{{*  SSL certificate verify result: self-signed certificate (18), continuing 
anyway.}}
{{* using HTTP/1.1}}
{{> GET / HTTP/1.1}}
{{> Host: localhost:8443}}
{{> User-Agent: curl/7.88.1}}
{{> Accept: */*}}
{{> }}
{{< HTTP/1.1 200 OK}}
{{< Date: Tue, 23 Sep 2025 18:01:18 GMT}}
{{< Server: Apache-HttpCore/5.3.5 (Java/24.0.2)}}
{{< Content-Length: 14}}
{{< Content-Type: text/plain; charset=UTF-8}}
{{< }}
{{Hello, World!}}
{{* Connection #0 to host localhost left intact}}

But if I allow curl to negotiate the HTTP version, it chooses HTTP 2 by ALPN 
and fails:

{{$ curl -kv https://localhost:8443/}}
{{*   Trying 127.0.0.1:8443...}}
{{* Connected to localhost (127.0.0.1) port 8443 (#0)}}
{{* ALPN: offers h2,http/1.1}}
{{* TLSv1.3 (OUT), TLS handshake, Client hello (1):}}
{{* TLSv1.3 (IN), TLS handshake, Server hello (2):}}
{{* TLSv1.2 (IN), TLS handshake, Certificate (11):}}
{{* TLSv1.2 (IN), TLS handshake, Server key exchange (12):}}
{{* TLSv1.2 (IN), TLS handshake, Server finished (14):}}
{{* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):}}
{{* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):}}
{{* TLSv1.2 (OUT), TLS handshake, Finished (20):}}
{{* TLSv1.2 (IN), TLS handshake, Finished (20):}}
{{* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256}}
{{* ALPN: server accepted h2}}
{{* Server certificate:}}
{{*  subject: CN=localhost}}
{{*  start date: Sep 18 22:47:40 2025 GMT}}
{{*  expire date: Sep 16 22:47:40 2035 GMT}}
{{*  issuer: CN=localhost}}
{{*  SSL certificate verify result: self-signed certificate (18), continuing 
anyway.}}
{{* using HTTP/2}}
{{* h2h3 [:method: GET]}}
{{* h2h3 [:path: /]}}
{{* h2h3 [:scheme: https]}}
{{* h2h3 [:authority: localhost:8443]}}
{{* h2h3 [user-agent: curl/7.88.1]}}
{{* h2h3 [accept: */*]}}
{{* Using Stream ID: 1 (easy handle 0x5619da01fce0)}}
{{> GET / HTTP/2}}
{{> Host: localhost:8443}}
{{> user-agent: curl/7.88.1}}
{{> accept: */*}}
{{> }}
{{* Empty reply from server}}
{{* Closing connection 0}}
{{curl: (52) Empty reply from server}}

A workaround is to use BasicServerTlsStrategy to avoid ALPN.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to