Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion core/src/main/java/feign/template/BodyTemplate.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public static BodyTemplate create(String template) {
}

private BodyTemplate(String value, Charset charset) {
super(value, false, false, false, charset);
super(value, ExpansionOptions.ALLOW_UNRESOLVED, EncodingOptions.NOT_REQUIRED, false, charset);
}

@Override
Expand Down
5 changes: 5 additions & 0 deletions core/src/main/java/feign/template/Expression.java
Original file line number Diff line number Diff line change
Expand Up @@ -68,4 +68,9 @@ public String getValue() {
}
return "{" + this.name + "}";
}

@Override
public String toString() {
return this.getValue();
}
}
2 changes: 1 addition & 1 deletion core/src/main/java/feign/template/HeaderTemplate.java
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ public static HeaderTemplate append(HeaderTemplate headerTemplate, Iterable<Stri
* @param template to parse.
*/
private HeaderTemplate(String template, String name, Iterable<String> values, Charset charset) {
super(template, false, false, false, charset);
super(template, ExpansionOptions.REQUIRED, EncodingOptions.NOT_REQUIRED, false, charset);
this.values = StreamSupport.stream(values.spliterator(), false)
.filter(Util::isNotBlank)
.collect(Collectors.toSet());
Expand Down
20 changes: 11 additions & 9 deletions core/src/main/java/feign/template/QueryTemplate.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public final class QueryTemplate extends Template {

/* cache a copy of the variables for lookup later */
private List<String> values;
private final String name;
private final Template name;
private final CollectionFormat collectionFormat;
private boolean pure = false;

Expand Down Expand Up @@ -118,8 +118,9 @@ private QueryTemplate(
Iterable<String> values,
Charset charset,
CollectionFormat collectionFormat) {
super(template, false, true, true, charset);
this.name = name;
super(template, ExpansionOptions.REQUIRED, EncodingOptions.REQUIRED, true, charset);
this.name = new Template(name, ExpansionOptions.ALLOW_UNRESOLVED, EncodingOptions.REQUIRED,
false, charset);
this.collectionFormat = collectionFormat;
this.values = StreamSupport.stream(values.spliterator(), false)
.filter(Util::isNotBlank)
Expand All @@ -136,12 +137,12 @@ public List<String> getValues() {
}

public String getName() {
return name;
return name.toString();
}

@Override
public String toString() {
return this.queryString(super.toString());
return this.queryString(this.name.toString(), super.toString());
}

/**
Expand All @@ -153,12 +154,13 @@ public String toString() {
*/
@Override
public String expand(Map<String, ?> variables) {
return this.queryString(super.expand(variables));
String name = this.name.expand(variables);
return this.queryString(name, super.expand(variables));
}

private String queryString(String values) {
private String queryString(String name, String values) {
if (this.pure) {
return this.name;
return name;
}

/* covert the comma separated values into a value query string */
Expand All @@ -167,7 +169,7 @@ private String queryString(String values) {
.collect(Collectors.toList());

if (!resolved.isEmpty()) {
return this.collectionFormat.join(this.name, resolved, this.getCharset()).toString();
return this.collectionFormat.join(name, resolved, this.getCharset()).toString();
}

/* nothing to return, all values are unresolved */
Expand Down
41 changes: 28 additions & 13 deletions core/src/main/java/feign/template/Template.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,13 @@
* <a href="https://tools.ietf.org/html/rfc6570">RFC 6570</a>, with some relaxed rules, allowing the
* concept to be used in areas outside of the uri.
*/
public abstract class Template {
public class Template {

private static final Logger logger = Logger.getLogger(Template.class.getName());
private static final Pattern QUERY_STRING_PATTERN = Pattern.compile("(?<!\\{)(\\?)");
private final String template;
private final boolean allowUnresolved;
private final boolean encode;
private final EncodingOptions encode;
private final boolean encodeSlash;
private final Charset charset;
private final List<TemplateChunk> templateChunks = new ArrayList<>();
Expand All @@ -48,12 +48,13 @@ public abstract class Template {
* @param encodeSlash if slash characters should be encoded.
*/
Template(
String value, boolean allowUnresolved, boolean encode, boolean encodeSlash, Charset charset) {
String value, ExpansionOptions allowUnresolved, EncodingOptions encode, boolean encodeSlash,
Charset charset) {
if (value == null) {
throw new IllegalArgumentException("template is required.");
}
this.template = value;
this.allowUnresolved = allowUnresolved;
this.allowUnresolved = ExpansionOptions.ALLOW_UNRESOLVED == allowUnresolved;
this.encode = encode;
this.encodeSlash = encodeSlash;
this.charset = charset;
Expand All @@ -78,7 +79,7 @@ public String expand(Map<String, ?> variables) {
Expression expression = (Expression) chunk;
Object value = variables.get(expression.getName());
if (value != null) {
String expanded = expression.expand(value, this.encode);
String expanded = expression.expand(value, this.encode.isEncodingRequired());
if (!this.encodeSlash) {
logger.fine("Explicit slash decoding specified, decoding all slashes in uri");
expanded = expanded.replaceAll("\\%2F", "/");
Expand All @@ -105,7 +106,7 @@ public String expand(Map<String, ?> variables) {
* @return the encoded value.
*/
private String encode(String value) {
return this.encode ? UriUtils.encode(value, this.charset) : value;
return this.encode.isEncodingRequired() ? UriUtils.encode(value, this.charset) : value;
}

/**
Expand All @@ -116,7 +117,7 @@ private String encode(String value) {
* @return the encoded value
*/
private String encode(String value, boolean query) {
if (this.encode) {
if (this.encode.isEncodingRequired()) {
return query ? UriUtils.queryEncode(value, this.charset)
: UriUtils.pathEncode(value, this.charset);
} else {
Expand Down Expand Up @@ -218,15 +219,11 @@ public String toString() {
.map(TemplateChunk::getValue).collect(Collectors.joining());
}

public boolean allowUnresolved() {
return allowUnresolved;
}

public boolean encode() {
return encode;
return encode.isEncodingRequired();
}

public boolean encodeSlash() {
boolean encodeSlash() {
return encodeSlash;
}

Expand Down Expand Up @@ -315,4 +312,22 @@ public String next() {
}
}

public enum EncodingOptions {
REQUIRED(true), NOT_REQUIRED(false);

private boolean shouldEncode;

EncodingOptions(boolean shouldEncode) {
this.shouldEncode = shouldEncode;
}

public boolean isEncodingRequired() {
return this.shouldEncode;
}
}

public enum ExpansionOptions {
ALLOW_UNRESOLVED, REQUIRED
}

}
2 changes: 1 addition & 1 deletion core/src/main/java/feign/template/UriTemplate.java
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,6 @@ public static UriTemplate append(UriTemplate uriTemplate, String fragment) {
* @param charset to use when encoding.
*/
private UriTemplate(String template, boolean encodeSlash, Charset charset) {
super(template, false, true, encodeSlash, charset);
super(template, ExpansionOptions.REQUIRED, EncodingOptions.REQUIRED, encodeSlash, charset);
}
}
10 changes: 7 additions & 3 deletions core/src/test/java/feign/DefaultContractTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

import com.google.gson.reflect.TypeToken;
import java.util.ArrayList;
import java.util.Collections;
import org.assertj.core.api.Fail;
import org.junit.Rule;
import org.junit.Test;
Expand Down Expand Up @@ -147,7 +148,8 @@ public void headersOnMethodAddsContentTypeHeader() throws Exception {
assertThat(md.template())
.hasHeaders(
entry("Content-Type", asList("application/xml")),
entry("Content-Length", asList(String.valueOf(md.template().body().length))));
entry("Content-Length",
asList(String.valueOf(md.template().requestBody().asBytes().length))));
}

@Test
Expand All @@ -157,7 +159,8 @@ public void headersOnTypeAddsContentTypeHeader() throws Exception {
assertThat(md.template())
.hasHeaders(
entry("Content-Type", asList("application/xml")),
entry("Content-Length", asList(String.valueOf(md.template().body().length))));
entry("Content-Length",
asList(String.valueOf(md.template().requestBody().asBytes().length))));
}

@Test
Expand All @@ -167,7 +170,8 @@ public void headersContainsWhitespaces() throws Exception {
assertThat(md.template())
.hasHeaders(
entry("Content-Type", asList("application/xml")),
entry("Content-Length", asList(String.valueOf(md.template().body().length))));
entry("Content-Length",
asList(String.valueOf(md.template().requestBody().asBytes().length))));
}

@Test
Expand Down
31 changes: 31 additions & 0 deletions core/src/test/java/feign/template/QueryTemplateTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,35 @@ public void collectionFormat() {
assertThat(expanded).isEqualToIgnoringCase("name=James,Jason");
}

@Test
public void expandName() {
QueryTemplate template =
QueryTemplate.create("{name}", Arrays.asList("James", "Jason"), Util.UTF_8);
String expanded = template.expand(Collections.singletonMap("name", "firsts"));
assertThat(expanded).isEqualToIgnoringCase("firsts=James&firsts=Jason");
}

@Test
public void expandPureParameter() {
QueryTemplate template =
QueryTemplate.create("{name}", Collections.emptyList(), Util.UTF_8);
String expanded = template.expand(Collections.singletonMap("name", "firsts"));
assertThat(expanded).isEqualToIgnoringCase("firsts");
}

@Test
public void expandPureParameterWithSlash() {
QueryTemplate template =
QueryTemplate.create("/path/{name}", Collections.emptyList(), Util.UTF_8);
String expanded = template.expand(Collections.singletonMap("name", "firsts"));
assertThat(expanded).isEqualToIgnoringCase("/path/firsts");
}

@Test
public void expandNameUnresolved() {
QueryTemplate template =
QueryTemplate.create("{parameter}", Arrays.asList("James", "Jason"), Util.UTF_8);
String expanded = template.expand(Collections.singletonMap("name", "firsts"));
assertThat(expanded).isEqualToIgnoringCase("%7Bparameter%7D=James&%7Bparameter%7D=Jason");
}
}