ForwardedHeaderFilter handles query+fragment correctly

Issue: SPR-16506
This commit is contained in:
Rossen Stoyanchev 2018-02-16 11:10:50 -05:00
parent dcf5c646be
commit 6920a1f958
2 changed files with 33 additions and 2 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -324,6 +324,24 @@ public class ForwardedHeaderFilter extends OncePerRequestFilter {
return;
}
String fragment = null;
int fragmentIndex = location.indexOf('#');
if (fragmentIndex != -1) {
if (location.length() > fragmentIndex) {
fragment = location.substring(fragmentIndex + 1);
}
location = location.substring(0, fragmentIndex);
}
String query = null;
int queryIndex = location.indexOf('?');
if (queryIndex != -1) {
if (location.length() > queryIndex) {
query = location.substring(queryIndex + 1);
}
location = location.substring(0, queryIndex);
}
// Relative to Servlet container root or to current request
String path = (location.startsWith(FOLDER_SEPARATOR) ? location :
StringUtils.applyRelativePath(this.request.getRequestURI(), location));
@ -331,6 +349,8 @@ public class ForwardedHeaderFilter extends OncePerRequestFilter {
String result = UriComponentsBuilder
.fromHttpRequest(new ServletServerHttpRequest(this.request))
.replacePath(path)
.replaceQuery(query)
.fragment(fragment)
.build().normalize().toUriString();
super.sendRedirect(result);

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -301,6 +301,17 @@ public class ForwardedHeaderFilterTests {
assertEquals("https://example.com/foo/bar", redirectedUrl);
}
@Test // SPR-16506
public void sendRedirectWithAbsolutePathQueryParamAndFragment() throws Exception {
this.request.addHeader(X_FORWARDED_PROTO, "https");
this.request.addHeader(X_FORWARDED_HOST, "example.com");
this.request.addHeader(X_FORWARDED_PORT, "443");
this.request.setQueryString("oldqp=1");
String redirectedUrl = sendRedirect("/foo/bar?newqp=2#fragment");
assertEquals("https://example.com/foo/bar?newqp=2#fragment", redirectedUrl);
}
@Test
public void sendRedirectWithContextPath() throws Exception {
this.request.addHeader(X_FORWARDED_PROTO, "https");