Skip to content

Commit d0ee044

Browse files
authored
Merge pull request #2358 from froque/2357_case_insensitive_headers
Fixes case insensitive headers
2 parents 596d5e1 + 33bff75 commit d0ee044

7 files changed

Lines changed: 48 additions & 6 deletions

File tree

jooby/src/main/java/io/jooby/Value.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import io.jooby.internal.MissingValue;
1313
import io.jooby.internal.SingleValue;
1414

15+
import java.util.TreeMap;
1516
import javax.annotation.Nonnull;
1617
import javax.annotation.Nullable;
1718
import java.time.Instant;
@@ -519,4 +520,17 @@ default boolean isObject() {
519520
node.put(values);
520521
return node;
521522
}
523+
524+
/**
525+
* Create a hash/object value using the map values.
526+
*
527+
* @param ctx Current context.
528+
* @param values Map values.
529+
* @return A hash/object value.
530+
*/
531+
static @Nonnull ValueNode headers(Context ctx, @Nonnull Map<String, Collection<String>> values) {
532+
HashValue node = new HashValue(ctx, null, () -> new TreeMap<>(String.CASE_INSENSITIVE_ORDER));
533+
node.put(values);
534+
return node;
535+
}
522536
}

jooby/src/main/java/io/jooby/internal/HashValue.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import io.jooby.Formdata;
1111
import io.jooby.ValueNode;
1212

13+
import java.util.function.Supplier;
1314
import javax.annotation.Nonnull;
1415
import java.util.ArrayList;
1516
import java.util.Collection;
@@ -34,6 +35,12 @@ public class HashValue implements ValueNode, Formdata {
3435

3536
private final String name;
3637

38+
public HashValue(Context ctx, String name, Supplier<Map<String, ValueNode>> mapSupplier) {
39+
this.ctx = ctx;
40+
this.name = name;
41+
this.hash = mapSupplier.get();
42+
}
43+
3744
public HashValue(Context ctx, String name) {
3845
this.ctx = ctx;
3946
this.name = name;

modules/jooby-jetty/src/main/java/io/jooby/internal/jetty/JettyContext.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@
5454
import java.io.InputStream;
5555
import java.io.OutputStream;
5656
import java.io.PrintWriter;
57-
import java.net.InetSocketAddress;
5857
import java.nio.ByteBuffer;
5958
import java.nio.channels.Channels;
6059
import java.nio.channels.FileChannel;
@@ -240,7 +239,7 @@ public JettyContext(Request request, Router router, int bufferSize, long maxRequ
240239
String name = names.nextElement();
241240
headerMap.put(name, Collections.list(request.getHeaders(name)));
242241
}
243-
headers = Value.hash(this, headerMap);
242+
headers = Value.headers(this, headerMap);
244243
}
245244
return headers;
246245
}

modules/jooby-netty/src/main/java/io/jooby/internal/netty/NettyContext.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@
3939
import java.util.Map;
4040
import java.util.Set;
4141
import java.util.concurrent.Executor;
42-
import java.util.concurrent.TimeUnit;
4342
import java.util.stream.Stream;
4443

4544
import javax.annotation.Nonnull;
@@ -314,7 +313,7 @@ boolean isHttpGet() {
314313
for (String name : names) {
315314
headerMap.put(name, headers.getAll(name));
316315
}
317-
this.headers = Value.hash(this, headerMap);
316+
this.headers = Value.headers(this, headerMap);
318317
}
319318
return headers;
320319
}

modules/jooby-test/src/main/java/io/jooby/MockContext.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ public MockContext setFlashMap(@Nonnull FlashMap flashMap) {
248248
}
249249

250250
@Nonnull @Override public ValueNode header() {
251-
return Value.hash(this, headers);
251+
return Value.headers(this, headers);
252252
}
253253

254254
/**

modules/jooby-utow/src/main/java/io/jooby/internal/utow/UtowContext.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ boolean isHttpGet() {
238238
HeaderValues values = map.get(name);
239239
headerMap.put(name.toString(), values);
240240
}
241-
headers = Value.hash(this, headerMap);
241+
headers = Value.headers(this, headerMap);
242242
}
243243
return headers;
244244
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package io.jooby;
2+
3+
import io.jooby.junit.ServerTest;
4+
import io.jooby.junit.ServerTestRunner;
5+
import org.junit.jupiter.api.Assertions;
6+
7+
class Issue2357 {
8+
9+
@ServerTest
10+
public void headersShouldBeCaseInsensitive(ServerTestRunner runner) {
11+
runner.define(app -> app.get("/", ctx -> {
12+
Assertions.assertEquals("value1", ctx.header().get("x-header1").value());
13+
Assertions.assertEquals("value1", ctx.header().get("X-HEADER1").value());
14+
Assertions.assertEquals("value1", ctx.header().get("X-hEaDeR1").value());
15+
Assertions.assertEquals("value1", ctx.header("x-header1").value());
16+
Assertions.assertEquals("value1", ctx.header("X-HEADER1").value());
17+
Assertions.assertEquals("value1", ctx.header("X-hEaDeR1").value());
18+
return "OK";
19+
})).ready(http -> http.header("x-header1", "value1").get("/", rsp -> {
20+
Assertions.assertEquals(200, rsp.code());
21+
}));
22+
}
23+
}

0 commit comments

Comments
 (0)