@@ -65,8 +65,10 @@ public abstract class ForwardedHeaderUtils {
6565 * Parse the "Forwarded" header.
6666 * @param uri the request {@code URI}
6767 * @param headers the HTTP headers to get the "Forwarded" header from
68- * @param remoteAddress for a default port for the parsed "for" value
69- * @param localAddress for a default port for the parsed "by" value
68+ * @param remoteAddress for a default port for the parsed "for" value.
69+ * If null and no port is specified in the header, 0 is returned.
70+ * @param localAddress for a default port for the parsed "by" value.
71+ * If null, the port indication from the 'uri' is used as the 'byAddress'.
7072 * @return a {@link ForwardedInfo} with the parse results
7173 * @since 6.1.29
7274 * @see <a href="https://tools.ietf.org/html/rfc7239">RFC 7239</a>
@@ -95,7 +97,7 @@ public static ForwardedInfo parseStandardHeader(URI uri, HttpHeaders headers,
9597
9698 String forValue = pairs .get ("for" );
9799 if (forValue != null ) {
98- forAddress = parseInetSocketAddress (forValue , getPortToUse (remoteAddress , uri ));
100+ forAddress = parseInetSocketAddress (forValue , getRemotePortFallback (remoteAddress ));
99101 }
100102 String byValue = pairs .get ("by" );
101103 if (byValue != null ) {
@@ -220,6 +222,10 @@ private static int getPortToUse(@Nullable InetSocketAddress address, URI uri) {
220222 return (address != null ? address .getPort () : "https" .equals (uri .getScheme ()) ? 443 : 80 );
221223 }
222224
225+ private static int getRemotePortFallback (@ Nullable InetSocketAddress address ) {
226+ return (address != null ? address .getPort () : 0 );
227+ }
228+
223229 private static InetSocketAddress parseInetSocketAddress (String value , int port ) {
224230 String host = value ;
225231 int portSeparatorIdx = value .lastIndexOf (':' );
@@ -247,7 +253,8 @@ private static InetSocketAddress parseInetSocketAddress(String value, int port)
247253 * {@code byAddress} in {@link ForwardedInfo} is always {@code null}.
248254 * @param uri the request {@code URI}
249255 * @param headers the HTTP headers to get the "Forwarded" header from
250- * @param remoteAddress for a default port for the parsed "for" value
256+ * @param remoteAddress for a default port for the parsed "for" value.
257+ * If null, port 0 is returned if not specified in the header.
251258 * @param localAddress for a default port for the parsed "by" value;
252259 * this argument is ignored currently and the byAddress is always {@code null}
253260 * @return a {@link ForwardedInfo} with the scheme, host, and port adapted
@@ -289,8 +296,7 @@ else if (isForwardedSslOn(headers)) {
289296 String host = getLeftMostValue (forHeader );
290297 boolean ipv6 = (host .indexOf (':' ) != -1 );
291298 host = (ipv6 && !host .startsWith ("[" ) && !host .endsWith ("]" ) ? "[" + host + "]" : host );
292- int port = getPortToUse (remoteAddress , uri );
293- forAddress = InetSocketAddress .createUnresolved (host , port );
299+ forAddress = InetSocketAddress .createUnresolved (host , getRemotePortFallback (remoteAddress ));
294300 }
295301
296302 return new ForwardedInfo (uriComponentsBuilder , forAddress , null );
@@ -371,11 +377,13 @@ else if (isForwardedSslOn(headers)) {
371377 /**
372378 * Parse the first "Forwarded: for=..." or "X-Forwarded-For" header value to
373379 * an {@code InetSocketAddress} representing the address of the client.
374- * @param uri the request {@code URI}
380+ * @param uri the request {@code URI} (not used)
375381 * @param headers the request headers that may contain forwarded headers
376382 * @param remoteAddress the current remote address
377383 * @return an {@code InetSocketAddress} with the extracted host and port, or
378- * {@code null} if the headers are not present
384+ * {@code null} if the headers are not present. If the address is present but
385+ * the port is omitted in the header, the port is taken from {@code remoteAddress}
386+ * if given, otherwise 0 is used.
379387 * @deprecated as of 7.1 in favor of {@link #parseStandardHeader} and
380388 * {@link #parseXForwardedHeaders}
381389 */
@@ -389,7 +397,7 @@ else if (isForwardedSslOn(headers)) {
389397 Matcher matcher = FORWARDED_FOR_PATTERN .matcher (forwardedToUse );
390398 if (matcher .find ()) {
391399 String value = matcher .group (1 ).trim ();
392- return parseInetSocketAddress (value , getPortToUse (remoteAddress , uri ));
400+ return parseInetSocketAddress (value , getRemotePortFallback (remoteAddress ));
393401 }
394402 }
395403
@@ -398,7 +406,7 @@ else if (isForwardedSslOn(headers)) {
398406 String host = getLeftMostValue (forHeader );
399407 boolean ipv6 = (host .indexOf (':' ) != -1 );
400408 host = (ipv6 && !host .startsWith ("[" ) && !host .endsWith ("]" ) ? "[" + host + "]" : host );
401- return InetSocketAddress .createUnresolved (host , getPortToUse (remoteAddress , uri ));
409+ return InetSocketAddress .createUnresolved (host , getRemotePortFallback (remoteAddress ));
402410 }
403411
404412 return null ;
@@ -411,7 +419,8 @@ else if (isForwardedSslOn(headers)) {
411419 * @param headers the request headers that may contain forwarded headers
412420 * @param localAddress the current local address
413421 * @return an {@code InetSocketAddress} with the extracted host and port, or
414- * {@code null} if the headers are not present
422+ * {@code null} if the headers are not present. A port number of '0' indicates
423+ * that the port is unspecified.
415424 * @since 7.0
416425 * @deprecated as of 7.1 in favor of {@link #parseStandardHeader} and
417426 * {@link #parseXForwardedHeaders}
0 commit comments