Skip to content

Commit e6c2193

Browse files
committed
Added OptionalString, multiple bodies (to be implemented), lazy content
1 parent ed0d23b commit e6c2193

File tree

12 files changed

+393
-66
lines changed

12 files changed

+393
-66
lines changed

Diff for: src/main/java/dev/latvian/apps/tinyserver/HTTPServer.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -261,16 +261,16 @@ boolean handleClient(HTTPConnection<REQ> connection) {
261261
path = path.substring(0, path.length() - 1);
262262
}
263263

264-
Map<String, String> query = queryString.isEmpty() ? Map.of() : new HashMap<>();
264+
Map<String, OptionalString> query = queryString.isEmpty() ? Map.of() : new HashMap<>();
265265

266266
if (!queryString.isEmpty()) {
267267
for (var part : queryString.split("&")) {
268268
var parts = part.split("=", 2);
269269

270270
if (parts.length == 2) {
271-
query.put(URLDecoder.decode(parts[0], StandardCharsets.UTF_8), URLDecoder.decode(parts[1], StandardCharsets.UTF_8));
271+
query.put(URLDecoder.decode(parts[0], StandardCharsets.UTF_8), OptionalString.of(URLDecoder.decode(parts[1], StandardCharsets.UTF_8)));
272272
} else {
273-
query.put(URLDecoder.decode(parts[0], StandardCharsets.UTF_8), "");
273+
query.put(URLDecoder.decode(parts[0], StandardCharsets.UTF_8), OptionalString.EMPTY);
274274
}
275275
}
276276
}
@@ -290,7 +290,7 @@ boolean handleClient(HTTPConnection<REQ> connection) {
290290
var header = new Header(parts[0].trim(), parts[1].trim());
291291
headers.add(header);
292292

293-
if (header.is("Connection") && header.value().equalsIgnoreCase("keep-alive")) {
293+
if (header.is("Connection") && header.value().asString().equalsIgnoreCase("keep-alive")) {
294294
keepAlive = true;
295295
}
296296
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
package dev.latvian.apps.tinyserver;
2+
3+
public record OptionalString(String value) {
4+
public static final OptionalString MISSING = new OptionalString(null);
5+
public static final OptionalString EMPTY = new OptionalString("");
6+
7+
public static OptionalString of(String str) {
8+
return str == null ? MISSING : str.isEmpty() ? EMPTY : new OptionalString(str);
9+
}
10+
11+
public boolean isMissing() {
12+
return value == null;
13+
}
14+
15+
public boolean isPresent() {
16+
return value != null;
17+
}
18+
19+
@Override
20+
public String toString() {
21+
return value == null ? "<empty>" : value;
22+
}
23+
24+
public String asString() {
25+
return value == null ? "" : value;
26+
}
27+
28+
public String asString(String def) {
29+
return value == null ? def : value;
30+
}
31+
32+
public int asInt() {
33+
return asInt(0);
34+
}
35+
36+
public int asInt(int def) {
37+
if (value == null) {
38+
return def;
39+
}
40+
41+
try {
42+
return Integer.parseInt(value);
43+
} catch (NumberFormatException ex) {
44+
return def;
45+
}
46+
}
47+
48+
public long asLong() {
49+
return asLong(0L);
50+
}
51+
52+
public long asLong(long def) {
53+
if (value == null) {
54+
return def;
55+
}
56+
57+
try {
58+
return Long.parseLong(value);
59+
} catch (NumberFormatException ex) {
60+
return def;
61+
}
62+
}
63+
64+
public long asULong() {
65+
return asULong(0L);
66+
}
67+
68+
public long asULong(long def) {
69+
if (value == null) {
70+
return def;
71+
}
72+
73+
try {
74+
return Long.parseUnsignedLong(value);
75+
} catch (NumberFormatException ex) {
76+
return def;
77+
}
78+
}
79+
80+
public float asFloat() {
81+
return asFloat(0F);
82+
}
83+
84+
public float asFloat(float def) {
85+
if (value == null) {
86+
return def;
87+
}
88+
89+
try {
90+
return Float.parseFloat(value);
91+
} catch (NumberFormatException ex) {
92+
return def;
93+
}
94+
}
95+
96+
public double asDouble() {
97+
return asDouble(0D);
98+
}
99+
100+
public double asDouble(double def) {
101+
if (value == null) {
102+
return def;
103+
}
104+
105+
try {
106+
return Double.parseDouble(value);
107+
} catch (NumberFormatException ex) {
108+
return def;
109+
}
110+
}
111+
}

Diff for: src/main/java/dev/latvian/apps/tinyserver/ServerRegistry.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ default void post(String path, HTTPHandler<REQ> handler) {
3232

3333
default void acceptPostString(String path, Consumer<String> handler) {
3434
post(path, req -> {
35-
handler.accept(req.body());
35+
handler.accept(req.mainBody().text());
3636
return HTTPResponse.noContent();
3737
});
3838
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package dev.latvian.apps.tinyserver.content;
2+
3+
import dev.latvian.apps.tinyserver.HTTPConnection;
4+
5+
import java.io.IOException;
6+
import java.io.OutputStream;
7+
import java.net.http.HttpRequest;
8+
import java.util.function.Supplier;
9+
10+
public class LazyContent implements ResponseContent {
11+
private final Supplier<ResponseContent> content;
12+
private ResponseContent cached;
13+
14+
public LazyContent(Supplier<ResponseContent> content) {
15+
this.content = content;
16+
this.cached = null;
17+
}
18+
19+
public ResponseContent get() {
20+
if (cached == null) {
21+
cached = content.get();
22+
}
23+
24+
return cached;
25+
}
26+
27+
@Override
28+
public long length() {
29+
return get().length();
30+
}
31+
32+
@Override
33+
public String type() {
34+
return get().type();
35+
}
36+
37+
@Override
38+
public boolean hasData() {
39+
return get().hasData();
40+
}
41+
42+
@Override
43+
public void write(OutputStream out) throws IOException {
44+
get().write(out);
45+
}
46+
47+
@Override
48+
public byte[] toBytes() throws IOException {
49+
return get().toBytes();
50+
}
51+
52+
@Override
53+
public void transferTo(HTTPConnection<?> connection) throws IOException {
54+
get().transferTo(connection);
55+
}
56+
57+
@Override
58+
public HttpRequest.BodyPublisher bodyPublisher() throws IOException {
59+
return get().bodyPublisher();
60+
}
61+
}
+96
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
package dev.latvian.apps.tinyserver.http;
2+
3+
import dev.latvian.apps.tinyserver.OptionalString;
4+
import dev.latvian.apps.tinyserver.content.MimeType;
5+
6+
import java.io.ByteArrayOutputStream;
7+
import java.net.URLDecoder;
8+
import java.nio.ByteBuffer;
9+
import java.nio.charset.StandardCharsets;
10+
import java.util.Collections;
11+
import java.util.LinkedHashMap;
12+
import java.util.Map;
13+
14+
public class Body {
15+
ByteBuffer byteBuffer;
16+
Map<String, OptionalString> properties; // new LinkedHashMap<>()
17+
String name = "";
18+
String fileName = "";
19+
String contentType = MimeType.TEXT;
20+
21+
public ByteBuffer byteBuffer() {
22+
return byteBuffer.position(0);
23+
}
24+
25+
public String text() {
26+
return StandardCharsets.UTF_8.decode(byteBuffer()).toString();
27+
}
28+
29+
public byte[] bytes() {
30+
var buf = byteBuffer();
31+
32+
try {
33+
return buf.array();
34+
} catch (Exception ex) {
35+
var out = new ByteArrayOutputStream(buf.remaining());
36+
37+
while (buf.hasRemaining()) {
38+
out.write(buf.get());
39+
}
40+
41+
return out.toByteArray();
42+
}
43+
}
44+
45+
public OptionalString property(String key) {
46+
return properties == null || properties.isEmpty() ? OptionalString.MISSING : properties.getOrDefault(key.toLowerCase(), OptionalString.MISSING);
47+
}
48+
49+
public String name() {
50+
return name;
51+
}
52+
53+
public String fileName() {
54+
return fileName;
55+
}
56+
57+
public String contentType() {
58+
return contentType;
59+
}
60+
61+
public Map<String, OptionalString> getPostData() {
62+
var text = text();
63+
64+
if (text.isEmpty()) {
65+
return Collections.emptyMap();
66+
}
67+
68+
var map = new LinkedHashMap<String, OptionalString>(4);
69+
70+
for (var s : text.split("&")) {
71+
var p = s.split("=", 2);
72+
73+
try {
74+
var k = URLDecoder.decode(p[0], StandardCharsets.UTF_8);
75+
76+
if (!k.isEmpty()) {
77+
if (p.length == 2) {
78+
map.put(k, OptionalString.of(URLDecoder.decode(p[1], StandardCharsets.UTF_8)));
79+
} else {
80+
map.put(k, OptionalString.EMPTY);
81+
}
82+
}
83+
} catch (Exception ex) {
84+
ex.printStackTrace();
85+
}
86+
}
87+
88+
return map;
89+
}
90+
91+
@Override
92+
public String toString() {
93+
return name.isEmpty() ? "body" : name;
94+
}
95+
}
96+

0 commit comments

Comments
 (0)