Skip to content

Commit 176ee0a

Browse files
committed
Handle authority value computation in Http2ServerRequest instead of the headers implementation.
1 parent c58fbc6 commit 176ee0a

File tree

7 files changed

+80
-32
lines changed

7 files changed

+80
-32
lines changed

vertx-core/src/main/java/io/vertx/core/http/impl/http2/Http2HeadersMultiMap.java

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,7 @@ private Http2HeadersMultiMap(boolean mutable, Headers<CharSequence, CharSequence
5757

5858
private Integer status;
5959
private HttpMethod method;
60-
private HostAndPort computedAuthority;
61-
private HostAndPort realAuthority;
60+
private HostAndPort authority;
6261
private String uri;
6362
private String scheme;
6463

@@ -76,25 +75,25 @@ public boolean validate(boolean isRequest) {
7675
CharSequence pathHeader = headers.get(HttpHeaders.PSEUDO_PATH);
7776
String uri = pathHeader != null ? pathHeader.toString() : null;
7877

79-
HostAndPort currentAuthority = null;
80-
String authorityHeaderAsString;
78+
HostAndPort authority;
8179
CharSequence authorityHeader = headers.get(HttpHeaders.PSEUDO_AUTHORITY);
8280
if (authorityHeader != null) {
83-
authorityHeaderAsString = authorityHeader.toString();
84-
this.realAuthority = HostAndPort.parseAuthority(authorityHeaderAsString, -1);
85-
currentAuthority = this.realAuthority;
81+
String authorityHeaderAsString = authorityHeader.toString();
82+
authority = HostAndPort.parseAuthority(authorityHeaderAsString, -1);
83+
} else {
84+
authority = null;
8685
}
8786

87+
HostAndPort authorityPresence;
8888
CharSequence hostHeader = headers.get(HttpHeaders.HOST);
89-
if (currentAuthority == null) {
90-
headers.remove(HttpHeaders.HOST);
91-
if (hostHeader != null) {
92-
currentAuthority = HostAndPort.parseAuthority(hostHeader.toString(), -1);
93-
}
89+
if (authority == null && hostHeader != null) {
90+
authorityPresence = HostAndPort.parseAuthority(hostHeader.toString(), -1);
91+
} else {
92+
authorityPresence = authority;
9493
}
9594

9695
if (method == HttpMethod.CONNECT) {
97-
if (scheme != null || uri != null || currentAuthority == null) {
96+
if (scheme != null || uri != null || authorityPresence == null) {
9897
return false;
9998
}
10099
} else {
@@ -105,20 +104,21 @@ public boolean validate(boolean isRequest) {
105104

106105
boolean hasAuthority = authorityHeader != null || hostHeader != null;
107106
if (hasAuthority) {
108-
if (currentAuthority == null) {
107+
if (authorityPresence == null) {
108+
// Malformed authority
109109
return false;
110110
}
111111
if (hostHeader != null) {
112112
HostAndPort host = HostAndPort.parseAuthority(hostHeader.toString(), -1);
113-
if (host == null || (!currentAuthority.host().equals(host.host()) || currentAuthority.port() != host.port())) {
113+
if (host == null || (!authorityPresence.host().equals(host.host()) || authorityPresence.port() != host.port())) {
114114
return false;
115115
}
116116
}
117117
}
118118

119119
this.method = method;
120120
this.uri = uri;
121-
this.computedAuthority = currentAuthority;
121+
this.authority = authority;
122122
this.scheme = scheme;
123123

124124
return true;
@@ -158,8 +158,8 @@ public Http2HeadersMultiMap prepare() {
158158
if (scheme != null) {
159159
headers.set(HttpHeaders.PSEUDO_SCHEME, scheme);
160160
}
161-
if (computedAuthority != null) {
162-
headers.set(HttpHeaders.PSEUDO_AUTHORITY, computedAuthority.toString(ssl));
161+
if (authority != null) {
162+
headers.set(HttpHeaders.PSEUDO_AUTHORITY, authority.toString(ssl));
163163
}
164164
if (scheme != null) {
165165
headers.set(HttpHeaders.PSEUDO_SCHEME, scheme);
@@ -207,16 +207,12 @@ public HttpMethod method() {
207207
}
208208

209209
public Http2HeadersMultiMap authority(HostAndPort authority) {
210-
this.computedAuthority = authority;
210+
this.authority = authority;
211211
return this;
212212
}
213213

214214
public HostAndPort authority() {
215-
return computedAuthority;
216-
}
217-
218-
public HostAndPort authority(boolean real) {
219-
return real ? realAuthority : computedAuthority;
215+
return authority;
220216
}
221217

222218
public String scheme() {

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

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,13 @@
1616
import io.netty.handler.codec.http.multipart.Attribute;
1717
import io.netty.handler.codec.http.multipart.HttpPostRequestDecoder;
1818
import io.netty.handler.codec.http.multipart.InterfaceHttpData;
19+
import io.netty.handler.codec.http2.Http2Headers;
1920
import io.vertx.codegen.annotations.Nullable;
2021
import io.vertx.core.Future;
2122
import io.vertx.core.Handler;
2223
import io.vertx.core.MultiMap;
2324
import io.vertx.core.buffer.Buffer;
25+
import io.vertx.core.http.HttpHeaders;
2426
import io.vertx.core.http.impl.HttpEventHandler;
2527
import io.vertx.core.http.impl.HttpRequestHead;
2628
import io.vertx.core.http.impl.HttpUtils;
@@ -61,6 +63,8 @@ public class Http2ServerRequest extends HttpServerRequestInternal {
6163

6264
// Accessed on context thread
6365
private MultiMap headersMap;
66+
private HostAndPort authority;
67+
private HostAndPort realAuthority;
6468
private Charset paramsCharset = StandardCharsets.UTF_8;
6569
private MultiMap params;
6670
private boolean semicolonIsNormalCharInParams;
@@ -108,7 +112,21 @@ private HttpEventHandler eventHandler(boolean create) {
108112
}
109113

110114
public void handleHeaders(HttpRequestHead headers) {
111-
this.headersMap = headers.headers;
115+
Http2HeadersMultiMap map = (Http2HeadersMultiMap)headers.headers;
116+
117+
realAuthority = headers.authority;
118+
authority = headers.authority;
119+
if (authority == null) {
120+
String hostHeader = headers.headers.get(HttpHeaders.HOST);
121+
if (hostHeader != null) {
122+
headers.headers.remove(HttpHeaders.HOST);
123+
authority = HostAndPort.parseAuthority(hostHeader, -1);
124+
}
125+
}
126+
127+
map.sanitize();
128+
129+
this.headersMap = map;
112130

113131
// Check expect header and implement 100 continue automatically
114132
CharSequence value = headersMap.get(HttpHeaderNames.EXPECT);
@@ -334,12 +352,12 @@ public String scheme() {
334352

335353
@Override
336354
public @Nullable HostAndPort authority() {
337-
return stream.authority();
355+
return authority;
338356
}
339357

340358
@Override
341359
public @Nullable HostAndPort authority(boolean real) {
342-
return stream.authority(real);
360+
return real ? realAuthority : authority;
343361
}
344362

345363
@Override

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,11 +118,11 @@ public String scheme() {
118118
}
119119

120120
public HostAndPort authority() {
121-
return requestHeaders.authority(false);
121+
return requestHeaders.authority();
122122
}
123123

124124
public HostAndPort authority(boolean real) {
125-
return requestHeaders.authority(real);
125+
return requestHeaders.authority();
126126
}
127127

128128
public Object metric() {

vertx-core/src/main/java/io/vertx/core/http/impl/http2/codec/Http2ServerConnectionImpl.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,6 @@ protected synchronized void onHeadersRead(int streamId, Http2Headers headers, St
125125
handler.writeReset(streamId, Http2Error.PROTOCOL_ERROR.code(), null);
126126
return;
127127
}
128-
headersMap.sanitize();
129128
if (streamId == 1 && handler.upgraded) {
130129
stream = createStream(headers, true);
131130
} else {

vertx-core/src/main/java/io/vertx/core/http/impl/http2/multiplex/Http2MultiplexServerConnection.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,6 @@ void receiveHeaders(ChannelHandlerContext chctx, Http2FrameStream frameStream, H
7979
if (handler == null) {
8080
chctx.writeAndFlush(new DefaultHttp2ResetFrame(Http2Error.REFUSED_STREAM.code()));
8181
} else {
82-
headersMap.sanitize();
8382
Http2ServerStream stream = new Http2ServerStream(this, serverMetrics, metric(),
8483
streamContextSupplier.get(), null);;
8584
stream.init(streamId, chctx.channel().isWritable());

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,7 @@ public void testOverrideAuthority() throws Exception {
382382
@Test
383383
public void testNoAuthority() throws Exception {
384384
server.requestHandler(req -> {
385+
assertNotNull("fromHost", req.authority());
385386
assertEquals("fromHost", req.authority().host());
386387
assertEquals(1234, req.authority().port());
387388
assertNull(req.authority(true));

vertx-core/src/test/java/io/vertx/tests/http/headers/Http2HeadersAdaptorsTest.java

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
import io.netty.handler.codec.http2.DefaultHttp2Headers;
1515
import io.vertx.core.MultiMap;
16+
import io.vertx.core.http.HttpMethod;
1617
import io.vertx.core.http.impl.http2.Http2HeadersMultiMap;
1718
import org.junit.Before;
1819
import org.junit.Ignore;
@@ -42,7 +43,7 @@ public void setUp() {
4243
}
4344

4445
@Override
45-
protected MultiMap newMultiMap() {
46+
protected Http2HeadersMultiMap newMultiMap() {
4647
return new Http2HeadersMultiMap(new DefaultHttp2Headers());
4748
}
4849

@@ -111,4 +112,38 @@ public void testEntries() {
111112
private void assertHeaderNames(String... expected) {
112113
assertEquals(new HashSet<>(Arrays.asList(expected)), headers.names().stream().map(CharSequence::toString).collect(Collectors.toSet()));
113114
}
115+
116+
private Http2HeadersMultiMap headers(HttpMethod method, String authority, String host) {
117+
DefaultHttp2Headers s = new DefaultHttp2Headers();
118+
s.set(":method", method.name());
119+
if (method != HttpMethod.CONNECT) {
120+
s.set(":path", "/");
121+
s.set(":scheme", "http");
122+
}
123+
if (authority != null) {
124+
s.set(":authority", authority);
125+
}
126+
if (host != null) {
127+
s.set("host", host);
128+
}
129+
return new Http2HeadersMultiMap(s);
130+
}
131+
132+
@Test
133+
public void testAuthorityValidation() {
134+
assertTrue(headers(HttpMethod.GET, null, null).validate(true));
135+
assertTrue(headers(HttpMethod.GET, "localhost:8080", null).validate(true));
136+
assertTrue(headers(HttpMethod.GET, null, "localhost:8080").validate(true));
137+
assertTrue(headers(HttpMethod.GET, "localhost:8080", "localhost:8080").validate(true));
138+
assertFalse(headers(HttpMethod.GET, "localhost:8080", "localhost:8081").validate(true));
139+
assertFalse(headers(HttpMethod.GET, "localhost:a", null).validate(true));
140+
assertFalse(headers(HttpMethod.GET, null, "localhost:a").validate(true));
141+
assertFalse(headers(HttpMethod.CONNECT, null, null).validate(true));
142+
assertTrue(headers(HttpMethod.CONNECT, "localhost:8080", null).validate(true));
143+
assertTrue(headers(HttpMethod.CONNECT, null, "localhost:8080").validate(true));
144+
assertTrue(headers(HttpMethod.CONNECT, "localhost:8080", "localhost:8080").validate(true));
145+
assertFalse(headers(HttpMethod.CONNECT, "localhost:8080", "localhost:8081").validate(true));
146+
assertFalse(headers(HttpMethod.CONNECT, "localhost:a", null).validate(true));
147+
assertFalse(headers(HttpMethod.CONNECT, null, "localhost:a").validate(true));
148+
}
114149
}

0 commit comments

Comments
 (0)