Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
package io.avaje.jex.staticcontent;

import java.net.URLConnection;
import java.util.function.Predicate;

import io.avaje.jex.Context;
import io.avaje.jex.spi.JexPlugin;

/**
* Static content resource handler.
* <pre>{@code
*
* var staticContent = StaticContent.createFile("src/test/resources/public")
* .directoryIndex("index.html")
* .preCompress()
* .build()
*
* Jex.create()
* .plugin(staticContent)
* .port(8080)
* .start();
*
* }</pre>
*/
public sealed interface StaticContent extends JexPlugin
permits StaticResourceHandlerBuilder {

/**
* Create and return a new static content class path configuration.
*
* @param resourceRoot The file to serve, or the directory the files are located in.
*/
static Builder createCP(String resourceRoot) {
return StaticResourceHandlerBuilder.builder(resourceRoot);
}

/**
* Create and return a new static content class path configuration with the
* `/public` directory as the root.
*/
static Builder createCP() {
return StaticResourceHandlerBuilder.builder("/public/");
}

/**
* Create and return a new static content configuration for a File.
*
* @param resourceRoot The path of the file to serve, or the directory the files are located in.
*/
static Builder createFile(String resourceRoot) {
return StaticResourceHandlerBuilder.builder(resourceRoot).file();
}

/**
* Builder for StaticContent.
*/
sealed interface Builder
permits StaticResourceHandlerBuilder {

/**
* Sets the HTTP path for the static resource handler.
*
* @param path the HTTP path prefix
* @return the updated configuration
*/
Builder httpPath(String path);

/**
* Sets the index file to be served when a directory is requests.
*
* @param directoryIndex the index file
* @return the updated configuration
*/
Builder directoryIndex(String directoryIndex);

/**
* Sent resources will be pre-compressed and cached in memory when this is enabled
*
* @return the updated configuration
*/
Builder preCompress();

/**
* Sets a custom resource loader for loading class/module path resources. This is normally used
* when running the application on the module path when files cannot be discovered.
*
* <p>Example usage: {@code service.resourceLoader(ClassResourceLoader.create(getClass())) }
*
* @param resourceLoader the custom resource loader
* @return the updated configuration
*/
Builder resourceLoader(ClassResourceLoader resourceLoader);

/**
* Adds a new MIME type mapping to the configuration. (Default: uses {@link
* URLConnection#getFileNameMap()}
*
* @param ext the file extension (e.g., "html", "css", "js")
* @param mimeType the corresponding MIME type (e.g., "text/html", "text/css",
* "application/javascript")
* @return the updated configuration
*/
Builder putMimeTypeMapping(String ext, String mimeType);

/**
* Adds a new response header to the configuration.
*
* @param key the header name
* @param value the header value
* @return the updated configuration
*/
Builder putResponseHeader(String key, String value);

/**
* Sets a predicate to filter files based on the request context.
*
* @param skipFilePredicate the predicate to use
* @return the updated configuration
*/
Builder skipFilePredicate(Predicate<Context> skipFilePredicate);

/**
* Build and return the StaticContent.
*/
StaticContent build();
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import io.avaje.jex.Jex;
import io.avaje.jex.compression.CompressionConfig;

final class StaticResourceHandlerBuilder implements StaticContentService {
final class StaticResourceHandlerBuilder implements StaticContent.Builder, StaticContent {

private static final String FAILED_TO_LOCATE_FILE = "Failed to locate file: ";
private static final String DIRECTORY_INDEX_FAILURE =
Expand Down Expand Up @@ -43,6 +43,11 @@ public void apply(Jex jex) {
jex.get(path, createHandler(jex.config().compression()));
}

@Override
public StaticContent build() {
return this;
}

ExchangeHandler createHandler(CompressionConfig compress) {
path =
Objects.requireNonNull(path)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Static Content API - see {@link io.avaje.jex.staticcontent.StaticContentService}.
* Static Content API - see {@link io.avaje.jex.staticcontent.StaticContent}.
*
* <pre>{@code
* var staticContent = StaticContentService.createCP("/public").httpPath("/").directoryIndex("index.html");
Expand Down
2 changes: 1 addition & 1 deletion avaje-jex-static-content/src/main/java/module-info.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Defines the Static Content API for serving static resources with Jex - see {@link io.avaje.jex.staticcontent.StaticContentService}.
* Defines the Static Content API for serving static resources with Jex - see {@link StaticContent}.
*
* <pre>{@code
* var staticContent = StaticContentService.createCP("/public").httpPath("/").directoryIndex("index.html");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,28 +19,30 @@ static TestPair init() {

final Jex app =
Jex.create()
.plugin(defaultCP().httpPath("/index"))
.plugin(defaultFile().httpPath("/indexFile"))
.plugin(defaultCP().httpPath("/indexWild/*"))
.plugin(defaultFile().httpPath("/indexWildFile/*"))
.plugin(defaultCP().httpPath("/sus/"))
.plugin(defaultFile().httpPath("/susFile/*"))
.plugin(StaticContentService.createCP("/logback.xml").httpPath("/single"))
.plugin(defaultCP().httpPath("/index").build())
.plugin(defaultFile().httpPath("/indexFile").build())
.plugin(defaultCP().httpPath("/indexWild/*").build())
.plugin(defaultFile().httpPath("/indexWildFile/*").build())
.plugin(defaultCP().httpPath("/sus/").build())
.plugin(defaultFile().httpPath("/susFile/*").build())
.plugin(StaticContent.createCP("/logback.xml").httpPath("/single").build())
.plugin(
StaticContentService.createFile("src/test/resources/logback.xml")
.httpPath("/singleFile"));
StaticContent.createFile("src/test/resources/logback.xml")
.httpPath("/singleFile").build());

return TestPair.create(app);
}

private static StaticContentService defaultFile() {
return StaticContentService.createFile("src/test/resources/public")
private static StaticContent.Builder defaultFile() {
return StaticContent.createFile("src/test/resources/public")
.directoryIndex("index.html")
.preCompress();
}

private static StaticContentService defaultCP() {
return StaticContentService.createCP("/public").directoryIndex("index.html").preCompress();
private static StaticContent.Builder defaultCP() {
return StaticContent.createCP("/public")
.directoryIndex("index.html")
.preCompress();
}

@AfterAll
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,27 +19,27 @@ static TestPair init() {

final Jex app =
Jex.create()
.plugin(defaultCP().httpPath("/index"))
.plugin(defaultFile().httpPath("/indexFile"))
.plugin(defaultCP().httpPath("/indexWild/*"))
.plugin(defaultFile().httpPath("/indexWildFile/*"))
.plugin(defaultCP().httpPath("/sus/"))
.plugin(defaultFile().httpPath("/susFile/*"))
.plugin(StaticContentService.createCP("/logback.xml").httpPath("/single"))
.plugin(defaultCP().httpPath("/index").build())
.plugin(defaultFile().httpPath("/indexFile").build())
.plugin(defaultCP().httpPath("/indexWild/*").build())
.plugin(defaultFile().httpPath("/indexWildFile/*").build())
.plugin(defaultCP().httpPath("/sus/").build())
.plugin(defaultFile().httpPath("/susFile/*").build())
.plugin(StaticContent.createCP("/logback.xml").httpPath("/single").build())
.plugin(
StaticContentService.createFile("src/test/resources/logback.xml")
.httpPath("/singleFile"));
StaticContent.createFile("src/test/resources/logback.xml")
.httpPath("/singleFile").build());

return TestPair.create(app);
}

private static StaticContentService defaultFile() {
return StaticContentService.createFile("src/test/resources/public")
private static StaticContent.Builder defaultFile() {
return StaticContent.createFile("src/test/resources/public")
.directoryIndex("index.html");
}

private static StaticContentService defaultCP() {
return StaticContentService.createCP("/public").directoryIndex("index.html");
private static StaticContent.Builder defaultCP() {
return StaticContent.createCP("/public").directoryIndex("index.html");
}

@AfterAll
Expand Down
1 change: 1 addition & 0 deletions avaje-jex/src/main/java/io/avaje/jex/Jex.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public sealed interface Jex permits DJex {
* Create Jex.
*
* <pre>{@code
*
* final Jex.Server app = Jex.create()
* .routing(routing -> routing
* .get("/", ctx -> ctx.text("hello world"))
Expand Down
Loading