From a1cf4ada496f1c6915ad769b8dddd167485bfd40 Mon Sep 17 00:00:00 2001
From: Relism
Date: Sun, 26 Apr 2026 13:00:08 +0200
Subject: [PATCH] fix: merge jte extension refactor with static serving
features
- Move JteStaticServing to dev.relism.flash package
- Fix imports in HttpStatus and test files
- Add fluent config methods to JteExtension (templateRoot, serveStatics, staticPrefix, etc.)
- Implement routes() for static asset serving with HEAD support
- Include Main.java entry point
---
.../src/main/resources/routeviewer/index.html | 22 +++----
.../ondemand/pages/JtehomeGenerated.class | Bin 2113 -> 2126 bytes
.../ondemand/pages/JtehomeGenerated.java | 10 +--
.../flash/ext/view/jte/JteExtension.java | 60 ++++++++++++++++--
.../ext/view/jte/JteStaticServing.java | 10 +--
.../flash/ext/view/jte/JteExtensionTest.java | 40 +++++-------
.../ext/view/jte/JteStaticServingTest.java | 4 +-
.../src/main/java/dev/relism/flash/Main.java | 48 ++++++++++++++
.../dev/relism/flash/http/HttpStatus.java | 5 --
9 files changed, 144 insertions(+), 55 deletions(-)
rename flash-extensions/flash-ext-view-jte/src/main/java/dev/relism/{ => flash}/ext/view/jte/JteStaticServing.java (98%)
rename flash-extensions/flash-ext-view-jte/src/test/java/dev/relism/{ => flash}/ext/view/jte/JteStaticServingTest.java (98%)
create mode 100644 flash/src/main/java/dev/relism/flash/Main.java
diff --git a/flash-extensions/flash-ext-routeviewer/src/main/resources/routeviewer/index.html b/flash-extensions/flash-ext-routeviewer/src/main/resources/routeviewer/index.html
index 720f499..bab0ef8 100644
--- a/flash-extensions/flash-ext-routeviewer/src/main/resources/routeviewer/index.html
+++ b/flash-extensions/flash-ext-routeviewer/src/main/resources/routeviewer/index.html
@@ -1,13 +1,13 @@
-
-
-
-
-
- Flash Route Viewer
+
+
+
+
+
+ Flash Route Viewer
-
-
-
-
-
+
+
+
+
+
diff --git a/flash-extensions/flash-ext-view-jte/jte-classes/gg/jte/generated/ondemand/pages/JtehomeGenerated.class b/flash-extensions/flash-ext-view-jte/jte-classes/gg/jte/generated/ondemand/pages/JtehomeGenerated.class
index 64f788b358a3558fce92ce5022a8e5105c6c8d88..22995af0c53796fd6a4e1d9873bb02988921f760 100644
GIT binary patch
delta 150
zcmX>oa86)?9V6>RhfRVyDXC@pMX5QN#ku-vIf=y?lMPv9CQC9pvT@qzXBgT|PGnS8
zF7#Rd?^dSna8O`^9TOYxMEgzLYALB@`bDWZnZ>!2KQPHmmSc2e=d#hyFtp>HoXV)o#%rTr
z0A%(uN^l9<=ojZE=Hvjm>lkaefU00zW2Rij&dCdzye5BS`pdW;%Cgy9&2pI;05UHl
A2><{9
diff --git a/flash-extensions/flash-ext-view-jte/jte-classes/gg/jte/generated/ondemand/pages/JtehomeGenerated.java b/flash-extensions/flash-ext-view-jte/jte-classes/gg/jte/generated/ondemand/pages/JtehomeGenerated.java
index 421290c..9fb39b4 100644
--- a/flash-extensions/flash-ext-view-jte/jte-classes/gg/jte/generated/ondemand/pages/JtehomeGenerated.java
+++ b/flash-extensions/flash-ext-view-jte/jte-classes/gg/jte/generated/ondemand/pages/JtehomeGenerated.java
@@ -6,19 +6,19 @@ public final class JtehomeGenerated {
public static final String JTE_NAME = "pages/home.jte";
public static final int[] JTE_LINE_INFO = {0,0,1,2,2,2,2,6,6,6,6,7,7,7,8,8,8,9,9,9,10,10,10,2,3,4,4,4,4};
public static void render(gg.jte.html.HtmlTemplateOutput jteOutput, gg.jte.html.HtmlInterceptor jteHtmlInterceptor, HomePage page, String build, Map global) {
- jteOutput.writeContent("\r\n");
+ jteOutput.writeContent("\n");
jteOutput.setContext("h1", null);
jteOutput.writeUserContent(page.title());
- jteOutput.writeContent("
\r\n
");
+ jteOutput.writeContent("\n
");
jteOutput.setContext("p", null);
jteOutput.writeUserContent(page.author());
- jteOutput.writeContent("
\r\n");
+ jteOutput.writeContent("
\n");
jteOutput.setContext("small", null);
jteOutput.writeUserContent(build);
- jteOutput.writeContent("\r\n");
+ jteOutput.writeContent("\n");
jteOutput.setContext("small", null);
jteOutput.writeUserContent((String) global.get("appName"));
- jteOutput.writeContent("\r\n");
+ jteOutput.writeContent("\n");
}
public static void renderMap(gg.jte.html.HtmlTemplateOutput jteOutput, gg.jte.html.HtmlInterceptor jteHtmlInterceptor, java.util.Map params) {
HomePage page = (HomePage)params.get("page");
diff --git a/flash-extensions/flash-ext-view-jte/src/main/java/dev/relism/flash/ext/view/jte/JteExtension.java b/flash-extensions/flash-ext-view-jte/src/main/java/dev/relism/flash/ext/view/jte/JteExtension.java
index 6ff638c..d7cbf7f 100644
--- a/flash-extensions/flash-ext-view-jte/src/main/java/dev/relism/flash/ext/view/jte/JteExtension.java
+++ b/flash-extensions/flash-ext-view-jte/src/main/java/dev/relism/flash/ext/view/jte/JteExtension.java
@@ -1,5 +1,7 @@
package dev.relism.flash.ext.view.jte;
+import dev.relism.flash.extension.FlashContext;
+import dev.relism.flash.extension.FlashRegistrar;
import dev.relism.flash.ext.view.core.BaseViewExtension;
import dev.relism.flash.ext.view.core.GlobalValue;
import dev.relism.flash.ext.view.core.ViewRuntimeBridge;
@@ -10,9 +12,6 @@ import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
-/**
- * Opinionated jte SSR extension for Flash.
- */
public final class JteExtension extends BaseViewExtension {
private final JteSettings settings;
@@ -21,7 +20,7 @@ public final class JteExtension extends BaseViewExtension {
}
public JteExtension() {
- this(JteSettings.builder().build());
+ this.settings = JteSettings.builder().build();
}
public JteExtension(Consumer customizer) {
@@ -34,6 +33,41 @@ public final class JteExtension extends BaseViewExtension {
this.settings = settings;
}
+ public JteExtension templateRoot(String templateRoot) {
+ return new JteExtension(settings.toBuilder().templateRoot(templateRoot).build());
+ }
+
+ public JteExtension serveStatics(boolean serveStatics) {
+ return new JteExtension(settings.toBuilder().serveStatics(serveStatics).build());
+ }
+
+ public JteExtension staticPrefix(String staticPrefix) {
+ return new JteExtension(settings.toBuilder().staticPrefix(staticPrefix).build());
+ }
+
+ public JteExtension withStaticCors() {
+ return new JteExtension(settings.toBuilder().enableStaticCors(true).build());
+ }
+
+ public JteExtension staticCors(Consumer corsConfig) {
+ JteSettings.Builder builder = settings.toBuilder();
+ builder.enableStaticCors(true);
+ corsConfig.accept(builder);
+ return new JteExtension(builder.build());
+ }
+
+ @Override
+ public void routes(FlashRegistrar> app, FlashContext ctx) {
+ if (!settings.serveStatics()) return;
+ JteStaticServing staticServing = JteStaticServing.load(settings);
+ if (staticServing == null) return;
+
+ String wildcard = settings.staticPrefix() + "/**";
+ StaticJteHandler handler = new StaticJteHandler(staticServing);
+ app.get(wildcard, handler::handle);
+ app.head(wildcard, (req, res) -> { staticServing.serve(req, res, true); return null; });
+ }
+
@Override
public JteExtension addGlobal(String key, Function resolver) {
super.addGlobal(key, resolver);
@@ -60,6 +94,24 @@ public final class JteExtension extends BaseViewExtension {
}
}
+ JteSettings getSettings() {
+ return settings;
+ }
+
+ private static final class StaticJteHandler extends dev.relism.flash.models.RequestHandler {
+ private final JteStaticServing serving;
+
+ StaticJteHandler(JteStaticServing serving) {
+ this.serving = serving;
+ }
+
+ @Override
+ public Object handle(dev.relism.flash.models.Request req, dev.relism.flash.models.Response res) {
+ serving.serve(req, res, false);
+ return null;
+ }
+ }
+
private static void ensureJtePresent() {
try {
Class.forName("gg.jte.TemplateEngine", false, JteExtension.class.getClassLoader());
diff --git a/flash-extensions/flash-ext-view-jte/src/main/java/dev/relism/ext/view/jte/JteStaticServing.java b/flash-extensions/flash-ext-view-jte/src/main/java/dev/relism/flash/ext/view/jte/JteStaticServing.java
similarity index 98%
rename from flash-extensions/flash-ext-view-jte/src/main/java/dev/relism/ext/view/jte/JteStaticServing.java
rename to flash-extensions/flash-ext-view-jte/src/main/java/dev/relism/flash/ext/view/jte/JteStaticServing.java
index 16a0f7c..b0a8dee 100644
--- a/flash-extensions/flash-ext-view-jte/src/main/java/dev/relism/ext/view/jte/JteStaticServing.java
+++ b/flash-extensions/flash-ext-view-jte/src/main/java/dev/relism/flash/ext/view/jte/JteStaticServing.java
@@ -1,8 +1,8 @@
-package dev.relism.ext.view.jte;
+package dev.relism.flash.ext.view.jte;
-import dev.relism.http.HttpStatus;
-import dev.relism.models.Request;
-import dev.relism.models.Response;
+import dev.relism.flash.http.HttpStatus;
+import dev.relism.flash.models.Request;
+import dev.relism.flash.models.Response;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -202,4 +202,4 @@ final class JteStaticServing {
}
private record RangeSlice(int start, int end, int length) {}
-}
+}
\ No newline at end of file
diff --git a/flash-extensions/flash-ext-view-jte/src/test/java/dev/relism/flash/ext/view/jte/JteExtensionTest.java b/flash-extensions/flash-ext-view-jte/src/test/java/dev/relism/flash/ext/view/jte/JteExtensionTest.java
index 0f8e2c6..4a9d129 100644
--- a/flash-extensions/flash-ext-view-jte/src/test/java/dev/relism/flash/ext/view/jte/JteExtensionTest.java
+++ b/flash-extensions/flash-ext-view-jte/src/test/java/dev/relism/flash/ext/view/jte/JteExtensionTest.java
@@ -92,7 +92,7 @@ class JteExtensionTest {
void routes_register_static_wildcard_when_enabled() {
JteExtension ext = new JteExtension(cfg -> cfg.staticPrefix("/assets"));
TestRegistrar app = new TestRegistrar();
- ext.routes(app, new dev.relism.extension.FlashContext());
+ ext.routes(app, new dev.relism.flash.extension.FlashContext());
assertTrue(app.routes.containsKey("GET /assets/**"));
assertTrue(app.routes.containsKey("HEAD /assets/**"));
}
@@ -101,7 +101,7 @@ class JteExtensionTest {
void routes_do_not_register_static_when_disabled() {
JteExtension ext = new JteExtension().serveStatics(false);
TestRegistrar app = new TestRegistrar();
- ext.routes(app, new dev.relism.extension.FlashContext());
+ ext.routes(app, new dev.relism.flash.extension.FlashContext());
assertTrue(app.routes.isEmpty());
}
@@ -111,10 +111,10 @@ class JteExtensionTest {
.staticPrefix("/assets")
.largeFileThresholdBytes(1));
TestRegistrar app = new TestRegistrar();
- ext.routes(app, new dev.relism.extension.FlashContext());
+ ext.routes(app, new dev.relism.flash.extension.FlashContext());
Request req = request("/assets/sample.css", null, null, null);
- Response res = new Response(200, dev.relism.http.ContentType.TEXT_PLAIN);
+ Response res = new Response(200, dev.relism.flash.http.ContentType.TEXT_PLAIN);
Object out = app.routes.get("GET /assets/**").handle(req, res);
assertEquals(null, out);
@@ -124,13 +124,7 @@ class JteExtensionTest {
}
private static JteSettings readSettings(JteExtension ext) {
- try {
- var f = JteExtension.class.getDeclaredField("settings");
- f.setAccessible(true);
- return (JteSettings) f.get(ext);
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
+ return ext.getSettings();
}
private static void invokeValidate(JteExtension ext, Class extends RequestHandler> type) throws Exception {
@@ -147,39 +141,39 @@ class JteExtensionTest {
}
private static Request request(String path, String query, String acceptEncoding, String origin) {
- dev.relism.models.HeaderMap headers = new dev.relism.models.HeaderMap();
+ dev.relism.flash.models.HeaderMap headers = new dev.relism.flash.models.HeaderMap();
String raw = "Host: localhost\r\n";
if (acceptEncoding != null) raw += "Accept-Encoding: " + acceptEncoding + "\r\n";
if (origin != null) raw += "Origin: " + origin + "\r\n";
byte[] bytes = raw.getBytes(StandardCharsets.UTF_8);
headers.reset(bytes, 0, bytes.length);
- dev.relism.models.RequestLine line = new dev.relism.models.RequestLine(
- dev.relism.http.HttpMethod.GET,
- new dev.relism.routing.routers.fastpathrouter.FastPathViews.StringByteView(path),
- query == null ? null : new dev.relism.routing.routers.fastpathrouter.FastPathViews.StringByteView(query),
- new dev.relism.routing.routers.fastpathrouter.FastPathViews.StringByteView("HTTP/1.1"),
+ dev.relism.flash.models.RequestLine line = new dev.relism.flash.models.RequestLine(
+ dev.relism.flash.http.HttpMethod.GET,
+ new dev.relism.flash.routing.routers.fastpathrouter.FastPathViews.StringByteView(path),
+ query == null ? null : new dev.relism.flash.routing.routers.fastpathrouter.FastPathViews.StringByteView(query),
+ new dev.relism.flash.routing.routers.fastpathrouter.FastPathViews.StringByteView("HTTP/1.1"),
headers
);
return new Request(line, new byte[0]);
}
- private static final class TestRegistrar extends dev.relism.extension.FlashRegistrar {
+ private static final class TestRegistrar extends dev.relism.flash.extension.FlashRegistrar {
private final Map routes = new HashMap<>();
- private final List mws = new ArrayList<>();
+ private final List mws = new ArrayList<>();
@Override
- public dev.relism.extension.FlashContext ctx() {
- return new dev.relism.extension.FlashContext();
+ public dev.relism.flash.extension.FlashContext ctx() {
+ return new dev.relism.flash.extension.FlashContext();
}
@Override
- protected void addRoute(dev.relism.http.HttpMethod method, String path, RequestHandler handler, List mw) {
+ protected void addRoute(dev.relism.flash.http.HttpMethod method, String path, RequestHandler handler, List mw) {
routes.put(method.name() + " " + path, handler);
}
@Override
- protected void addMiddleware(dev.relism.routing.Middleware mw) {
+ protected void addMiddleware(dev.relism.flash.routing.Middleware mw) {
mws.add(mw);
}
}
diff --git a/flash-extensions/flash-ext-view-jte/src/test/java/dev/relism/ext/view/jte/JteStaticServingTest.java b/flash-extensions/flash-ext-view-jte/src/test/java/dev/relism/flash/ext/view/jte/JteStaticServingTest.java
similarity index 98%
rename from flash-extensions/flash-ext-view-jte/src/test/java/dev/relism/ext/view/jte/JteStaticServingTest.java
rename to flash-extensions/flash-ext-view-jte/src/test/java/dev/relism/flash/ext/view/jte/JteStaticServingTest.java
index 405e7d1..3060cff 100644
--- a/flash-extensions/flash-ext-view-jte/src/test/java/dev/relism/ext/view/jte/JteStaticServingTest.java
+++ b/flash-extensions/flash-ext-view-jte/src/test/java/dev/relism/flash/ext/view/jte/JteStaticServingTest.java
@@ -1,4 +1,4 @@
-package dev.relism.ext.view.jte;
+package dev.relism.flash.ext.view.jte;
import org.junit.jupiter.api.Test;
@@ -47,4 +47,4 @@ class JteStaticServingTest {
assertEquals(-1, JteStaticServing.rangeLength("bytes=100-120", 100));
assertEquals(-1, JteStaticServing.rangeLength("invalid", 100));
}
-}
+}
\ No newline at end of file
diff --git a/flash/src/main/java/dev/relism/flash/Main.java b/flash/src/main/java/dev/relism/flash/Main.java
new file mode 100644
index 0000000..f4c5813
--- /dev/null
+++ b/flash/src/main/java/dev/relism/flash/Main.java
@@ -0,0 +1,48 @@
+package dev.relism.flash;
+
+import dev.relism.flash.extension.FlashApp;
+import dev.relism.flash.http.ContentType;
+import dev.relism.flash.http.HttpMethod;
+import dev.relism.flash.routing.Middleware;
+import lombok.extern.slf4j.Slf4j;
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+@Slf4j
+public class Main {
+
+ private static final int PORT = 8080;
+ private static final Path UPLOAD_DIR = Path.of(System.getProperty("java.io.tmpdir"), "flash-uploads");
+
+ private static final Middleware CORS = next -> (req, res) -> {
+ res
+ .header("Access-Control-Allow-Origin", "*")
+ .header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
+ .header("Access-Control-Allow-Headers", "Content-Type, Authorization");
+ if (req.method() == HttpMethod.OPTIONS) { res.status(204); return null; }
+ return next.handle(req, res);
+ };
+
+ private static final Middleware ACCESS_LOG = next -> (req, res) -> {
+ long start = System.nanoTime();
+ try {
+ return next.handle(req, res);
+ } finally {
+ log.info("{} {} -> {}ms", req.method(), req.path(),
+ (System.nanoTime() - start) / 1_000_000.0);
+ }
+ };
+
+
+ public static void main(String[] args) throws Exception {
+ Files.createDirectories(UPLOAD_DIR);
+
+ FlashApp.create(PORT)
+ .get("/plaintext", (req, res) -> {
+ res.type(ContentType.TEXT_PLAIN);
+ return "Hello, World!";
+ }, ACCESS_LOG, CORS)
+ .startAndBlock();
+ }
+}
diff --git a/flash/src/main/java/dev/relism/flash/http/HttpStatus.java b/flash/src/main/java/dev/relism/flash/http/HttpStatus.java
index 9d3f3ca..58bafba 100644
--- a/flash/src/main/java/dev/relism/flash/http/HttpStatus.java
+++ b/flash/src/main/java/dev/relism/flash/http/HttpStatus.java
@@ -1,10 +1,5 @@
package dev.relism.flash.http;
-import dev.relism.models.Request;
-import dev.relism.models.Response;
-import dev.relism.routing.GET;
-import dev.relism.routing.Route;
-
import java.nio.charset.StandardCharsets;
import java.util.List;