Merge pull request 'feat(core): add HTTP QUERY method support' (#5) from feature/core/http-query-method into master
CI / Build & Test (push) Canceled after 5s
Publish Snapshot / Deploy Snapshot (push) Canceled after 7s

Reviewed-on: #5
This commit was merged in pull request #5.
This commit is contained in:
2026-08-10 13:29:24 +00:00
5 changed files with 30 additions and 1 deletions
@@ -45,6 +45,7 @@ public abstract class FlashRegistrar<SELF extends FlashRegistrar<SELF>> {
public final SELF trace (String path, SimpleHandler.FunctionalHandler h, Middleware... mw) { return route(HttpMethod.TRACE, path, h, mw); } public final SELF trace (String path, SimpleHandler.FunctionalHandler h, Middleware... mw) { return route(HttpMethod.TRACE, path, h, mw); }
public final SELF connect(String path, SimpleHandler.FunctionalHandler h, Middleware... mw) { return route(HttpMethod.CONNECT, path, h, mw); } public final SELF connect(String path, SimpleHandler.FunctionalHandler h, Middleware... mw) { return route(HttpMethod.CONNECT, path, h, mw); }
public final SELF purge (String path, SimpleHandler.FunctionalHandler h, Middleware... mw) { return route(HttpMethod.PURGE, path, h, mw); } public final SELF purge (String path, SimpleHandler.FunctionalHandler h, Middleware... mw) { return route(HttpMethod.PURGE, path, h, mw); }
public final SELF query (String path, SimpleHandler.FunctionalHandler h, Middleware... mw) { return route(HttpMethod.QUERY, path, h, mw); }
// ── Middleware ──────────────────────────────────────────────────────────── // ── Middleware ────────────────────────────────────────────────────────────
@@ -5,7 +5,7 @@ import java.nio.charset.StandardCharsets;
@Getter @Getter
public enum HttpMethod { public enum HttpMethod {
GET, POST, PUT, DELETE, PATCH, OPTIONS, HEAD, TRACE, CONNECT, PURGE; GET, POST, PUT, DELETE, PATCH, OPTIONS, HEAD, TRACE, CONNECT, PURGE, QUERY;
private static final HttpMethod[] VALUES = values(); private static final HttpMethod[] VALUES = values();
private final byte[] bytes; private final byte[] bytes;
@@ -35,6 +35,7 @@ public enum HttpMethod {
case 'H' -> (len == 4 && buf[off + 1] == 'E' && buf[off + 2] == 'A' && buf[off + 3] == 'D') ? HEAD : null; case 'H' -> (len == 4 && buf[off + 1] == 'E' && buf[off + 2] == 'A' && buf[off + 3] == 'D') ? HEAD : null;
case 'T' -> (len == 5 && buf[off + 1] == 'R' && buf[off + 2] == 'A' && buf[off + 3] == 'C' && buf[off + 4] == 'E') ? TRACE : null; case 'T' -> (len == 5 && buf[off + 1] == 'R' && buf[off + 2] == 'A' && buf[off + 3] == 'C' && buf[off + 4] == 'E') ? TRACE : null;
case 'C' -> (len == 7 && buf[off + 1] == 'O' && buf[off + 2] == 'N' && buf[off + 3] == 'N' && buf[off + 4] == 'E' && buf[off + 5] == 'C' && buf[off + 6] == 'T') ? CONNECT : null; case 'C' -> (len == 7 && buf[off + 1] == 'O' && buf[off + 2] == 'N' && buf[off + 3] == 'N' && buf[off + 4] == 'E' && buf[off + 5] == 'C' && buf[off + 6] == 'T') ? CONNECT : null;
case 'Q' -> (len == 5 && buf[off + 1] == 'U' && buf[off + 2] == 'E' && buf[off + 3] == 'R' && buf[off + 4] == 'Y') ? QUERY : null;
default -> null; default -> null;
}; };
} }
@@ -0,0 +1,16 @@
package dev.relism.flash.routing;
import dev.relism.flash.http.HttpMethod;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/** Shorthand for {@code @Route(method = HttpMethod.QUERY, path = "…")}. */
@Route(method = HttpMethod.QUERY, path = "")
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface QUERY {
String value();
}
@@ -75,6 +75,16 @@ class RequestParserTest {
assertEquals(body, new String(r.body().bytes(), StandardCharsets.UTF_8)); assertEquals(body, new String(r.body().bytes(), StandardCharsets.UTF_8));
} }
@Test
void body_parsed_forQueryMethod() throws IOException {
String body = "{\"filter\":\"active\"}";
String raw = "QUERY / HTTP/1.1\r\nContent-Type: application/json\r\nContent-Length: " + body.length() + "\r\n\r\n" + body;
Request r = new RequestParser().parse(new ByteArrayInputStream(raw.getBytes(StandardCharsets.UTF_8)));
assertNotNull(r);
assertEquals(dev.relism.flash.http.HttpMethod.QUERY, r.method());
assertEquals(body, new String(r.body().bytes(), StandardCharsets.UTF_8));
}
@Test @Test
void body_emptyWhenNoContentLength() throws IOException { void body_emptyWhenNoContentLength() throws IOException {
Request r = parse(req("GET / HTTP/1.1", "Host: localhost")); Request r = parse(req("GET / HTTP/1.1", "Host: localhost"));
@@ -34,6 +34,7 @@ class HttpMethodTest {
assertEquals(HttpMethod.TRACE, parse("TRACE")); assertEquals(HttpMethod.TRACE, parse("TRACE"));
assertEquals(HttpMethod.CONNECT, parse("CONNECT")); assertEquals(HttpMethod.CONNECT, parse("CONNECT"));
assertEquals(HttpMethod.PURGE, parse("PURGE")); assertEquals(HttpMethod.PURGE, parse("PURGE"));
assertEquals(HttpMethod.QUERY, parse("QUERY"));
} }
@Test @Test