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
20 changes: 4 additions & 16 deletions core/src/main/java/feign/RequestTemplate.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,31 +13,20 @@
*/
package feign;

import static feign.Util.CONTENT_LENGTH;
import static feign.Util.UTF_8;
import static feign.Util.checkNotNull;
import feign.Request.HttpMethod;
import feign.template.BodyTemplate;
import feign.template.HeaderTemplate;
import feign.template.QueryTemplate;
import feign.template.UriTemplate;
import feign.template.UriUtils;
import java.io.Serializable;
import java.nio.charset.Charset;
import java.util.AbstractMap.SimpleImmutableEntry;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import static feign.Util.*;

/**
* Request Builder for an HTTP Target.
Expand All @@ -51,7 +40,7 @@ public final class RequestTemplate implements Serializable {

private static final Pattern QUERY_STRING_PATTERN = Pattern.compile("(?<!\\{)\\?");
private final Map<String, QueryTemplate> queries = new LinkedHashMap<>();
private final Map<String, HeaderTemplate> headers = new LinkedHashMap<>();
private final Map<String, HeaderTemplate> headers = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
private String target;
private boolean resolved = false;
private UriTemplate uriTemplate;
Expand All @@ -73,7 +62,6 @@ public RequestTemplate() {
*
* @param target for the template.
* @param uriTemplate for the template.
* @param bodyTemplate for the template.
* @param method of the request.
* @param charset for the request.
* @param body of the request, may be null
Expand Down Expand Up @@ -691,7 +679,7 @@ public RequestTemplate headers(Map<String, Collection<String>> headers) {
* @return the currently applied headers.
*/
public Map<String, Collection<String>> headers() {
Map<String, Collection<String>> headerMap = new LinkedHashMap<>();
Map<String, Collection<String>> headerMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
this.headers.forEach((key, headerTemplate) -> {
List<String> values = new ArrayList<>(headerTemplate.getValues());

Expand Down
16 changes: 8 additions & 8 deletions core/src/test/java/feign/LoggerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -76,16 +76,16 @@ public static Iterable<Object[]> data() {
"\\[SendsStuff#login\\] <--- HTTP/1.1 200 OK \\([0-9]+ms\\)")},
{Level.HEADERS, Arrays.asList(
"\\[SendsStuff#login\\] ---> POST http://localhost:[0-9]+/ HTTP/1.1",
"\\[SendsStuff#login\\] Content-Type: application/json",
"\\[SendsStuff#login\\] Content-Length: 80",
"\\[SendsStuff#login\\] Content-Type: application/json",
Comment thread
velo marked this conversation as resolved.
"\\[SendsStuff#login\\] ---> END HTTP \\(80-byte body\\)",
"\\[SendsStuff#login\\] <--- HTTP/1.1 200 OK \\([0-9]+ms\\)",
"\\[SendsStuff#login\\] content-length: 3",
"\\[SendsStuff#login\\] <--- END HTTP \\(3-byte body\\)")},
{Level.FULL, Arrays.asList(
"\\[SendsStuff#login\\] ---> POST http://localhost:[0-9]+/ HTTP/1.1",
"\\[SendsStuff#login\\] Content-Type: application/json",
"\\[SendsStuff#login\\] Content-Length: 80",
"\\[SendsStuff#login\\] Content-Type: application/json",
"\\[SendsStuff#login\\] ",
"\\[SendsStuff#login\\] \\{\"customer_name\": \"netflix\", \"user_name\": \"denominator\", \"password\": \"password\"\\}",
"\\[SendsStuff#login\\] ---> END HTTP \\(80-byte body\\)",
Expand Down Expand Up @@ -161,14 +161,14 @@ public static Iterable<Object[]> data() {
"\\[SendsStuff#login\\] <--- ERROR SocketTimeoutException: Read timed out \\([0-9]+ms\\)")},
{Level.HEADERS, Arrays.asList(
"\\[SendsStuff#login\\] ---> POST http://localhost:[0-9]+/ HTTP/1.1",
"\\[SendsStuff#login\\] Content-Type: application/json",
"\\[SendsStuff#login\\] Content-Length: 80",
"\\[SendsStuff#login\\] Content-Type: application/json",
"\\[SendsStuff#login\\] ---> END HTTP \\(80-byte body\\)",
"\\[SendsStuff#login\\] <--- ERROR SocketTimeoutException: Read timed out \\([0-9]+ms\\)")},
{Level.FULL, Arrays.asList(
"\\[SendsStuff#login\\] ---> POST http://localhost:[0-9]+/ HTTP/1.1",
"\\[SendsStuff#login\\] Content-Type: application/json",
"\\[SendsStuff#login\\] Content-Length: 80",
"\\[SendsStuff#login\\] Content-Type: application/json",
"\\[SendsStuff#login\\] ",
"\\[SendsStuff#login\\] \\{\"customer_name\": \"netflix\", \"user_name\": \"denominator\", \"password\": \"password\"\\}",
"\\[SendsStuff#login\\] ---> END HTTP \\(80-byte body\\)",
Expand Down Expand Up @@ -223,14 +223,14 @@ public static Iterable<Object[]> data() {
"\\[SendsStuff#login\\] <--- ERROR UnknownHostException: robofu.abc \\([0-9]+ms\\)")},
{Level.HEADERS, Arrays.asList(
"\\[SendsStuff#login\\] ---> POST http://robofu.abc/ HTTP/1.1",
"\\[SendsStuff#login\\] Content-Type: application/json",
"\\[SendsStuff#login\\] Content-Length: 80",
"\\[SendsStuff#login\\] Content-Type: application/json",
"\\[SendsStuff#login\\] ---> END HTTP \\(80-byte body\\)",
"\\[SendsStuff#login\\] <--- ERROR UnknownHostException: robofu.abc \\([0-9]+ms\\)")},
{Level.FULL, Arrays.asList(
"\\[SendsStuff#login\\] ---> POST http://robofu.abc/ HTTP/1.1",
"\\[SendsStuff#login\\] Content-Type: application/json",
"\\[SendsStuff#login\\] Content-Length: 80",
"\\[SendsStuff#login\\] Content-Type: application/json",
"\\[SendsStuff#login\\] ",
"\\[SendsStuff#login\\] \\{\"customer_name\": \"netflix\", \"user_name\": \"denominator\", \"password\": \"password\"\\}",
"\\[SendsStuff#login\\] ---> END HTTP \\(80-byte body\\)",
Expand Down Expand Up @@ -285,14 +285,14 @@ public static Iterable<Object[]> data() {
"\\[SendsStuff#login\\] <--- ERROR UnknownHostException: sna%fu.abc \\([0-9]+ms\\)")},
{Level.HEADERS, Arrays.asList(
"\\[SendsStuff#login\\] ---> POST http://sna%fu.abc/ HTTP/1.1",
"\\[SendsStuff#login\\] Content-Type: application/json",
"\\[SendsStuff#login\\] Content-Length: 80",
"\\[SendsStuff#login\\] Content-Type: application/json",
"\\[SendsStuff#login\\] ---> END HTTP \\(80-byte body\\)",
"\\[SendsStuff#login\\] <--- ERROR UnknownHostException: sna%fu.abc \\([0-9]+ms\\)")},
{Level.FULL, Arrays.asList(
"\\[SendsStuff#login\\] ---> POST http://sna%fu.abc/ HTTP/1.1",
"\\[SendsStuff#login\\] Content-Type: application/json",
"\\[SendsStuff#login\\] Content-Length: 80",
"\\[SendsStuff#login\\] Content-Type: application/json",
"\\[SendsStuff#login\\] ",
"\\[SendsStuff#login\\] \\{\"customer_name\": \"netflix\", \"user_name\": \"denominator\", \"password\": \"password\"\\}",
"\\[SendsStuff#login\\] ---> END HTTP \\(80-byte body\\)",
Expand Down
28 changes: 23 additions & 5 deletions core/src/test/java/feign/RequestTemplateTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,10 @@
import static feign.assertj.FeignAssertions.assertThat;
import static java.util.Arrays.asList;
import static org.assertj.core.data.MapEntry.entry;
import static org.junit.Assert.*;
import feign.Request.HttpMethod;
import feign.template.UriUtils;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.*;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
Expand Down Expand Up @@ -323,6 +320,27 @@ public void spaceEncodingInUrlParam() {
.isEqualTo("/api/ABC%20123?key=XYZ%20123");
}

@Test
public void useCaseInsensitiveHeaderFieldNames() {
final RequestTemplate template = new RequestTemplate();

final String value = "value1";
template.header("TEST", value);

final String value2 = "value2";
template.header("tEST", value2);

final Collection<String> test = template.headers().get("test");

final String assertionMessage = "Header field names should be case insensitive";

assertNotNull(assertionMessage, test);
assertTrue(assertionMessage, test.contains(value));
assertTrue(assertionMessage, test.contains(value2));
assertEquals(1, template.headers().size());
assertEquals(2, template.headers().get("tesT").size());
}

@Test
public void encodeSlashTest() {
RequestTemplate template = new RequestTemplate().method(HttpMethod.GET)
Expand Down