Skip to content

Commit 5b1aafc

Browse files
authored
Merge pull request #656 from jooby-project/649
cookie parser fails when cookie value isn't present fix #649
2 parents 0e494a3 + ed9628b commit 5b1aafc

3 files changed

Lines changed: 52 additions & 32 deletions

File tree

jooby/src/main/java/org/jooby/Cookie.java

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* "License"); you may not use this file except in compliance
88
* with the License. You may obtain a copy of the License at
99
*
10-
* http://www.apache.org/licenses/LICENSE-2.0
10+
* http://www.apache.org/licenses/LICENSE-2.0
1111
*
1212
* Unless required by applicable law or agreed to in writing,
1313
* software distributed under the License is distributed on an
@@ -18,30 +18,29 @@
1818
*/
1919
package org.jooby;
2020

21-
import static java.util.Objects.requireNonNull;
21+
import com.google.common.base.Splitter;
22+
import com.google.common.base.Strings;
23+
import com.google.common.io.BaseEncoding;
24+
import javaslang.Tuple;
25+
import javaslang.Tuple2;
26+
import javaslang.control.Try;
27+
import org.jooby.internal.CookieImpl;
2228

29+
import javax.crypto.Mac;
30+
import javax.crypto.spec.SecretKeySpec;
2331
import java.net.URLDecoder;
2432
import java.net.URLEncoder;
2533
import java.nio.charset.StandardCharsets;
34+
import java.util.Collections;
2635
import java.util.Iterator;
2736
import java.util.Map;
37+
import java.util.Objects;
2838
import java.util.Optional;
2939
import java.util.function.Function;
3040
import java.util.regex.Pattern;
3141
import java.util.stream.Collectors;
3242

33-
import javax.crypto.Mac;
34-
import javax.crypto.spec.SecretKeySpec;
35-
36-
import org.jooby.internal.CookieImpl;
37-
38-
import com.google.common.base.Splitter;
39-
import com.google.common.base.Strings;
40-
import com.google.common.io.BaseEncoding;
41-
42-
import javaslang.Tuple;
43-
import javaslang.Tuple2;
44-
import javaslang.control.Try;
43+
import static java.util.Objects.requireNonNull;
4544

4645
/**
4746
* Creates a cookie, a small amount of information sent by a server to
@@ -84,18 +83,27 @@ public interface Cookie {
8483
* {@link URLDecoder}.
8584
*/
8685
public static final Function<String, Map<String, String>> URL_DECODER = value -> {
86+
if (value == null) {
87+
return Collections.emptyMap();
88+
}
8789
Function<String, String> decode = v -> Try
88-
.of(() -> URLDecoder.decode(v, StandardCharsets.UTF_8.name())).get();
89-
return Splitter.on('&').trimResults().omitEmptyStrings()
90+
.of(() -> URLDecoder.decode(v, StandardCharsets.UTF_8.name()))
91+
.get();
92+
return Splitter.on('&')
93+
.trimResults()
94+
.omitEmptyStrings()
9095
.splitToList(value)
9196
.stream()
9297
.map(v -> {
9398
Iterator<String> it = Splitter.on('=').trimResults().omitEmptyStrings()
9499
.split(v)
95100
.iterator();
96-
Tuple2<String, String> t2 = Tuple.of(decode.apply(it.next()), decode.apply(it.next()));
101+
Tuple2<String, String> t2 = Tuple
102+
.of(decode.apply(it.next()), it.hasNext() ? decode.apply(it.next()) : null);
97103
return t2;
98-
}).collect(Collectors.toMap(it -> it._1, it -> it._2));
104+
})
105+
.filter(it -> Objects.nonNull(it._2))
106+
.collect(Collectors.toMap(it -> it._1, it -> it._2));
99107
};
100108

101109
/**
@@ -349,7 +357,7 @@ public Optional<Boolean> secure() {
349357
* </p>
350358
*
351359
* @param maxAge an integer specifying the maximum age of the cookie in seconds; if negative,
352-
* means the cookie is not stored; if zero, deletes the cookie.
360+
* means the cookie is not stored; if zero, deletes the cookie.
353361
* @return This definition.
354362
*/
355363
public Definition maxAge(final int maxAge) {
@@ -494,7 +502,7 @@ public static boolean valid(final String value, final String secret) {
494502
* </p>
495503
*
496504
* @return An integer specifying the maximum age of the cookie in seconds; if negative, means
497-
* the cookie persists until browser shutdown
505+
* the cookie persists until browser shutdown
498506
*/
499507
int maxAge();
500508

jooby/src/main/java/org/jooby/internal/CookieSessionManager.java

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* "License"); you may not use this file except in compliance
88
* with the License. You may obtain a copy of the License at
99
*
10-
* http://www.apache.org/licenses/LICENSE-2.0
10+
* http://www.apache.org/licenses/LICENSE-2.0
1111
*
1212
* Unless required by applicable law or agreed to in writing,
1313
* software distributed under the License is distributed on an
@@ -18,14 +18,6 @@
1818
*/
1919
package org.jooby.internal;
2020

21-
import java.util.Collections;
22-
import java.util.Map;
23-
import java.util.Optional;
24-
import java.util.concurrent.TimeUnit;
25-
26-
import javax.inject.Inject;
27-
import javax.inject.Named;
28-
2921
import org.jooby.Cookie;
3022
import org.jooby.Cookie.Definition;
3123
import org.jooby.Request;
@@ -36,6 +28,13 @@
3628
import org.slf4j.Logger;
3729
import org.slf4j.LoggerFactory;
3830

31+
import javax.inject.Inject;
32+
import javax.inject.Named;
33+
import java.util.Collections;
34+
import java.util.Map;
35+
import java.util.Optional;
36+
import java.util.concurrent.TimeUnit;
37+
3938
/**
4039
* Save session data in a cookie.
4140
*
@@ -100,9 +99,6 @@ public Definition cookie() {
10099

101100
private Map<String, String> attributes(final String raw) {
102101
String unsigned = Cookie.Signature.unsign(raw, secret);
103-
if (unsigned == null) {
104-
return Collections.emptyMap();
105-
}
106102
return Cookie.URL_DECODER.apply(unsigned);
107103
}
108104

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package org.jooby.issues;
2+
3+
import org.jooby.Cookie;
4+
import org.junit.Test;
5+
6+
import static org.junit.Assert.assertTrue;
7+
8+
public class Issue649 {
9+
10+
@Test
11+
public void emptyCookie() {
12+
assertTrue(Cookie.URL_DECODER.apply("foo=").isEmpty());
13+
assertTrue(Cookie.URL_DECODER.apply("foo").isEmpty());
14+
assertTrue(Cookie.URL_DECODER.apply(null).isEmpty());
15+
}
16+
}

0 commit comments

Comments
 (0)