Fix trailing slash issue

Issue: SPR-15201
This commit is contained in:
Rossen Stoyanchev 2017-01-28 12:38:44 -05:00
parent ee861e8001
commit b487ed6748
3 changed files with 75 additions and 8 deletions

View File

@ -48,6 +48,8 @@ public class DefaultUriBuilderFactory implements UriBuilderFactory {
private EncodingMode encodingMode = EncodingMode.URI_COMPONENT;
private boolean parsePath = true;
/**
* Default constructor without a base URI.
@ -126,6 +128,28 @@ public class DefaultUriBuilderFactory implements UriBuilderFactory {
return this.encodingMode;
}
/**
* Whether to parse the path into path segments for the URI string passed
* into {@link #uriString(String)} or one of the expand methods.
* <p>Setting this property to {@code true} ensures that URI variables
* expanded into the path are subject to path segment encoding rules and
* "/" characters are percent-encoded. If set to {@code false} the path is
* kept as a full path and expanded URI variables will have "/" characters
* preserved.
* <p>By default this is set to {@code true}.
* @param parsePath whether to parse the path into path segments
*/
public void setParsePath(boolean parsePath) {
this.parsePath = parsePath;
}
/**
* Whether the handler is configured to parse the path into path segments.
*/
public boolean shouldParsePath() {
return this.parsePath;
}
// UriTemplateHandler
@ -158,16 +182,22 @@ public class DefaultUriBuilderFactory implements UriBuilderFactory {
private UriComponentsBuilder initUriComponentsBuilder(String uriTemplate) {
// Merge base URI with child URI template
UriComponentsBuilder result = baseUri.cloneBuilder();
UriComponents child = UriComponentsBuilder.fromUriString(uriTemplate).build();
result.uriComponents(child);
// Split path into path segments
List<String> pathList = result.build().getPathSegments();
String[] pathArray = pathList.toArray(new String[pathList.size()]);
result.replacePath(null);
result.pathSegment(pathArray);
if (shouldParsePath()) {
UriComponents uric = result.build();
String path = uric.getPath();
List<String> pathSegments = uric.getPathSegments();
result.replacePath(null);
result.pathSegment(pathSegments.toArray(new String[0]));
if (path != null && path.endsWith("/")) {
result.path("/");
}
}
return result;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2017 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.
@ -153,6 +153,21 @@ public class RestTemplateTests {
verify(response).close();
}
@Test // SPR-15201
public void uriTemplateWithTrailingSlash() throws Exception {
String url = "http://example.com/spring/";
given(requestFactory.createRequest(new URI(url), HttpMethod.GET)).willReturn(request);
given(request.execute()).willReturn(response);
given(errorHandler.hasError(response)).willReturn(false);
HttpStatus status = HttpStatus.OK;
given(response.getStatusCode()).willReturn(status);
given(response.getStatusText()).willReturn(status.getReasonPhrase());
template.execute(url, HttpMethod.GET, null, null);
verify(response).close();
}
@Test
public void errorHandling() throws Exception {
given(requestFactory.createRequest(new URI("http://example.com"), HttpMethod.GET)).willReturn(request);

View File

@ -127,10 +127,32 @@ public class DefaultUriBuilderFactoryTests {
}
@Test
public void initialPathSplitIntoPathSegments() throws Exception {
public void parsePathWithDefaultSettings() throws Exception {
DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory("/foo/{bar}");
URI uri = factory.uriString("/baz/{id}").build("a/b", "c/d");
assertEquals("/foo/a%2Fb/baz/c%2Fd", uri.toString());
}
@Test
public void parsePathIsTurnedOff() throws Exception {
DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory("/foo/{bar}");
factory.setParsePath(false);
URI uri = factory.uriString("/baz/{id}").build("a/b", "c/d");
assertEquals("/foo/a/b/baz/c/d", uri.toString());
}
@Test // SPR-15201
public void pathWithTrailingSlash() throws Exception {
DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory();
URI uri = factory.expand("http://localhost:8080/spring/");
assertEquals("http://localhost:8080/spring/", uri.toString());
}
@Test
public void pathWithDuplicateSlashes() throws Exception {
DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory();
URI uri = factory.expand("/foo/////////bar");
assertEquals("/foo/bar", uri.toString());
}
}