Skip to content

Commit 6771866

Browse files
rejierdkdavisk6
authored andcommitted
Don't URL encode fragment identifiers (#937)
Fixes #936 This is a super simple fix to illustrate the issue. If a different solution is preferred, then I'm open for suggestions of course.
1 parent 7ba16df commit 6771866

File tree

2 files changed

+40
-1
lines changed

2 files changed

+40
-1
lines changed

core/src/main/java/feign/RequestTemplate.java

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ public final class RequestTemplate implements Serializable {
4343
private final Map<String, QueryTemplate> queries = new LinkedHashMap<>();
4444
private final Map<String, HeaderTemplate> headers = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
4545
private String target;
46+
private String fragment;
4647
private boolean resolved = false;
4748
private UriTemplate uriTemplate;
4849
private HttpMethod method;
@@ -70,13 +71,15 @@ public RequestTemplate() {
7071
* @param collectionFormat when expanding collection based variables.
7172
*/
7273
private RequestTemplate(String target,
74+
String fragment,
7375
UriTemplate uriTemplate,
7476
HttpMethod method,
7577
Charset charset,
7678
Request.Body body,
7779
boolean decodeSlash,
7880
CollectionFormat collectionFormat) {
7981
this.target = target;
82+
this.fragment = fragment;
8083
this.uriTemplate = uriTemplate;
8184
this.method = method;
8285
this.charset = charset;
@@ -94,7 +97,8 @@ private RequestTemplate(String target,
9497
*/
9598
public static RequestTemplate from(RequestTemplate requestTemplate) {
9699
RequestTemplate template =
97-
new RequestTemplate(requestTemplate.target, requestTemplate.uriTemplate,
100+
new RequestTemplate(requestTemplate.target, requestTemplate.fragment,
101+
requestTemplate.uriTemplate,
98102
requestTemplate.method, requestTemplate.charset,
99103
requestTemplate.body, requestTemplate.decodeSlash, requestTemplate.collectionFormat);
100104

@@ -118,6 +122,7 @@ public static RequestTemplate from(RequestTemplate requestTemplate) {
118122
public RequestTemplate(RequestTemplate toCopy) {
119123
checkNotNull(toCopy, "toCopy");
120124
this.target = toCopy.target;
125+
this.fragment = toCopy.fragment;
121126
this.method = toCopy.method;
122127
this.queries.putAll(toCopy.queries);
123128
this.headers.putAll(toCopy.headers);
@@ -421,6 +426,12 @@ public RequestTemplate uri(String uri, boolean append) {
421426
uri = uri.substring(0, queryMatcher.start());
422427
}
423428

429+
int fragmentIndex = uri.indexOf('#');
430+
if (fragmentIndex > -1) {
431+
fragment = uri.substring(fragmentIndex);
432+
uri = uri.substring(0, fragmentIndex);
433+
}
434+
424435
/* replace the uri template */
425436
if (append && this.uriTemplate != null) {
426437
this.uriTemplate = UriTemplate.append(this.uriTemplate, uri);
@@ -462,6 +473,9 @@ public RequestTemplate target(String target) {
462473

463474
/* strip the query string */
464475
this.target = targetUri.getScheme() + "://" + targetUri.getAuthority() + targetUri.getPath();
476+
if (targetUri.getFragment() != null) {
477+
this.fragment = "#" + targetUri.getFragment();
478+
}
465479
} catch (IllegalArgumentException iae) {
466480
/* the uri provided is not a valid one, we can't continue */
467481
throw new IllegalArgumentException("Target is not a valid URI.", iae);
@@ -482,6 +496,9 @@ public String url() {
482496
if (!this.queries.isEmpty()) {
483497
url.append(this.queryLine());
484498
}
499+
if (fragment != null) {
500+
url.append(fragment);
501+
}
485502

486503
return url.toString();
487504
}

core/src/test/java/feign/RequestTemplateTest.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
import org.junit.Rule;
3030
import org.junit.Test;
3131
import org.junit.rules.ExpectedException;
32+
import feign.Request.HttpMethod;
33+
import feign.template.UriUtils;
3234

3335
public class RequestTemplateTest {
3436

@@ -431,4 +433,24 @@ public void shouldNotInsertHeadersImmutableMap() {
431433

432434
template.headers().put("key2", Collections.singletonList("other value"));
433435
}
436+
437+
@Test
438+
public void fragmentShouldNotBeEncodedInUri() {
439+
RequestTemplate template = new RequestTemplate()
440+
.method(HttpMethod.GET)
441+
.uri("/path#fragment")
442+
.queries(mapOf("key1", Collections.singletonList("value1")));
443+
444+
assertThat(template.url()).isEqualTo("/path?key1=value1#fragment");
445+
}
446+
447+
@Test
448+
public void fragmentShouldNotBeEncodedInTarget() {
449+
RequestTemplate template = new RequestTemplate()
450+
.method(HttpMethod.GET)
451+
.target("https://example.com/path#fragment")
452+
.queries(mapOf("key1", Collections.singletonList("value1")));
453+
454+
assertThat(template.url()).isEqualTo("https://example.com/path?key1=value1#fragment");
455+
}
434456
}

0 commit comments

Comments
 (0)