Skip to content

Commit 005e6df

Browse files
committed
Merge #2714 into 1.1.4
2 parents 25a6216 + a3e6d37 commit 005e6df

File tree

6 files changed

+179
-41
lines changed

6 files changed

+179
-41
lines changed

reactor-netty-http/build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,8 @@ task japicmp(type: JapicmpTask) {
241241

242242
compatibilityChangeExcludes = [ "METHOD_NEW_DEFAULT" ]
243243
methodExcludes = [
244+
'reactor.netty.http.server.ConnectionInformation#hostName()',
245+
'reactor.netty.http.server.ConnectionInformation#hostPort()'
244246
]
245247
}
246248

reactor-netty-http/src/main/java/reactor/netty/http/server/ConnectionInfo.java

Lines changed: 45 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2018-2021 VMware, Inc. or its affiliates, All Rights Reserved.
2+
* Copyright (c) 2018-2023 VMware, Inc. or its affiliates, All Rights Reserved.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -21,6 +21,7 @@
2121

2222
import io.netty.channel.Channel;
2323
import io.netty.channel.socket.SocketChannel;
24+
import io.netty.handler.codec.http.HttpHeaderNames;
2425
import io.netty.handler.codec.http.HttpRequest;
2526
import reactor.util.annotation.Nullable;
2627

