Skip to content

Commit 5faa08c

Browse files
NilsRenaudvietj
authored andcommitted
4.x backport - 5553 permits access to :authority HTTP/2 pseudo header value
And fix the `HttpServerRequest#autority()` javadoc, which was incorrect. And have a single source of authority truth between the Http2ServerStream and Http2ServerRequest (cherry picked from commit 532e428)
1 parent 2220b30 commit 5faa08c

File tree

8 files changed

+74
-38
lines changed

8 files changed

+74
-38
lines changed

src/main/java/io/vertx/core/http/HttpServerRequest.java

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -137,14 +137,26 @@ default boolean isSSL() {
137137
String query();
138138

139139
/**
140-
* @return the request authority. For HTTP/2 the {@literal :authority} pseudo header is returned, for HTTP/1.x the
141-
* {@literal Host} header is returned or {@code null} when no such header is present. When the authority
142-
* string does not carry a port, the {@link HostAndPort#port()} returns {@code -1} to indicate the
143-
* scheme port is prevalent.
140+
* @return the request authority.
141+
* <ul>
142+
* <li>HTTP/2: the {@literal :authority} pseudo header is returned if present, otherwise the {@literal Host}
143+
* header value is returned.
144+
* <li>HTTP/1.x: the {@literal Host} header is returned
145+
* <li>or {@code null} when no such header is present
146+
* </ul>
147+
* When the authority string does not carry a port, the {@link HostAndPort#port()} returns {@code -1} to
148+
* indicate the scheme port is prevalent.
144149
*/
145150
@Nullable
146151
HostAndPort authority();
147152

153+
/**
154+
* @param real whether to return the value of the real HTTP/2 {@literal :authority} header, or the computed one.
155+
* @return the authority, either computed or real. May be null when {@literal real} is {@code true}.
156+
*/
157+
@Nullable
158+
HostAndPort authority(boolean real);
159+
148160
/**
149161
* @return the request host. For HTTP2 it returns the {@literal :authority} pseudo header otherwise it returns the {@literal Host} header
150162
* @deprecated instead use {@link #authority()}

src/main/java/io/vertx/core/http/impl/Http1xServerRequest.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,11 @@ public HostAndPort authority() {
275275
return authority;
276276
}
277277

278+
@Override
279+
public HostAndPort authority(boolean real) {
280+
return real ? null : authority();
281+
}
282+
278283
@Override
279284
public @Nullable String host() {
280285
return getHeader(HttpHeaderNames.HOST);

src/main/java/io/vertx/core/http/impl/Http2ServerConnection.java

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ private static boolean isMalformedRequest(Http2ServerStream request) {
8585
}
8686

8787
if (request.method == HttpMethod.CONNECT) {
88-
if (request.scheme != null || request.uri != null || request.authority == null) {
88+
if (request.scheme != null || request.uri != null || request.authority() == null) {
8989
return true;
9090
}
9191
} else {
@@ -94,13 +94,13 @@ private static boolean isMalformedRequest(Http2ServerStream request) {
9494
}
9595
}
9696
if (request.hasAuthority) {
97-
if (request.authority == null) {
97+
if (request.authority() == null) {
9898
return true;
9999
}
100100
CharSequence hostHeader = request.headers.get(HttpHeaders.HOST);
101101
if (hostHeader != null) {
102102
HostAndPort host = HostAndPort.parseAuthority(hostHeader.toString(), -1);
103-
return host == null || (!request.authority.host().equals(host.host()) || request.authority.port() != host.port());
103+
return host == null || (!request.authority().host().equals(host.host()) || request.authority().port() != host.port());
104104
}
105105
}
106106
return false;
@@ -129,18 +129,20 @@ String determineContentEncoding(Http2Headers headers) {
129129

130130
private Http2ServerStream createStream(Http2Headers headers, boolean streamEnded) {
131131
CharSequence schemeHeader = headers.getAndRemove(HttpHeaders.PSEUDO_SCHEME);
132-
HostAndPort authority = null;
132+
HostAndPort computedAuthority = null;
133+
HostAndPort realAuthority = null;
133134
String authorityHeaderAsString;
134135
CharSequence authorityHeader = headers.getAndRemove(HttpHeaders.PSEUDO_AUTHORITY);
135136
if (authorityHeader != null) {
136137
authorityHeaderAsString = authorityHeader.toString();
137-
authority = HostAndPort.parseAuthority(authorityHeaderAsString, -1);
138+
realAuthority = HostAndPort.parseAuthority(authorityHeaderAsString, -1);
139+
computedAuthority = realAuthority;
138140
}
139141
CharSequence hostHeader = null;
140-
if (authority == null) {
142+
if (computedAuthority == null) {
141143
hostHeader = headers.getAndRemove(HttpHeaders.HOST);
142144
if (hostHeader != null) {
143-
authority = HostAndPort.parseAuthority(hostHeader.toString(), -1);
145+
computedAuthority = HostAndPort.parseAuthority(hostHeader.toString(), -1);
144146
}
145147
}
146148
CharSequence pathHeader = headers.getAndRemove(HttpHeaders.PSEUDO_PATH);
@@ -151,7 +153,8 @@ private Http2ServerStream createStream(Http2Headers headers, boolean streamEnded
151153
headers,
152154
schemeHeader != null ? schemeHeader.toString() : null,
153155
authorityHeader != null || hostHeader != null,
154-
authority,
156+
realAuthority,
157+
computedAuthority,
155158
methodHeader != null ? HttpMethod.valueOf(methodHeader.toString()) : null,
156159
pathHeader != null ? pathHeader.toString() : null,
157160
options.getTracingPolicy(), streamEnded);

src/main/java/io/vertx/core/http/impl/Http2ServerRequest.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,12 @@ public String host() {
328328

329329
@Override
330330
public @Nullable HostAndPort authority() {
331-
return stream.authority;
331+
return stream.authority();
332+
}
333+
334+
@Override
335+
public @Nullable HostAndPort authority(boolean real) {
336+
return stream.authority(real);
332337
}
333338

334339
@Override

src/main/java/io/vertx/core/http/impl/Http2ServerResponse.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -727,7 +727,7 @@ public Future<HttpServerResponse> push(HttpMethod method, HostAndPort authority,
727727
throw new IllegalStateException("A push response cannot promise another push");
728728
}
729729
if (authority == null) {
730-
authority = stream.authority;
730+
authority = stream.authority();
731731
}
732732
synchronized (conn) {
733733
checkValid();
@@ -747,7 +747,7 @@ public Future<HttpServerResponse> push(HttpMethod method, String authority, Stri
747747
hostAndPort = HostAndPort.parseAuthority(authority, -1);
748748
}
749749
if (hostAndPort == null) {
750-
hostAndPort = stream.authority;
750+
hostAndPort = stream.authority();
751751
}
752752
synchronized (conn) {
753753
checkValid();

src/main/java/io/vertx/core/http/impl/Http2ServerStream.java

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ class Http2ServerStream extends VertxHttp2Stream<Http2ServerConnection> {
4141
protected final String uri;
4242
protected final String host; // deprecated
4343
protected final boolean hasAuthority;
44-
protected final HostAndPort authority;
44+
private final HostAndPort computedAuthority;
45+
private final HostAndPort realAuthority;
4546
private final TracingPolicy tracingPolicy;
4647
private Object metric;
4748
private Object trace;
@@ -64,7 +65,8 @@ class Http2ServerStream extends VertxHttp2Stream<Http2ServerConnection> {
6465
this.scheme = null;
6566
this.host = null;
6667
this.hasAuthority = false;
67-
this.authority = null;
68+
this.computedAuthority = null;
69+
this.realAuthority = null;
6870
this.tracingPolicy = tracingPolicy;
6971
this.halfClosedRemote = halfClosedRemote;
7072
}
@@ -74,7 +76,8 @@ class Http2ServerStream extends VertxHttp2Stream<Http2ServerConnection> {
7476
Http2Headers headers,
7577
String scheme,
7678
boolean hasAuthority,
77-
HostAndPort authority,
79+
HostAndPort realAuthority,
80+
HostAndPort computedAuthority,
7881
HttpMethod method,
7982
String uri,
8083
TracingPolicy tracingPolicy,
@@ -84,8 +87,9 @@ class Http2ServerStream extends VertxHttp2Stream<Http2ServerConnection> {
8487
this.scheme = scheme;
8588
this.headers = headers;
8689
this.hasAuthority = hasAuthority;
87-
this.authority = authority;
88-
this.host = authority != null ? authority.toString() : null;
90+
this.realAuthority = realAuthority;
91+
this.computedAuthority = computedAuthority;
92+
this.host = computedAuthority != null ? computedAuthority.toString() : null;
8993
this.uri = uri;
9094
this.method = method;
9195
this.tracingPolicy = tracingPolicy;
@@ -105,6 +109,14 @@ void registerMetrics() {
105109
}
106110
}
107111

112+
public HostAndPort authority() {
113+
return computedAuthority;
114+
}
115+
116+
public HostAndPort authority(boolean real) {
117+
return real ? realAuthority : computedAuthority;
118+
}
119+
108120
@Override
109121
void onHeaders(Http2Headers headers, StreamPriority streamPriority) {
110122
if (streamPriority != null) {

src/main/java/io/vertx/core/http/impl/HttpServerRequestWrapper.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,11 @@ public HostAndPort authority() {
118118
return delegate.authority();
119119
}
120120

121+
@Override
122+
public @Nullable HostAndPort authority(boolean real) {
123+
return delegate.authority(real);
124+
}
125+
121126
@Override
122127
public boolean isValidAuthority() {
123128
return delegate.isValidAuthority();

src/test/java/io/vertx/core/http/Http2ClientTest.java

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,7 @@ public void testOverrideAuthority() throws Exception {
346346
assertEquals("localhost:4444", req.host());
347347
assertEquals("localhost", req.authority().host());
348348
assertEquals(4444, req.authority().port());
349+
assertEquals(req.authority(), req.authority(true));
349350
req.response().end();
350351
});
351352
startServer(testAddress);
@@ -360,26 +361,19 @@ public void testOverrideAuthority() throws Exception {
360361

361362
@Test
362363
public void testNoAuthority() throws Exception {
363-
ServerBootstrap bootstrap = createH2Server((decoder, encoder) -> new Http2EventAdapter() {
364-
@Override
365-
public void onHeadersRead(ChannelHandlerContext ctx, int streamId, Http2Headers headers, int streamDependency, short weight, boolean exclusive, int padding, boolean endStream) throws Http2Exception {
366-
vertx.runOnContext(v -> {
367-
assertNull(headers.authority());
368-
encoder.writeHeaders(ctx, streamId, new DefaultHttp2Headers().status("200"), 0, true, ctx.newPromise());
369-
ctx.flush();
370-
});
371-
}
364+
server.requestHandler(req -> {
365+
assertEquals("fromHost", req.authority().host());
366+
assertEquals(1234, req.authority().port());
367+
assertNull(req.authority(true));
368+
req.response().end();
372369
});
373-
ChannelFuture s = bootstrap.bind(DEFAULT_HTTPS_HOST, DEFAULT_HTTPS_PORT).sync();
370+
startServer(testAddress);
374371
client.request(new RequestOptions().setServer(testAddress)
375-
.setPort(4444)
376-
.setHost("localhost")
377-
)
378-
.compose(request -> {
379-
request.authority(null);
380-
return request.send();
381-
})
382-
.onComplete(onSuccess(resp -> testComplete()));
372+
.addHeader("Host", "fromHost:1234")
373+
)
374+
.onSuccess(req -> req.authority(null))
375+
.compose(HttpClientRequest::send)
376+
.onComplete(onSuccess(resp -> testComplete()));
383377
await();
384378
}
385379

0 commit comments

Comments
 (0)