@@ -117,7 +117,7 @@ public static String expand(String template, Map<String, ?> variables) {
117117 // skip expansion if there's no valid variables set. ex. {a} is the
118118 // first valid
119119 if (checkNotNull (template , "template" ).length () < 3 ) {
120- return template . toString () ;
120+ return template ;
121121 }
122122 checkNotNull (variables , "variables for %s" , template );
123123
@@ -200,21 +200,29 @@ private static void putKV(String stringToParse, Map<String, Collection<String>>
200200 map .put (key , values );
201201 }
202202
203+ /** {@link #resolve(Map, Map)}, which assumes no parameter is encoded */
204+ public RequestTemplate resolve (Map <String , ?> unencoded ) {
205+ return resolve (unencoded , Collections .<String , Boolean >emptyMap ());
206+ }
207+
203208 /**
204209 * Resolves any template parameters in the requests path, query, or headers against the supplied
205210 * unencoded arguments. <br> <br><br><b>relationship to JAXRS 2.0</b><br> <br> This call is
206211 * similar to {@code javax.ws.rs.client.WebTarget.resolveTemplates(templateValues, true)} , except
207212 * that the template values apply to any part of the request, not just the URL
208213 */
209- public RequestTemplate resolve (Map <String , ?> unencoded ) {
210- replaceQueryValues (unencoded );
214+ RequestTemplate resolve (Map <String , ?> unencoded , Map < String , Boolean > alreadyEncoded ) {
215+ replaceQueryValues (unencoded , alreadyEncoded );
211216 Map <String , String > encoded = new LinkedHashMap <String , String >();
212217 for (Entry <String , ?> entry : unencoded .entrySet ()) {
213- encoded .put (entry .getKey (), urlEncode (String .valueOf (entry .getValue ())));
218+ final String key = entry .getKey ();
219+ final Object objectValue = entry .getValue ();
220+ String encodedValue = encodeValueIfNotEncoded (key , objectValue , alreadyEncoded );
221+ encoded .put (key , encodedValue );
214222 }
215223 String resolvedUrl = expand (url .toString (), encoded ).replace ("+" , "%20" );
216224 if (decodeSlash ) {
217- resolvedUrl = resolvedUrl .replace ("%2F" , "/" );
225+ resolvedUrl = resolvedUrl .replace ("%2F" , "/" );
218226 }
219227 url = new StringBuilder (resolvedUrl );
220228
@@ -235,13 +243,21 @@ public RequestTemplate resolve(Map<String, ?> unencoded) {
235243 return this ;
236244 }
237245
246+ private String encodeValueIfNotEncoded (String key , Object objectValue , Map <String , Boolean > alreadyEncoded ) {
247+ String value = String .valueOf (objectValue );
248+ final Boolean isEncoded = alreadyEncoded .get (key );
249+ if (isEncoded == null || !isEncoded ) {
250+ value = urlEncode (value );
251+ }
252+ return value ;
253+ }
254+
238255 /* roughly analogous to {@code javax.ws.rs.client.Target.request()}. */
239256 public Request request () {
240257 Map <String , Collection <String >> safeCopy = new LinkedHashMap <String , Collection <String >>();
241258 safeCopy .putAll (headers );
242259 return Request .create (
243- method ,
244- new StringBuilder (url ).append (queryLine ()).toString (),
260+ method , url + queryLine (),
245261 Collections .unmodifiableMap (safeCopy ),
246262 body , charset
247263 );
@@ -589,11 +605,16 @@ public String toString() {
589605 return request ().toString ();
590606 }
591607
608+ /** {@link #replaceQueryValues(Map, Map)}, which assumes no parameter is encoded */
609+ public void replaceQueryValues (Map <String , ?> unencoded ) {
610+ replaceQueryValues (unencoded , Collections .<String , Boolean >emptyMap ());
611+ }
612+
592613 /**
593614 * Replaces query values which are templated with corresponding values from the {@code unencoded}
594615 * map. Any unresolved queries are removed.
595616 */
596- public void replaceQueryValues (Map <String , ?> unencoded ) {
617+ void replaceQueryValues (Map <String , ?> unencoded , Map < String , Boolean > alreadyEncoded ) {
597618 Iterator <Entry <String , Collection <String >>> iterator = queries .entrySet ().iterator ();
598619 while (iterator .hasNext ()) {
599620 Entry <String , Collection <String >> entry = iterator .next ();
@@ -610,10 +631,12 @@ public void replaceQueryValues(Map<String, ?> unencoded) {
610631 }
611632 if (variableValue instanceof Iterable ) {
612633 for (Object val : Iterable .class .cast (variableValue )) {
613- values .add (urlEncode (String .valueOf (val )));
634+ String encodedValue = encodeValueIfNotEncoded (entry .getKey (), val , alreadyEncoded );
635+ values .add (encodedValue );
614636 }
615637 } else {
616- values .add (urlEncode (String .valueOf (variableValue )));
638+ String encodedValue = encodeValueIfNotEncoded (entry .getKey (), variableValue , alreadyEncoded );
639+ values .add (encodedValue );
617640 }
618641 } else {
619642 values .add (value );
0 commit comments