This is an automated email from the ASF dual-hosted git repository.
samueleresca pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/pekko-http.git
The following commit(s) were added to refs/heads/main by this push:
new c7655e129 docs: modernize HTTP/2 ALPN and h2c guidance (#1253)
c7655e129 is described below
commit c7655e129cb7630aaaa069fc9b7fb72b8950dfcf
Author: Samuele Resca <[email protected]>
AuthorDate: Sun Sep 6 13:38:42 2026 +0100
docs: modernize HTTP/2 ALPN and h2c guidance (#1253)
* docs: modernize HTTP/2 ALPN and h2c guidance
Motivation:
The HTTP/2 server-side doc still described ALPN as requiring separate
negotiation setup and documented a JDK <= 9 fallback where curl could not
determine h2 support, plus it presented the HTTP/1.1 h2c Upgrade mechanism
without noting it is now obsolete per RFC 9113. Apache Pekko HTTP's minimum
supported JDK has since moved to 17, where ALPN is natively part of JSSE
and the RFC 7540 Upgrade path has been superseded.
Modification:
Reword the ALPN section to state it needs no extra provider or boot
classpath configuration on supported JDKs, and link to RFC 7301/RFC 9113
instead of RFC 7540. Add a warning that h2c Upgrade is obsolete in RFC 9113
and should only be used for older-client compatibility, rename the "h2c
with prior knowledge" section to "Cleartext HTTP/2 with prior knowledge",
and drop the outdated JDK <= 9 curl fallback example that no longer applies
on the project's supported JDKs.
Result:
The doc reflects the project's current JDK baseline and RFC 9113 guidance
without the stale JDK <= 9 ALPN caveat or unlabeled deprecated h2c Upgrade
mechanism.
Tests:
Not run - docs only
References:
None - documentation accuracy update
* Fixing wording from prior knowledge to Prior Knowledge
---
.../main/paradox/client-side/connection-level.md | 2 +-
docs/src/main/paradox/client-side/http2.md | 4 +-
docs/src/main/paradox/server-side/http2.md | 57 +++++++++-------------
.../http2/OutgoingConnectionBuilderImpl.scala | 2 +-
.../http/javadsl/OutgoingConnectionBuilder.scala | 4 +-
.../http/scaladsl/OutgoingConnectionBuilder.scala | 4 +-
6 files changed, 31 insertions(+), 42 deletions(-)
diff --git a/docs/src/main/paradox/client-side/connection-level.md
b/docs/src/main/paradox/client-side/connection-level.md
index 591586744..ad4e2acae 100644
--- a/docs/src/main/paradox/client-side/connection-level.md
+++ b/docs/src/main/paradox/client-side/connection-level.md
@@ -24,7 +24,7 @@ Java
In addition to the host name and port the builder
@apidoc[OutgoingConnectionBuilder] returned by
@scala[`Http().connectionTo(...)`]@java[`Http.get(system).connectionTo(...)`]
method also allows you to specify additional properties and as the final step
deciding which protocol to use
-(HTTP/1, HTTP/1 over TLS, HTTP/2 over TLS or HTTP/2 with prior knowledge over
a plaintext connection). For details on
+(HTTP/1, HTTP/1 over TLS, HTTP/2 over TLS or HTTP/2 with Prior Knowledge over
a plaintext connection). For details on
using HTTP/2 see @ref[Client-Side HTTP/2](./http2.md).
No connection is attempted until the returned flow is actually materialized!
If the flow is materialized
diff --git a/docs/src/main/paradox/client-side/http2.md
b/docs/src/main/paradox/client-side/http2.md
index 59490bca0..69261215e 100644
--- a/docs/src/main/paradox/client-side/http2.md
+++ b/docs/src/main/paradox/client-side/http2.md
@@ -17,7 +17,7 @@ unexpected when coming from a background with non-"streaming
first" HTTP Clients
There are three mechanisms for a client to establish an HTTP/2 connection.
Apache Pekko HTTP supports:
- HTTP/2 over TLS
- - HTTP/2 over a plain TCP connection ("h2c with prior knowledge")
+ - HTTP/2 over a plain TCP connection ("h2c with Prior Knowledge")
Apache Pekko HTTP doesn't support:
@@ -37,7 +37,7 @@ HTTP/2 over TLS needs [Application-Layer Protocol Negotiation
(ALPN)](https://en
to negotiate whether both client and server support HTTP/2.
Apache Pekko HTTP does not currently support protocol negotiation to fall back
to HTTP/1.1 for this API. When the server does not support HTTP/2, the stream
will fail.
-### h2c with prior knowledge
+### h2c with Prior Knowledge
The other option is to connect and start communicating in HTTP/2 immediately.
You must know beforehand the target server
supports HTTP/2 over a plain TCP connection. For this reason this approach is
known as h2c with
diff --git a/docs/src/main/paradox/server-side/http2.md
b/docs/src/main/paradox/server-side/http2.md
index 335d367e0..f63a89bcc 100644
--- a/docs/src/main/paradox/server-side/http2.md
+++ b/docs/src/main/paradox/server-side/http2.md
@@ -26,20 +26,20 @@ Java
Note that currently only `newServerAt(...).bind` and
`newServerAt(...).bindSync`
support HTTP/2 but not `bindFlow` or `connectionSource(): Source`.
-HTTP/2 over TLS needs [Application-Layer Protocol Negotiation
(ALPN)](https://en.wikipedia.org/wiki/Application-Layer_Protocol_Negotiation)
-to negotiate whether both client and server support HTTP/2.
+HTTP/2 over TLS uses [Application-Layer Protocol Negotiation
(ALPN)](https://www.rfc-editor.org/rfc/rfc7301.html)
+to negotiate whether both client and server support HTTP/2. ALPN support is
included in the Java versions supported by
+Apache Pekko HTTP and does not require a separate provider or boot classpath
configuration.
### HTTP/2 without HTTPS
-While un-encrypted connections are allowed by HTTP/2, this is [sometimes
discouraged](https://http2.github.io/faq/#does-http2-require-encryption).
+HTTP/2 without TLS should only be used on a trusted network or when TLS is
terminated by a trusted proxy. Most public
+clients use HTTP/2 over TLS.
-There are 2 ways to implement un-encrypted HTTP/2 connections: by using the
-[HTTP Upgrade mechanism](https://httpwg.org/specs/rfc7540.html#discover-http)
-or by starting communication in HTTP/2 directly which requires the client to
-have [Prior Knowledge](https://httpwg.org/specs/rfc7540.html#known-http) of
-HTTP/2 support.
+Apache Pekko HTTP supports starting a cleartext HTTP/2 connection with
+[Prior Knowledge](https://www.rfc-editor.org/rfc/rfc9113.html#section-3.3).
For compatibility with older clients, it
+also supports the HTTP/1.1 Upgrade mechanism from the obsolete RFC 7540
specification.
-We support both approaches transparently on the same port. This feature is
automatically enabled when HTTP/2 is enabled:
+Both approaches are supported transparently on the same port and are
automatically enabled when HTTP/2 is enabled:
Scala
:
@@snip[Http2Spec.scala](/docs/src/test/scala/docs/http/scaladsl/Http2Spec.scala)
{ #bindAndHandlePlain }
@@ -49,10 +49,16 @@ Java
#### h2c Upgrade
-The advantage of switching from HTTP/1.1 to HTTP/2 using the
-[HTTP Upgrade mechanism](https://httpwg.org/specs/rfc7540.html#discover-http)
-is that both HTTP/1.1 and HTTP/2 clients can connect to the server on the
-same port, without being aware beforehand which protocol the server supports.
+@@@ warning
+
+The HTTP/1.1 Upgrade mechanism and the `h2c` upgrade token are obsolete in
+[RFC 9113](https://www.rfc-editor.org/rfc/rfc9113.html#section-11.2). Use this
mode only when compatibility with an
+older client requires it. New cleartext HTTP/2 clients should use Prior
Knowledge.
+
+@@@
+
+The legacy Upgrade mechanism allows HTTP/1.1 and HTTP/2 clients to connect to
the same port without knowing beforehand
+which protocol the server supports.
The disadvantage is that relatively few clients support switching to HTTP/2
in this way. Additionally, HTTP/2 communication cannot start until the first
@@ -60,14 +66,13 @@ request has been completely sent. This means if your first
request may be
large, it might be worth it to start with an empty OPTIONS request to switch
to HTTP/2 before sending your first 'real' request, at the cost of a roundtrip.
-#### h2c with prior knowledge
+#### Cleartext HTTP/2 with Prior Knowledge
The other option is to connect and start communicating in HTTP/2 immediately.
The downside of this approach is the client must know beforehand that the
server supports HTTP/2.
-For the reason this approach is known as h2c with
-[Prior Knowledge](https://httpwg.org/specs/rfc7540.html#known-http) of HTTP/2
-support.
+For this reason the approach is known as HTTP/2 with
+[Prior Knowledge](https://www.rfc-editor.org/rfc/rfc9113.html#section-3.3).
## Trailing headers
@@ -114,20 +119,4 @@ $ curl -k -v https://localhost:8443
(...)
```
-If your curl output looks like above, you have successfully configured HTTP/2.
However, on JDKs up to version 9, it is likely to look like this instead:
-
-```
-$ curl -k -v https://localhost:8443
-(...)
-* ALPN, offering h2
-* ALPN, offering http/1.1
-(...)
-* ALPN, server did not agree to a protocol
-(...)
-> GET / HTTP/1.1
-(...)
-< HTTP/1.1 200 OK
-(...)
-```
-
-This shows `curl` declaring it is ready to speak `h2` (the shorthand name of
HTTP/2), but could not determine whether the server is ready to, so it fell
back to HTTP/1.1. To make this negotiation work you'll have to configure ALPN
as described below.
+If your curl output looks like above, you have successfully configured HTTP/2.
diff --git
a/http-core/src/main/scala/org/apache/pekko/http/impl/engine/http2/OutgoingConnectionBuilderImpl.scala
b/http-core/src/main/scala/org/apache/pekko/http/impl/engine/http2/OutgoingConnectionBuilderImpl.scala
index 2eb3f69ed..4fd7fd148 100644
---
a/http-core/src/main/scala/org/apache/pekko/http/impl/engine/http2/OutgoingConnectionBuilderImpl.scala
+++
b/http-core/src/main/scala/org/apache/pekko/http/impl/engine/http2/OutgoingConnectionBuilderImpl.scala
@@ -100,7 +100,7 @@ private[pekko] object OutgoingConnectionBuilderImpl {
clientConnectionSettings.http2Settings)
override def http2WithPriorKnowledge(): Flow[HttpRequest, HttpResponse,
Future[OutgoingConnection]] = {
- // http/2 prior knowledge plaintext
+ // http/2 Prior Knowledge plaintext
Http2(system.classicSystem).outgoingConnectionPriorKnowledge(host,
port.getOrElse(80), clientConnectionSettings,
log)
}
diff --git
a/http-core/src/main/scala/org/apache/pekko/http/javadsl/OutgoingConnectionBuilder.scala
b/http-core/src/main/scala/org/apache/pekko/http/javadsl/OutgoingConnectionBuilder.scala
index 0d407ddbc..9b104b539 100644
---
a/http-core/src/main/scala/org/apache/pekko/http/javadsl/OutgoingConnectionBuilder.scala
+++
b/http-core/src/main/scala/org/apache/pekko/http/javadsl/OutgoingConnectionBuilder.scala
@@ -77,7 +77,7 @@ trait OutgoingConnectionBuilder {
def managedPersistentHttp2(): Flow[HttpRequest, HttpResponse, NotUsed]
/**
- * Create a flow that when materialized creates a single HTTP/2 with 'prior
knowledge' plaintext connection with a default port 80
+ * Create a flow that when materialized creates a single HTTP/2 with 'Prior
Knowledge' plaintext connection with a default port 80
*
* Note that the responses are not guaranteed to arrive in the same order as
the requests go out (In the case of a HTTP/2 connection)
* so therefore requests needs to have a
[[pekko.http.scaladsl.model.RequestResponseAssociation]]
@@ -86,7 +86,7 @@ trait OutgoingConnectionBuilder {
def http2WithPriorKnowledge(): Flow[HttpRequest, HttpResponse,
CompletionStage[OutgoingConnection]]
/**
- * Create a flow that when materialized creates a single HTTP/2 with 'prior
knowledge' plaintext connection with a default port 80
+ * Create a flow that when materialized creates a single HTTP/2 with 'Prior
Knowledge' plaintext connection with a default port 80
*
* The connection will be re-established as needed.
*
diff --git
a/http-core/src/main/scala/org/apache/pekko/http/scaladsl/OutgoingConnectionBuilder.scala
b/http-core/src/main/scala/org/apache/pekko/http/scaladsl/OutgoingConnectionBuilder.scala
index 7bd057333..4ca5948e8 100644
---
a/http-core/src/main/scala/org/apache/pekko/http/scaladsl/OutgoingConnectionBuilder.scala
+++
b/http-core/src/main/scala/org/apache/pekko/http/scaladsl/OutgoingConnectionBuilder.scala
@@ -78,7 +78,7 @@ trait OutgoingConnectionBuilder {
def managedPersistentHttp2(): Flow[HttpRequest, HttpResponse, NotUsed]
/**
- * Create a flow that when materialized creates a single HTTP/2 with 'prior
knowledge' plaintext connection with a default port 80
+ * Create a flow that when materialized creates a single HTTP/2 with 'Prior
Knowledge' plaintext connection with a default port 80
*
* Note that the responses are not guaranteed to arrive in the same order as
the requests go out (In the case of a HTTP/2 connection)
* so therefore requests needs to have a
[[pekko.http.scaladsl.model.RequestResponseAssociation]]
@@ -87,7 +87,7 @@ trait OutgoingConnectionBuilder {
def http2WithPriorKnowledge(): Flow[HttpRequest, HttpResponse,
Future[OutgoingConnection]]
/**
- * Create a flow that when materialized creates a single HTTP/2 with 'prior
knowledge' plaintext connection with a default port 80
+ * Create a flow that when materialized creates a single HTTP/2 with 'Prior
Knowledge' plaintext connection with a default port 80
*
* The connection will be re-established as needed.
*
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]