@ -16,8 +16,10 @@
@@ -16,8 +16,10 @@
package org.springframework.web.util ;
import java.io.UnsupportedEncodingException ;
import java.net.URI ;
import java.net.URISyntaxException ;
import java.util.HashMap ;
import java.util.List ;
import java.util.Map ;
@ -36,6 +38,8 @@ public class DefaultUriTemplateHandler implements UriTemplateHandler {
@@ -36,6 +38,8 @@ public class DefaultUriTemplateHandler implements UriTemplateHandler {
private boolean parsePath ;
private boolean strictEncoding ;
/ * *
* Configure a base URL to prepend URI templates with . The base URL must
@ -83,19 +87,45 @@ public class DefaultUriTemplateHandler implements UriTemplateHandler {
@@ -83,19 +87,45 @@ public class DefaultUriTemplateHandler implements UriTemplateHandler {
return this . parsePath ;
}
/ * *
* Whether to encode characters outside the unreserved set as defined in
* < a href = "https://tools.ietf.org/html/rfc3986#section-2" > RFC 3986 Section 2 < / a > .
* This ensures a URI variable value will not contain any characters with a
* reserved purpose .
* < p > By default this is set to { @code false } in which case only characters
* illegal for the given URI component are encoded . For example when expanding
* a URI variable into a path segment the "/" character is illegal and
* encoded . The ";" character however is legal and not encoded even though
* it has a reserved purpose .
* < p > < strong > Note : < / strong > this property supersedes the need to also set
* the { @link # setParsePath parsePath } property .
* @param strictEncoding whether to perform strict encoding
* @since 4 . 3
* /
public void setStrictEncoding ( boolean strictEncoding ) {
this . strictEncoding = strictEncoding ;
}
/ * *
* Whether to strictly encode any character outside the unreserved set .
* /
public boolean isStrictEncoding ( ) {
return this . strictEncoding ;
}
@Override
public URI expand ( String uriTemplate , Map < String , ? > uriVariables ) {
UriComponentsBuilder builder = initUriComponentsBuilder ( uriTemplate ) ;
UriComponents url = builder . build ( ) . expand ( uriVariables ) . encode ( ) ;
return insertBaseUrl ( url ) ;
UriComponentsBuilder uriComponentsB uilder = initUriComponentsBuilder ( uriTemplate ) ;
UriComponents uriComponents = expandAndEncode ( uriComponentsBuilder , uriVariables ) ;
return insertBaseUrl ( uriComponents ) ;
}
@Override
public URI expand ( String uriTemplate , Object . . . uriVariables ) {
UriComponentsBuilder builder = initUriComponentsBuilder ( uriTemplate ) ;
UriComponents url = builder . build ( ) . expand ( uriVariables ) . encode ( ) ;
return insertBaseUrl ( url ) ;
UriComponentsBuilder uriComponentsB uilder = initUriComponentsBuilder ( uriTemplate ) ;
UriComponents uriComponents = expandAndEncode ( uriComponentsBuilder , uriVariables ) ;
return insertBaseUrl ( uriComponents ) ;
}
/ * *
@ -105,7 +135,7 @@ public class DefaultUriTemplateHandler implements UriTemplateHandler {
@@ -105,7 +135,7 @@ public class DefaultUriTemplateHandler implements UriTemplateHandler {
* /
protected UriComponentsBuilder initUriComponentsBuilder ( String uriTemplate ) {
UriComponentsBuilder builder = UriComponentsBuilder . fromUriString ( uriTemplate ) ;
if ( shouldParsePath ( ) ) {
if ( shouldParsePath ( ) & & ! isStrictEncoding ( ) ) {
List < String > pathSegments = builder . build ( ) . getPathSegments ( ) ;
builder . replacePath ( null ) ;
for ( String pathSegment : pathSegments ) {
@ -115,6 +145,43 @@ public class DefaultUriTemplateHandler implements UriTemplateHandler {
@@ -115,6 +145,43 @@ public class DefaultUriTemplateHandler implements UriTemplateHandler {
return builder ;
}
protected UriComponents expandAndEncode ( UriComponentsBuilder builder , Map < String , ? > uriVariables ) {
if ( ! isStrictEncoding ( ) ) {
return builder . build ( ) . expand ( uriVariables ) . encode ( ) ;
}
else {
Map < String , Object > encodedUriVars = new HashMap < String , Object > ( uriVariables . size ( ) ) ;
for ( Map . Entry < String , ? > entry : uriVariables . entrySet ( ) ) {
encodedUriVars . put ( entry . getKey ( ) , encodeValue ( entry . getValue ( ) ) ) ;
}
return builder . build ( ) . expand ( encodedUriVars ) ;
}
}
protected UriComponents expandAndEncode ( UriComponentsBuilder builder , Object [ ] uriVariables ) {
if ( ! isStrictEncoding ( ) ) {
return builder . build ( ) . expand ( uriVariables ) . encode ( ) ;
}
else {
Object [ ] encodedUriVars = new Object [ uriVariables . length ] ;
for ( int i = 0 ; i < uriVariables . length ; i + + ) {
encodedUriVars [ i ] = encodeValue ( uriVariables [ i ] ) ;
}
return builder . build ( ) . expand ( encodedUriVars ) ;
}
}
private String encodeValue ( Object value ) {
String stringValue = ( value ! = null ? value . toString ( ) : "" ) ;
try {
return UriUtils . encode ( stringValue , "UTF-8" ) ;
}
catch ( UnsupportedEncodingException ex ) {
// Should never happen
throw new IllegalStateException ( "Failed to encode URI variable" , ex ) ;
}
}
/ * *
* Invoked after the URI template has been expanded and encoded to prepend
* the configured { @link # setBaseUrl ( String ) baseUrl } if any .
@ -122,10 +189,10 @@ public class DefaultUriTemplateHandler implements UriTemplateHandler {
@@ -122,10 +189,10 @@ public class DefaultUriTemplateHandler implements UriTemplateHandler {
* @return the final URI
* /
protected URI insertBaseUrl ( UriComponents uriComponents ) {
if ( getBaseUrl ( ) = = null | | uriComponents . getHost ( ) ! = null ) {
return uriComponents . toUri ( ) ;
String url = uriComponents . toUriString ( ) ;
if ( getBaseUrl ( ) ! = null & & uriComponents . getHost ( ) = = null ) {
url = getBaseUrl ( ) + url ;
}
String url = getBaseUrl ( ) + uriComponents . toUriString ( ) ;
try {
return new URI ( url ) ;
}