Skip to content

Commit e262482

Browse files
authored
tidy internals (#195)
- sort Context/JexConfig - fix query param `+` decoding - use `Charset` instead of string for character encoding
1 parent 14dff41 commit e262482

File tree

9 files changed

+50
-42
lines changed

9 files changed

+50
-42
lines changed

avaje-jex/src/main/java/io/avaje/jex/core/JdkContext.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@
4141

4242
final class JdkContext implements Context {
4343

44-
private static final String UTF8 = "UTF8";
4544
private static final String SET_COOKIE = "Set-Cookie";
4645
private static final String COOKIE = "Cookie";
4746
private final ServiceManager mgr;
@@ -56,7 +55,7 @@ final class JdkContext implements Context {
5655
private Map<String, String> cookieMap;
5756
private int statusCode;
5857

59-
private String characterEncoding;
58+
private Charset characterEncoding;
6059

6160
JdkContext(
6261
ServiceManager mgr,
@@ -120,7 +119,7 @@ private static BasicAuthCredentials getBasicAuthCredentials(String authorization
120119

121120
@Override
122121
public String body() {
123-
return new String(bodyAsBytes(), Charset.forName(characterEncoding()));
122+
return new String(bodyAsBytes(), characterEncoding());
124123
}
125124

126125
@Override
@@ -147,7 +146,7 @@ public <T> T bodyAsType(Type beanType) {
147146
return mgr.fromJson(beanType, bodyAsInputStream());
148147
}
149148

150-
private String characterEncoding() {
149+
private Charset characterEncoding() {
151150
if (characterEncoding == null) {
152151
characterEncoding = mgr.requestCharset(this);
153152
}
@@ -389,7 +388,7 @@ public Map<String, String> queryParamMap() {
389388

390389
private Map<String, List<String>> queryParams() {
391390
if (queryParams == null) {
392-
queryParams = mgr.parseParamMap(queryString(), UTF8);
391+
queryParams = mgr.parseParamMap(queryString(), StandardCharsets.UTF_8);
393392
}
394393
return queryParams;
395394
}

avaje-jex/src/main/java/io/avaje/jex/core/ServiceManager.java

Lines changed: 16 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,10 @@
22

33
import java.io.InputStream;
44
import java.io.OutputStream;
5-
import java.io.UncheckedIOException;
6-
import java.io.UnsupportedEncodingException;
75
import java.lang.System.Logger.Level;
86
import java.lang.reflect.Type;
9-
import java.net.URLDecoder;
7+
import java.nio.charset.Charset;
8+
import java.nio.charset.StandardCharsets;
109
import java.util.ArrayList;
1110
import java.util.Collections;
1211
import java.util.Iterator;
@@ -22,14 +21,14 @@
2221
import io.avaje.jex.core.json.JacksonJsonService;
2322
import io.avaje.jex.core.json.JsonbJsonService;
2423
import io.avaje.jex.http.Context;
24+
import io.avaje.jex.routes.UrlDecode;
2525
import io.avaje.jex.spi.JsonService;
2626
import io.avaje.jex.spi.TemplateRender;
2727

2828
/** Core service methods available to Context implementations. */
2929
final class ServiceManager {
3030

3131
private static final System.Logger log = System.getLogger("io.avaje.jex");
32-
private static final String UTF_8 = "UTF-8";
3332

3433
private final CompressionConfig compressionConfig;
3534
private final JsonService jsonService;
@@ -120,42 +119,38 @@ void render(Context ctx, String name, Map<String, Object> model) {
120119
templateManager.render(ctx, name, model);
121120
}
122121

123-
String requestCharset(Context ctx) {
122+
Charset requestCharset(Context ctx) {
124123
return parseCharset(ctx.header(Constants.CONTENT_TYPE));
125124
}
126125

127-
static String parseCharset(String header) {
126+
static Charset parseCharset(String header) {
128127
if (header != null) {
129128
for (String val : header.split(";")) {
130129
val = val.trim();
131130
if (val.regionMatches(true, 0, "charset", 0, "charset".length())) {
132-
return val.split("=")[1].trim();
131+
return Charset.forName(val.split("=")[1].trim());
133132
}
134133
}
135134
}
136-
return UTF_8;
135+
return StandardCharsets.UTF_8;
137136
}
138137

139-
Map<String, List<String>> formParamMap(Context ctx, String charset) {
138+
Map<String, List<String>> formParamMap(Context ctx, Charset charset) {
140139
return parseParamMap(ctx.body(), charset);
141140
}
142141

143-
Map<String, List<String>> parseParamMap(String body, String charset) {
142+
Map<String, List<String>> parseParamMap(String body, Charset charset) {
144143
if (body == null || body.isEmpty()) {
145144
return Collections.emptyMap();
146145
}
147-
try {
148-
Map<String, List<String>> map = new LinkedHashMap<>();
149-
for (String pair : body.split("&")) {
150-
final String[] split1 = pair.split("=", 2);
151-
String key = URLDecoder.decode(split1[0], charset);
152-
String val = split1.length > 1 ? URLDecoder.decode(split1[1], charset) : "";
153-
map.computeIfAbsent(key, s -> new ArrayList<>()).add(val);
154-
}
155-
return map;
156-
} catch (UnsupportedEncodingException e) {
157-
throw new UncheckedIOException(e);
146+
Map<String, List<String>> map = new LinkedHashMap<>();
147+
for (String pair : body.split("&")) {
148+
final String[] split1 = pair.split("=", 2);
149+
String key = UrlDecode.decode(split1[0], charset);
150+
String val = split1.length > 1 ? UrlDecode.decode(split1[1], charset) : "";
151+
map.computeIfAbsent(key, s -> new ArrayList<>()).add(val);
158152
}
153+
return map;
159154
}
160155

161156
String scheme() {

avaje-jex/src/main/java/io/avaje/jex/http/ContentType.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package io.avaje.jex.http;
22

3+
/** Common Content Types */
34
public enum ContentType {
4-
55
TEXT_PLAIN("text/plain"),
66
TEXT_CSS("text/css"),
77
TEXT_CSV("text/csv"),

avaje-jex/src/main/java/io/avaje/jex/http/HttpFilter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ interface FilterChain {
5555
}
5656

5757
/**
58-
* Convert the JDK Filter into a Jex HttpFilter.
58+
* Convert a JDK {@link Filter} into a Jex HttpFilter.
5959
*/
6060
static HttpFilter fromJdkFilter(Filter filter) {
6161
return new JdkFilter(filter);

avaje-jex/src/main/java/io/avaje/jex/routes/PathSegment.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
import static java.util.stream.Collectors.joining;
66

7-
abstract class PathSegment {
7+
abstract sealed class PathSegment {
88

99
abstract String asRegexString(boolean extract);
1010

@@ -35,7 +35,7 @@ boolean multiSlash() {
3535
}
3636
}
3737

38-
private abstract static class Parameter extends PathSegment {
38+
private abstract static sealed class Parameter extends PathSegment {
3939
private final String name;
4040
private final String regex;
4141

avaje-jex/src/main/java/io/avaje/jex/routes/RouteEntry.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ final class RouteEntry implements SpiRoutes.Entry {
2222

2323
@Override
2424
public SpiRoutes.Entry multiHandler(ExchangeHandler[] handlers) {
25-
final var handler = new MultiHandler(handlers);
26-
return new RouteEntry(path, handler, roles);
25+
final var multi = new MultiHandler(handlers);
26+
return new RouteEntry(path, multi, roles);
2727
}
2828

2929
@Override
Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
package io.avaje.jex.routes;
22

33
import java.net.URLDecoder;
4+
import java.nio.charset.Charset;
45

56
import static java.nio.charset.StandardCharsets.UTF_8;
67

7-
final class UrlDecode {
8+
public final class UrlDecode {
89

9-
static String decode(String s) {
10-
return URLDecoder.decode(s.replace("+", "%2B"), UTF_8).replace("%2B", "+");
10+
public static String decode(String s) {
11+
return decode(s, UTF_8);
1112
}
1213

14+
public static String decode(String s, Charset charset) {
15+
return URLDecoder.decode(s.replace("+", "%2B"), charset).replace("%2B", "+");
16+
}
1317
}

avaje-jex/src/test/java/io/avaje/jex/core/ContextUtilTest.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,16 @@ class ContextUtilTest {
1010

1111
@Test
1212
void parseCharset_defaults() {
13-
assertThat(ServiceManager.parseCharset("")).isEqualTo(StandardCharsets.UTF_8.name());
14-
assertThat(ServiceManager.parseCharset("junk")).isEqualTo(StandardCharsets.UTF_8.name());
13+
assertThat(ServiceManager.parseCharset("")).isEqualTo(StandardCharsets.UTF_8);
14+
assertThat(ServiceManager.parseCharset("junk")).isEqualTo(StandardCharsets.UTF_8);
1515
}
1616

1717
@Test
1818
void parseCharset_caseCheck() {
19-
assertThat(ServiceManager.parseCharset("app/foo; charset=ME")).isEqualTo("ME");
20-
assertThat(ServiceManager.parseCharset("app/foo;charset=ME")).isEqualTo("ME");
21-
assertThat(ServiceManager.parseCharset("app/foo;charset = ME ")).isEqualTo("ME");
22-
assertThat(ServiceManager.parseCharset("app/foo;charset = ME;")).isEqualTo("ME");
23-
assertThat(ServiceManager.parseCharset("app/foo;charset = ME;other=junk")).isEqualTo("ME");
19+
assertThat(ServiceManager.parseCharset("app/foo; charset=Us-AsCiI")).isEqualTo(StandardCharsets.US_ASCII);
20+
assertThat(ServiceManager.parseCharset("app/foo;charset=Us-AsCiI")).isEqualTo(StandardCharsets.US_ASCII);
21+
assertThat(ServiceManager.parseCharset("app/foo;charset = Us-AsCiI ")).isEqualTo(StandardCharsets.US_ASCII);
22+
assertThat(ServiceManager.parseCharset("app/foo;charset = Us-AsCiI;")).isEqualTo(StandardCharsets.US_ASCII);
23+
assertThat(ServiceManager.parseCharset("app/foo;charset = Us-AsCiI;other=junk")).isEqualTo(StandardCharsets.US_ASCII);
2424
}
2525
}

avaje-jex/src/test/java/io/avaje/jex/core/QueryParamTest.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ static TestPair init() {
2121
.get("/queryParamMap", ctx -> ctx.text("qpm: "+ctx.queryParamMap()))
2222
.get("/queryParams", ctx -> ctx.text("qps: "+ctx.queryParams("a")))
2323
.get("/queryString", ctx -> ctx.text("qs: "+ctx.queryString()))
24+
.get("/plus/{plus}", ctx -> ctx.text(ctx.pathParam("plus")+ctx.queryParam("plus")))
2425
.get("/scheme", ctx -> ctx.text("scheme: "+ctx.scheme()))
2526
);
2627
return TestPair.create(app);
@@ -136,6 +137,15 @@ void queryString_when_set() {
136137
assertThat(res.body()).isEqualTo("qs: foo=f1&bar=b1&bar=b2");
137138
}
138139

140+
@Test
141+
void plus() {
142+
HttpResponse<String> res = pair.request().path("plus/+")
143+
.queryParam("plus","+")
144+
.GET().asString();
145+
assertThat(res.statusCode()).isEqualTo(200);
146+
assertThat(res.body()).isEqualTo("++");
147+
}
148+
139149
@Test
140150
void scheme() {
141151
HttpResponse<String> res = pair.request().path("scheme")

0 commit comments

Comments
 (0)