@@ -41,43 +42,59 @@
4142
* @see <a href="https://tools.ietf.org/html/rfc7239">rfc7239</a>
4243
*/
4344
public final class ConnectionInfo {
45+
static final int DEFAULT_HTTP_PORT = 80;
46+
static final int DEFAULT_HTTPS_PORT = 443;
47+
static final String DEFAULT_HOST_NAME = "localhost";
4448

4549
final InetSocketAddress hostAddress;
4650

4751
final InetSocketAddress remoteAddress;
4852

4953
final String scheme;
5054

51-
@Nullable
55+
final String hostName;
56+
57+
final int hostPort;
58+
5259
static ConnectionInfo from(Channel channel, HttpRequest request, boolean secured, SocketAddress remoteAddress,
5360
@Nullable BiFunction<ConnectionInfo, HttpRequest, ConnectionInfo> forwardedHeaderHandler) {
61+
String hostName = DEFAULT_HOST_NAME;
62+
int hostPort = secured ? DEFAULT_HTTPS_PORT : DEFAULT_HTTP_PORT;
63+
String scheme = secured ? "https" : "http";
64+
65+
String header = request.headers().get(HttpHeaderNames.HOST);
66+
if (header != null) {
67+
hostName = header;
68+
int portIndex = header.charAt(0) == '[' ? header.indexOf(':', header.indexOf(']')) : header.indexOf(':');
69+
if (portIndex != -1) {
70+
hostName = header.substring(0, portIndex);
71+
hostPort = Integer.parseInt(header.substring(portIndex + 1));
72+
}
73+
}
74+
5475
if (!(remoteAddress instanceof InetSocketAddress)) {
55-
return null;
76+
return new ConnectionInfo(hostName, hostPort, scheme);
5677
}
5778
else {
58-
ConnectionInfo connectionInfo = ConnectionInfo.newConnectionInfo(channel, secured, (InetSocketAddress) remoteAddress);
79+
ConnectionInfo connectionInfo =
80+
new ConnectionInfo(((SocketChannel) channel).localAddress(), hostName, hostPort,
81+
(InetSocketAddress) remoteAddress, scheme);
5982
if (forwardedHeaderHandler != null) {
6083
return forwardedHeaderHandler.apply(connectionInfo, request);
6184
}
6285
return connectionInfo;
6386
}
6487
}
6588

66-
/**
67-
* Retrieve the connection information from the current connection directly
68-
* @param c the current channel
69-
* @param secured is transport secure (SSL)
70-
* @return the connection information
71-
*/
72-
static ConnectionInfo newConnectionInfo(Channel c, boolean secured, InetSocketAddress remoteAddress) {
73-
SocketChannel channel = (SocketChannel) c;
74-
InetSocketAddress hostAddress = channel.localAddress();
75-
String scheme = secured ? "https" : "http";
76-
return new ConnectionInfo(hostAddress, remoteAddress, scheme);
89+
ConnectionInfo(String hostName, int hostPort, String scheme) {
90+
this(null, hostName, hostPort, null, scheme);
7791
}
7892

79-
ConnectionInfo(InetSocketAddress hostAddress, InetSocketAddress remoteAddress, String scheme) {
93+
ConnectionInfo(@Nullable InetSocketAddress hostAddress, String hostName, int hostPort,
94+
@Nullable InetSocketAddress remoteAddress, String scheme) {
8095
this.hostAddress = hostAddress;
96+
this.hostName = hostName;
97+
this.hostPort = hostPort;
8198
this.remoteAddress = remoteAddress;
8299
this.scheme = scheme;
83100
}
@@ -86,6 +103,7 @@ static ConnectionInfo newConnectionInfo(Channel c, boolean secured, InetSocketAd
86103
* Return the host address of the connection.
87104
* @return the host address
88105
*/
106+
@Nullable
89107
public InetSocketAddress getHostAddress() {
90108
return hostAddress;
91109
}
@@ -94,6 +112,7 @@ public InetSocketAddress getHostAddress() {
94112
* Return the remote address of the connection.
95113
* @return the remote address
96114
*/
115+
@Nullable
97116
public InetSocketAddress getRemoteAddress() {
98117
return remoteAddress;
99118
}
@@ -113,7 +132,7 @@ public String getScheme() {
113132
*/
114133
public ConnectionInfo withHostAddress(InetSocketAddress hostAddress) {
115134
requireNonNull(hostAddress, "hostAddress");
116-
return new ConnectionInfo(hostAddress, this.remoteAddress, this.scheme);
135+
return new ConnectionInfo(hostAddress, hostAddress.getHostString(), hostAddress.getPort(), this.remoteAddress, this.scheme);
117136
}
118137

119138
/**
@@ -123,7 +142,7 @@ public ConnectionInfo withHostAddress(InetSocketAddress hostAddress) {
123142
*/
124143
public ConnectionInfo withRemoteAddress(InetSocketAddress remoteAddress) {
125144
requireNonNull(remoteAddress, "remoteAddress");
126-
return new ConnectionInfo(this.hostAddress, remoteAddress, this.scheme);
145+
return new ConnectionInfo(this.hostAddress, this.hostName, this.hostPort, remoteAddress, this.scheme);
127146
}
128147

129148
/**
@@ -133,7 +152,14 @@ public ConnectionInfo withRemoteAddress(InetSocketAddress remoteAddress) {
133152
*/
134153
public ConnectionInfo withScheme(String scheme) {
135154
requireNonNull(scheme, "scheme");
136-
return new ConnectionInfo(this.hostAddress, this.remoteAddress, scheme);
155+
return new ConnectionInfo(this.hostAddress, this.hostName, this.hostPort, this.remoteAddress, scheme);
156+
}
157+
158+
String getHostName() {
159+
return hostName;
137160
}
138161

162+
int getHostPort() {
163+
return hostPort;
164+
}
139165
}

reactor-netty-http/src/main/java/reactor/netty/http/server/ConnectionInformation.java

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2022 VMware, Inc. or its affiliates, All Rights Reserved.
2+
* Copyright (c) 2022-2023 VMware, Inc. or its affiliates, All Rights Reserved.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -74,4 +74,24 @@ public interface ConnectionInformation {
7474
* @return the protocol scheme
7575
*/
7676
String connectionScheme();
77+
78+
/**
79+
* Returns the host name derived from the {@code Host}/{@code X-Forwarded-Host}/{@code Forwarded} header
80+
* associated with this request.
81+
*
82+
* @return the host name derived from the {@code Host}/{@code X-Forwarded-Host}/{@code Forwarded} header
83+
* associated with this request.
84+
* @since 1.0.29
85+
*/
86+
String hostName();
87+
88+
/**
89+
* Returns the host port derived from the {@code Host}/{@code X-Forwarded-*}/{@code Forwarded} header
90+
* associated with this request.
91+
*
92+
* @return the host port derived from the {@code Host}/{@code X-Forwarded-*}/{@code Forwarded} header
93+
* associated with this request.
94+
* @since 1.0.29
95+
*/
96+
int hostPort();
7797
}

reactor-netty-http/src/main/java/reactor/netty/http/server/DefaultHttpForwardedHeaderHandler.java

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@
2222
import io.netty.handler.codec.http.HttpRequest;
2323
import reactor.netty.transport.AddressUtils;
2424

25+
import static reactor.netty.http.server.ConnectionInfo.DEFAULT_HTTPS_PORT;
26+
import static reactor.netty.http.server.ConnectionInfo.DEFAULT_HTTP_PORT;
27+
2528
/**
2629
* @author Andrey Shlykov
2730
* @since 0.9.12
@@ -62,16 +65,16 @@ public ConnectionInfo apply(ConnectionInfo connectionInfo, HttpRequest request)
6265

6366
private ConnectionInfo parseForwardedInfo(ConnectionInfo connectionInfo, String forwardedHeader) {
6467
String forwarded = forwardedHeader.split(",", 2)[0];
65-
Matcher hostMatcher = FORWARDED_HOST_PATTERN.matcher(forwarded);
66-
if (hostMatcher.find()) {
67-
connectionInfo = connectionInfo.withHostAddress(
68-
AddressUtils.parseAddress(hostMatcher.group(1), connectionInfo.getHostAddress().getPort(),
69-
DEFAULT_FORWARDED_HEADER_VALIDATION));
70-
}
7168
Matcher protoMatcher = FORWARDED_PROTO_PATTERN.matcher(forwarded);
7269
if (protoMatcher.find()) {
7370
connectionInfo = connectionInfo.withScheme(protoMatcher.group(1).trim());
7471
}
72+
int port = connectionInfo.getScheme().equalsIgnoreCase("https") ? DEFAULT_HTTPS_PORT : DEFAULT_HTTP_PORT;
73+
Matcher hostMatcher = FORWARDED_HOST_PATTERN.matcher(forwarded);
74+
if (hostMatcher.find()) {
75+
connectionInfo = connectionInfo.withHostAddress(
76+
AddressUtils.parseAddress(hostMatcher.group(1), port, DEFAULT_FORWARDED_HEADER_VALIDATION));
77+
}
7578
Matcher forMatcher = FORWARDED_FOR_PATTERN.matcher(forwarded);
7679
if (forMatcher.find()) {
7780
connectionInfo = connectionInfo.withRemoteAddress(
@@ -87,9 +90,13 @@ private ConnectionInfo parseXForwardedInfo(ConnectionInfo connectionInfo, HttpRe
8790
connectionInfo = connectionInfo.withRemoteAddress(
8891
AddressUtils.parseAddress(ipHeader.split(",", 2)[0], connectionInfo.getRemoteAddress().getPort()));
8992
}
93+
String protoHeader = request.headers().get(X_FORWARDED_PROTO_HEADER);
94+
if (protoHeader != null) {
95+
connectionInfo = connectionInfo.withScheme(protoHeader.split(",", 2)[0].trim());
96+
}
9097
String hostHeader = request.headers().get(X_FORWARDED_HOST_HEADER);
9198
if (hostHeader != null) {
92-
int port = connectionInfo.getHostAddress().getPort();
99+
int port = connectionInfo.getScheme().equalsIgnoreCase("https") ? DEFAULT_HTTPS_PORT : DEFAULT_HTTP_PORT;
93100
connectionInfo = connectionInfo.withHostAddress(
94101
AddressUtils.parseAddress(hostHeader.split(",", 2)[0].trim(), port, DEFAULT_FORWARDED_HEADER_VALIDATION));
95102
String portHeader = request.headers().get(X_FORWARDED_PORT_HEADER);
@@ -105,10 +112,6 @@ else if (DEFAULT_FORWARDED_HEADER_VALIDATION) {
105112
AddressUtils.createUnresolved(connectionInfo.getHostAddress().getHostString(), port));
106113
}
107114
}
108-
String protoHeader = request.headers().get(X_FORWARDED_PROTO_HEADER);
109-
if (protoHeader != null) {
110-
connectionInfo = connectionInfo.withScheme(protoHeader.split(",", 2)[0].trim());
111-
}
112115
return connectionInfo;
113116
}
114117

reactor-netty-http/src/main/java/reactor/netty/http/server/HttpServerOperations.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,9 @@
9696
import static io.netty.buffer.Unpooled.EMPTY_BUFFER;
9797
import static io.netty.handler.codec.http.HttpUtil.isTransferEncodingChunked;
9898
import static reactor.netty.ReactorNetty.format;
99+
import static reactor.netty.http.server.ConnectionInfo.DEFAULT_HOST_NAME;
100+
import static reactor.netty.http.server.ConnectionInfo.DEFAULT_HTTPS_PORT;
101+
import static reactor.netty.http.server.ConnectionInfo.DEFAULT_HTTP_PORT;
99102
import static reactor.netty.http.server.HttpServerFormDecoderProvider.DEFAULT_FORM_DECODER_SPEC;
100103
import static reactor.netty.http.server.HttpServerState.REQUEST_DECODING_FAILED;
101104

@@ -478,6 +481,18 @@ public String connectionScheme() {
478481
return scheme;
479482
}
480483

484+
@Override
485+
public String hostName() {
486+
return connectionInfo != null ? connectionInfo.getHostName() : DEFAULT_HOST_NAME;
487+
}
488+
489+
@Override
490+
public int hostPort() {
491+
return connectionInfo != null ?
492+
connectionInfo.getHostPort() :
493+
scheme().equalsIgnoreCase("https") ? DEFAULT_HTTPS_PORT : DEFAULT_HTTP_PORT;
494+
}
495+
481496
@Override
482497
public HttpHeaders responseHeaders() {
483498
return responseHeaders;

0 commit comments

Comments
 (0)