TransportHttp: resolve redirect URIs from the "Location" header
The "Location" header in a redirect response may contain a relative URI. Resolve it against the URI the request was made. Bug: 550033 Change-Id: I29de07dfbbbc794090821b7c190cb2cf662c5a60 Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
This commit is contained in:
parent
39e83a6583
commit
8c7f1a699a
|
@ -56,6 +56,7 @@
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
import java.text.MessageFormat;
|
import java.text.MessageFormat;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -340,6 +341,23 @@ public void init(FilterConfig filterConfig)
|
||||||
// empty
|
// empty
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String local(String url, boolean toLocal) {
|
||||||
|
if (!toLocal) {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
URI u = new URI(url);
|
||||||
|
String fragment = u.getRawFragment();
|
||||||
|
if (fragment != null) {
|
||||||
|
return u.getRawPath() + '#' + fragment;
|
||||||
|
} else {
|
||||||
|
return u.getRawPath();
|
||||||
|
}
|
||||||
|
} catch (URISyntaxException e) {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doFilter(ServletRequest request,
|
public void doFilter(ServletRequest request,
|
||||||
ServletResponse response, FilterChain chain)
|
ServletResponse response, FilterChain chain)
|
||||||
|
@ -352,6 +370,11 @@ public void doFilter(ServletRequest request,
|
||||||
.append(httpServletRequest.getQueryString());
|
.append(httpServletRequest.getQueryString());
|
||||||
}
|
}
|
||||||
String urlString = fullUrl.toString();
|
String urlString = fullUrl.toString();
|
||||||
|
boolean localRedirect = false;
|
||||||
|
if (urlString.contains("/local")) {
|
||||||
|
urlString = urlString.replace("/local", "");
|
||||||
|
localRedirect = true;
|
||||||
|
}
|
||||||
if (urlString.contains("/loop/")) {
|
if (urlString.contains("/loop/")) {
|
||||||
urlString = urlString.replace("/loop/", "/loop/x/");
|
urlString = urlString.replace("/loop/", "/loop/x/");
|
||||||
if (urlString.contains("/loop/x/x/x/x/x/x/x/x/")) {
|
if (urlString.contains("/loop/x/x/x/x/x/x/x/x/")) {
|
||||||
|
@ -362,7 +385,7 @@ public void doFilter(ServletRequest request,
|
||||||
httpServletResponse.setStatus(
|
httpServletResponse.setStatus(
|
||||||
HttpServletResponse.SC_MOVED_TEMPORARILY);
|
HttpServletResponse.SC_MOVED_TEMPORARILY);
|
||||||
httpServletResponse.setHeader(HttpSupport.HDR_LOCATION,
|
httpServletResponse.setHeader(HttpSupport.HDR_LOCATION,
|
||||||
urlString);
|
local(urlString, localRedirect));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int responseCode = HttpServletResponse.SC_MOVED_PERMANENTLY;
|
int responseCode = HttpServletResponse.SC_MOVED_PERMANENTLY;
|
||||||
|
@ -392,9 +415,10 @@ public void doFilter(ServletRequest request,
|
||||||
targetContext = matcher.group(1);
|
targetContext = matcher.group(1);
|
||||||
}
|
}
|
||||||
urlString = urlString.replace("/redirect", targetContext);
|
urlString = urlString.replace("/redirect", targetContext);
|
||||||
|
|
||||||
}
|
}
|
||||||
httpServletResponse.setHeader(HttpSupport.HDR_LOCATION,
|
httpServletResponse.setHeader(HttpSupport.HDR_LOCATION,
|
||||||
urlString);
|
local(urlString, localRedirect));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -561,7 +585,15 @@ public void testInitialClone_Small() throws Exception {
|
||||||
|
|
||||||
private void initialClone_Redirect(int nofRedirects, int code)
|
private void initialClone_Redirect(int nofRedirects, int code)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
|
initialClone_Redirect(nofRedirects, code, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initialClone_Redirect(int nofRedirects, int code,
|
||||||
|
boolean localRedirect) throws Exception {
|
||||||
URIish cloneFrom = redirectURI;
|
URIish cloneFrom = redirectURI;
|
||||||
|
if (localRedirect) {
|
||||||
|
cloneFrom = extendPath(cloneFrom, "/local");
|
||||||
|
}
|
||||||
if (code != 301 || nofRedirects > 1) {
|
if (code != 301 || nofRedirects > 1) {
|
||||||
cloneFrom = extendPath(cloneFrom,
|
cloneFrom = extendPath(cloneFrom,
|
||||||
"/response/" + nofRedirects + "/" + code);
|
"/response/" + nofRedirects + "/" + code);
|
||||||
|
@ -614,6 +646,11 @@ public void testInitialClone_Redirect301Small() throws Exception {
|
||||||
initialClone_Redirect(1, 301);
|
initialClone_Redirect(1, 301);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInitialClone_Redirect301Local() throws Exception {
|
||||||
|
initialClone_Redirect(1, 301, true);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testInitialClone_Redirect302Small() throws Exception {
|
public void testInitialClone_Redirect302Small() throws Exception {
|
||||||
initialClone_Redirect(1, 302);
|
initialClone_Redirect(1, 302);
|
||||||
|
|
|
@ -77,6 +77,7 @@
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.Proxy;
|
import java.net.Proxy;
|
||||||
import java.net.ProxySelector;
|
import java.net.ProxySelector;
|
||||||
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.nio.file.InvalidPathException;
|
import java.nio.file.InvalidPathException;
|
||||||
|
@ -593,7 +594,8 @@ private HttpConnection connect(String service)
|
||||||
JGitText.get().redirectsOff,
|
JGitText.get().redirectsOff,
|
||||||
Integer.valueOf(status)));
|
Integer.valueOf(status)));
|
||||||
}
|
}
|
||||||
URIish newUri = redirect(conn.getHeaderField(HDR_LOCATION),
|
URIish newUri = redirect(u,
|
||||||
|
conn.getHeaderField(HDR_LOCATION),
|
||||||
Constants.INFO_REFS, redirects++);
|
Constants.INFO_REFS, redirects++);
|
||||||
setURI(newUri);
|
setURI(newUri);
|
||||||
u = getServiceURL(service);
|
u = getServiceURL(service);
|
||||||
|
@ -804,7 +806,8 @@ private void updateSslVerifyUser(boolean value) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private URIish redirect(String location, String checkFor, int redirects)
|
private URIish redirect(URL currentUrl, String location, String checkFor,
|
||||||
|
int redirects)
|
||||||
throws TransportException {
|
throws TransportException {
|
||||||
if (location == null || location.isEmpty()) {
|
if (location == null || location.isEmpty()) {
|
||||||
throw new TransportException(uri,
|
throw new TransportException(uri,
|
||||||
|
@ -818,13 +821,16 @@ private URIish redirect(String location, String checkFor, int redirects)
|
||||||
location));
|
location));
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
if (!isValidRedirect(baseUrl, location, checkFor)) {
|
URI redirectTo = new URI(location);
|
||||||
|
redirectTo = currentUrl.toURI().resolve(redirectTo);
|
||||||
|
String redirected = redirectTo.toASCIIString();
|
||||||
|
if (!isValidRedirect(baseUrl, redirected, checkFor)) {
|
||||||
throw new TransportException(uri,
|
throw new TransportException(uri,
|
||||||
MessageFormat.format(JGitText.get().redirectBlocked,
|
MessageFormat.format(JGitText.get().redirectBlocked,
|
||||||
baseUrl, location));
|
baseUrl, redirected));
|
||||||
}
|
}
|
||||||
location = location.substring(0, location.indexOf(checkFor));
|
redirected = redirected.substring(0, redirected.indexOf(checkFor));
|
||||||
URIish result = new URIish(location);
|
URIish result = new URIish(redirected);
|
||||||
if (LOG.isInfoEnabled()) {
|
if (LOG.isInfoEnabled()) {
|
||||||
LOG.info(MessageFormat.format(JGitText.get().redirectHttp,
|
LOG.info(MessageFormat.format(JGitText.get().redirectHttp,
|
||||||
uri.setPass(null),
|
uri.setPass(null),
|
||||||
|
@ -1454,7 +1460,8 @@ void sendRequest() throws IOException {
|
||||||
// Let openResponse() issue an error
|
// Let openResponse() issue an error
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
currentUri = redirect(conn.getHeaderField(HDR_LOCATION),
|
currentUri = redirect(conn.getURL(),
|
||||||
|
conn.getHeaderField(HDR_LOCATION),
|
||||||
'/' + serviceName, redirects++);
|
'/' + serviceName, redirects++);
|
||||||
try {
|
try {
|
||||||
baseUrl = toURL(currentUri);
|
baseUrl = toURL(currentUri);
|
||||||
|
|
Loading…
Reference in New Issue