diff --git a/net-http-j2html/src/main/java/org/xbib/net/http/j2html/BadRequestHandler.java b/net-http-j2html/src/main/java/org/xbib/net/http/j2html/BadRequestHandler.java new file mode 100644 index 0000000..cb37ccc --- /dev/null +++ b/net-http-j2html/src/main/java/org/xbib/net/http/j2html/BadRequestHandler.java @@ -0,0 +1,41 @@ +package org.xbib.net.http.j2html; + +import org.xbib.net.ParameterException; +import org.xbib.net.Resource; +import org.xbib.net.http.HttpResponseStatus; +import org.xbib.net.http.server.resource.HtmlTemplateResourceHandler; +import org.xbib.net.http.server.route.HttpRouterContext; + +import java.io.IOException; + +import static org.xbib.j2html.TagCreator.body; +import static org.xbib.j2html.TagCreator.h1; +import static org.xbib.j2html.TagCreator.html; + +public class BadRequestHandler extends J2HtmlResourceHandler { + + @Override + protected Resource createResource(HttpRouterContext httpRouterContext) + throws IOException, ParameterException { + return new UnauthorizedResource(this, httpRouterContext); + } + + protected static class UnauthorizedResource extends J2HtmlResource { + + protected UnauthorizedResource(HtmlTemplateResourceHandler templateResourceHandler, + HttpRouterContext httpRouterContext) + throws IOException, ParameterException { + super(templateResourceHandler, httpRouterContext); + } + + @Override + protected HttpResponseStatus getResponseStatus() { + return HttpResponseStatus.BAD_REQUEST; + } + + @Override + protected String renderHtml(HttpRouterContext httpRouterContext) { + return html(body(h1("Bad request"))).render(); + } + } +} diff --git a/net-http-j2html/src/main/java/org/xbib/net/http/j2html/InternalServerErrorHandler.java b/net-http-j2html/src/main/java/org/xbib/net/http/j2html/InternalServerErrorHandler.java index cc8f986..4e7b57e 100644 --- a/net-http-j2html/src/main/java/org/xbib/net/http/j2html/InternalServerErrorHandler.java +++ b/net-http-j2html/src/main/java/org/xbib/net/http/j2html/InternalServerErrorHandler.java @@ -1,6 +1,7 @@ package org.xbib.net.http.j2html; import org.xbib.net.Attributes; +import org.xbib.net.ParameterException; import org.xbib.net.Resource; import org.xbib.net.http.HttpResponseStatus; import org.xbib.net.http.server.resource.HtmlTemplateResourceHandler; @@ -19,14 +20,16 @@ import static org.xbib.j2html.TagCreator.pre; public class InternalServerErrorHandler extends J2HtmlResourceHandler { @Override - protected Resource createResource(HttpRouterContext httpRouterContext) throws IOException { + protected Resource createResource(HttpRouterContext httpRouterContext) + throws IOException, ParameterException { return new InternalServerErrorResource(this, httpRouterContext); } protected static class InternalServerErrorResource extends J2HtmlResource { protected InternalServerErrorResource(HtmlTemplateResourceHandler templateResourceHandler, - HttpRouterContext httpRouterContext) throws IOException { + HttpRouterContext httpRouterContext) + throws IOException, ParameterException { super(templateResourceHandler, httpRouterContext); } diff --git a/net-http-j2html/src/main/java/org/xbib/net/http/j2html/J2HtmlResource.java b/net-http-j2html/src/main/java/org/xbib/net/http/j2html/J2HtmlResource.java index e47ebe8..595dbab 100644 --- a/net-http-j2html/src/main/java/org/xbib/net/http/j2html/J2HtmlResource.java +++ b/net-http-j2html/src/main/java/org/xbib/net/http/j2html/J2HtmlResource.java @@ -1,6 +1,8 @@ package org.xbib.net.http.j2html; +import org.xbib.net.ParameterException; import org.xbib.net.buffer.DataBuffer; +import org.xbib.net.http.HttpHeaderValues; import org.xbib.net.http.HttpResponseStatus; import org.xbib.net.http.server.HttpRequest; import org.xbib.net.http.server.resource.HtmlTemplateResource; @@ -11,6 +13,8 @@ import java.io.IOException; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.Objects; +import java.util.logging.Level; +import java.util.logging.Logger; import static org.xbib.j2html.TagCreator.body; import static org.xbib.j2html.TagCreator.document; @@ -20,29 +24,40 @@ import static org.xbib.net.http.HttpHeaderNames.CONTENT_TYPE; public class J2HtmlResource extends HtmlTemplateResource { + private static final Logger logger = Logger.getLogger(J2HtmlResource.class.getName()); + protected HttpRequest request; public J2HtmlResource(HtmlTemplateResourceHandler templateResourceHandler, - HttpRouterContext httpRouterContext) throws IOException { + HttpRouterContext httpRouterContext) throws IOException, ParameterException { super(templateResourceHandler, httpRouterContext); } @Override - public void render(HttpRouterContext context) throws IOException { - this.request = context.getRequest(); - Objects.requireNonNull(responseBuilder); - DataBuffer dataBuffer = context.getDataBufferFactory().allocateBuffer(); - dataBuffer.write(renderHtml(context), getCharset()); - HttpResponseStatus httpResponseStatus = responseBuilder.getResponseStatus(); - if (httpResponseStatus == null) { - httpResponseStatus = getResponseStatus(); + public void render(HttpRouterContext context) + throws IOException { + try { + this.request = context.getRequest(); + Objects.requireNonNull(responseBuilder); + DataBuffer dataBuffer = context.getDataBufferFactory().allocateBuffer(); + dataBuffer.write(renderHtml(context), getCharset()); + HttpResponseStatus httpResponseStatus = responseBuilder.getResponseStatus(); + if (httpResponseStatus == null) { + httpResponseStatus = getResponseStatus(); + } + context.status(httpResponseStatus) + .setHeader("cache-control", "no-cache") + .setHeader("content-length", Integer.toString(dataBuffer.writePosition())) + .setHeader(CONTENT_TYPE, "text/html; charset=" + getCharset().displayName()) + .body(dataBuffer) + .done(); + } catch (ParameterException e) { + logger.log(Level.WARNING, e.getMessage(), e); + context.status(HttpResponseStatus.BAD_REQUEST) + .setHeader(CONTENT_TYPE, HttpHeaderValues.TEXT_PLAIN) + .body(e.getMessage()) + .done(); } - context.status(httpResponseStatus) - .setHeader("cache-control", "no-cache") - .setHeader("content-length", Integer.toString(dataBuffer.writePosition())) - .setHeader(CONTENT_TYPE, "text/html; charset=" + getCharset().displayName()) - .body(dataBuffer) - .done(); } protected HttpResponseStatus getResponseStatus() { @@ -54,14 +69,14 @@ public class J2HtmlResource extends HtmlTemplateResource { } /** - * Rendering. * By subclassing this handler, this method should be overridden by custom j2html code. * The HTML is here is just a greeting as an example. * * @param context the router context * @return the body string fo the HTTP response */ - protected String renderHtml(HttpRouterContext context) { + protected String renderHtml(HttpRouterContext context) + throws IOException, ParameterException { return document(html(body(h1("Hello World")))); } } diff --git a/net-http-j2html/src/main/java/org/xbib/net/http/j2html/J2HtmlResourceHandler.java b/net-http-j2html/src/main/java/org/xbib/net/http/j2html/J2HtmlResourceHandler.java index 1ade22c..264eeb0 100644 --- a/net-http-j2html/src/main/java/org/xbib/net/http/j2html/J2HtmlResourceHandler.java +++ b/net-http-j2html/src/main/java/org/xbib/net/http/j2html/J2HtmlResourceHandler.java @@ -1,5 +1,6 @@ package org.xbib.net.http.j2html; +import org.xbib.net.ParameterException; import org.xbib.net.Resource; import org.xbib.net.http.server.resource.HtmlTemplateResourceHandler; import org.xbib.net.http.server.route.HttpRouterContext; @@ -7,9 +8,6 @@ import org.xbib.net.http.server.route.HttpRouterContext; import java.io.IOException; import java.nio.file.Path; -import static org.xbib.j2html.TagCreator.body; -import static org.xbib.j2html.TagCreator.h1; - public class J2HtmlResourceHandler extends HtmlTemplateResourceHandler { public J2HtmlResourceHandler() { @@ -21,13 +19,15 @@ public class J2HtmlResourceHandler extends HtmlTemplateResourceHandler { } @Override - protected Resource createResource(HttpRouterContext httpRouterContext) throws IOException { + protected Resource createResource(HttpRouterContext httpRouterContext) + throws IOException, ParameterException { return httpRouterContext.isAuthenticated() ? new J2HtmlResource(this, httpRouterContext) : createUnauthenticatedResource(httpRouterContext); } - protected Resource createUnauthenticatedResource(HttpRouterContext httpRouterContext) throws IOException { + protected Resource createUnauthenticatedResource(HttpRouterContext httpRouterContext) + throws IOException, ParameterException { return new J2HtmlResource(this, httpRouterContext); } } diff --git a/net-http-j2html/src/main/java/org/xbib/net/http/j2html/NotFoundHandler.java b/net-http-j2html/src/main/java/org/xbib/net/http/j2html/NotFoundHandler.java index 7544a9e..0c43aa5 100644 --- a/net-http-j2html/src/main/java/org/xbib/net/http/j2html/NotFoundHandler.java +++ b/net-http-j2html/src/main/java/org/xbib/net/http/j2html/NotFoundHandler.java @@ -1,5 +1,6 @@ package org.xbib.net.http.j2html; +import org.xbib.net.ParameterException; import org.xbib.net.Resource; import org.xbib.net.http.HttpResponseStatus; import org.xbib.net.http.server.resource.HtmlTemplateResourceHandler; @@ -14,14 +15,16 @@ import static org.xbib.j2html.TagCreator.html; public class NotFoundHandler extends J2HtmlResourceHandler { @Override - protected Resource createResource(HttpRouterContext httpRouterContext) throws IOException { + protected Resource createResource(HttpRouterContext httpRouterContext) + throws IOException, ParameterException { return new UnauthorizedResource(this, httpRouterContext); } protected static class UnauthorizedResource extends J2HtmlResource { protected UnauthorizedResource(HtmlTemplateResourceHandler templateResourceHandler, - HttpRouterContext httpRouterContext) throws IOException { + HttpRouterContext httpRouterContext) + throws IOException, ParameterException { super(templateResourceHandler, httpRouterContext); } diff --git a/net-http-j2html/src/main/java/org/xbib/net/http/j2html/UnauthorizedHandler.java b/net-http-j2html/src/main/java/org/xbib/net/http/j2html/UnauthorizedHandler.java index 7a23426..2b8da9b 100644 --- a/net-http-j2html/src/main/java/org/xbib/net/http/j2html/UnauthorizedHandler.java +++ b/net-http-j2html/src/main/java/org/xbib/net/http/j2html/UnauthorizedHandler.java @@ -1,5 +1,6 @@ package org.xbib.net.http.j2html; +import org.xbib.net.ParameterException; import org.xbib.net.Resource; import org.xbib.net.http.HttpResponseStatus; import org.xbib.net.http.server.resource.HtmlTemplateResourceHandler; @@ -14,14 +15,16 @@ import static org.xbib.j2html.TagCreator.html; public class UnauthorizedHandler extends J2HtmlResourceHandler { @Override - protected Resource createResource(HttpRouterContext httpRouterContext) throws IOException { + protected Resource createResource(HttpRouterContext httpRouterContext) + throws IOException, ParameterException { return new UnauthorizedResource(this, httpRouterContext); } protected static class UnauthorizedResource extends J2HtmlResource { protected UnauthorizedResource(HtmlTemplateResourceHandler templateResourceHandler, - HttpRouterContext httpRouterContext) throws IOException { + HttpRouterContext httpRouterContext) + throws IOException, ParameterException { super(templateResourceHandler, httpRouterContext); } diff --git a/net-http-server-application-web/src/main/java/org/xbib/net/http/server/application/web/j2html/Bootstrap.java b/net-http-server-application-web/src/main/java/org/xbib/net/http/server/application/web/j2html/Bootstrap.java index 34ff7fa..a2e7dc9 100644 --- a/net-http-server-application-web/src/main/java/org/xbib/net/http/server/application/web/j2html/Bootstrap.java +++ b/net-http-server-application-web/src/main/java/org/xbib/net/http/server/application/web/j2html/Bootstrap.java @@ -5,15 +5,19 @@ import org.xbib.config.ConfigLogger; import org.xbib.config.ConfigParams; import org.xbib.config.SystemConfigLogger; import org.xbib.net.NetworkClass; +import org.xbib.net.ParameterException; import org.xbib.net.Resource; import org.xbib.net.http.HttpHeaderNames; import org.xbib.net.http.HttpHeaderValues; import org.xbib.net.http.HttpResponseStatus; import org.xbib.net.http.HttpVersion; +import org.xbib.net.http.j2html.BadRequestHandler; import org.xbib.net.http.j2html.InternalServerErrorHandler; import org.xbib.net.http.j2html.J2HtmlResource; import org.xbib.net.http.j2html.J2HtmlResourceHandler; import org.xbib.net.http.j2html.J2HtmlService; +import org.xbib.net.http.j2html.NotFoundHandler; +import org.xbib.net.http.j2html.UnauthorizedHandler; import org.xbib.net.http.server.application.web.WebApplication; import org.xbib.net.http.server.auth.BasicAuthenticationHandler; import org.xbib.net.http.server.auth.FormAuthenticationHandler; @@ -141,6 +145,9 @@ public final class Bootstrap { .build(); HttpRouter httpRouter = BaseHttpRouter.builder() + .setHandler(401, new UnauthorizedHandler()) + .setHandler(403, new BadRequestHandler()) + .setHandler(404, new NotFoundHandler()) .setHandler(500, new InternalServerErrorHandler()) .addDomain(BaseHttpDomain.builder() .setHttpAddress(httpsAddress) @@ -206,12 +213,14 @@ public final class Bootstrap { static class MyResourceHandler extends J2HtmlResourceHandler { @Override - protected Resource createResource(HttpRouterContext httpRouterContext) throws IOException { + protected Resource createResource(HttpRouterContext httpRouterContext) + throws IOException, ParameterException { return new DemoResource(this, httpRouterContext); } @Override - protected Resource createUnauthenticatedResource(HttpRouterContext httpRouterContext) throws IOException { + protected Resource createUnauthenticatedResource(HttpRouterContext httpRouterContext) + throws IOException, ParameterException { return new UnauthenticatedDemoResource(this, httpRouterContext); } } @@ -219,7 +228,8 @@ public final class Bootstrap { static class DemoResource extends J2HtmlResource { public DemoResource(HtmlTemplateResourceHandler templateResourceHandler, - HttpRouterContext httpRouterContext) throws IOException { + HttpRouterContext httpRouterContext) + throws IOException, ParameterException { super(templateResourceHandler, httpRouterContext); } @@ -233,7 +243,8 @@ public final class Bootstrap { static class UnauthenticatedDemoResource extends J2HtmlResource { public UnauthenticatedDemoResource(HtmlTemplateResourceHandler templateResourceHandler, - HttpRouterContext httpRouterContext) throws IOException { + HttpRouterContext httpRouterContext) + throws IOException, ParameterException { super(templateResourceHandler, httpRouterContext); } diff --git a/net-http-server/src/main/java/org/xbib/net/http/server/resource/AbstractResourceHandler.java b/net-http-server/src/main/java/org/xbib/net/http/server/resource/AbstractResourceHandler.java index 007048f..efd52ac 100644 --- a/net-http-server/src/main/java/org/xbib/net/http/server/resource/AbstractResourceHandler.java +++ b/net-http-server/src/main/java/org/xbib/net/http/server/resource/AbstractResourceHandler.java @@ -18,12 +18,15 @@ import java.util.Arrays; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; + +import org.xbib.net.ParameterException; import org.xbib.net.Resource; import org.xbib.net.URL; import org.xbib.net.buffer.DataBuffer; import org.xbib.net.buffer.DataBufferFactory; import org.xbib.net.buffer.DataBufferUtil; import org.xbib.net.http.HttpHeaderNames; +import org.xbib.net.http.HttpHeaderValues; import org.xbib.net.http.HttpHeaders; import org.xbib.net.http.HttpMethod; import org.xbib.net.http.HttpResponseStatus; @@ -44,7 +47,8 @@ public abstract class AbstractResourceHandler implements HttpHandler { public AbstractResourceHandler() { } - protected abstract Resource createResource(HttpRouterContext httpRouterContext) throws IOException; + protected abstract Resource createResource(HttpRouterContext httpRouterContext) + throws IOException, ParameterException; protected abstract boolean isETagEnabled(); @@ -56,39 +60,47 @@ public abstract class AbstractResourceHandler implements HttpHandler { @Override public void handle(HttpRouterContext context) throws IOException { - logger.log(Level.FINEST, () -> "handle: before creating resource " + this.getClass().getName()); - Resource resource = createResource(context); - logger.log(Level.FINEST, () -> "handle: resource = " + (resource != null ? resource.getClass().getName() + " " + resource : null)); - if (resource instanceof HtmlTemplateResource) { - generateCacheableResource(context, resource); - return; - } - if (resource == null) { - throw new HttpException("resource not found", context, HttpResponseStatus.NOT_FOUND); - } else if (resource.isDirectory()) { - logger.log(Level.FINEST, "we have a directory request"); - if (!resource.getResourcePath().isEmpty() && !resource.getResourcePath().endsWith("/")) { - URL url = context.getRequestBuilder().getUrl().resolve(resource.getName() + '/'); - String loc = URL.builder(url) - .query(url.getQuery()) - .fragment(url.getFragment()) - .build() - .toString(); - logger.log(Level.FINEST, "client must add a /, external redirect to = " + loc); - context.setHeader(HttpHeaderNames.LOCATION, loc) - .status(HttpResponseStatus.TEMPORARY_REDIRECT); - } else if (resource.isExistsIndexFile()) { - // internal redirect to default index file in this directory - logger.log(Level.FINEST, "internal redirect to default index file in this directory: " + resource.getIndexFileName()); + try { + logger.log(Level.FINEST, () -> "handle: before creating resource " + this.getClass().getName()); + Resource resource = createResource(context); + logger.log(Level.FINEST, () -> "handle: resource = " + (resource != null ? resource.getClass().getName() + " " + resource : null)); + if (resource instanceof HtmlTemplateResource) { generateCacheableResource(context, resource); - } else { - // send forbidden, we do not allow directory access - context.status(HttpResponseStatus.FORBIDDEN); + return; } - context.done(); - } else { - generateCacheableResource(context, resource); - context.done(); + if (resource == null) { + throw new HttpException("resource not found", context, HttpResponseStatus.NOT_FOUND); + } else if (resource.isDirectory()) { + logger.log(Level.FINEST, "we have a directory request"); + if (!resource.getResourcePath().isEmpty() && !resource.getResourcePath().endsWith("/")) { + URL url = context.getRequestBuilder().getUrl().resolve(resource.getName() + '/'); + String loc = URL.builder(url) + .query(url.getQuery()) + .fragment(url.getFragment()) + .build() + .toString(); + logger.log(Level.FINEST, "client must add a /, external redirect to = " + loc); + context.setHeader(HttpHeaderNames.LOCATION, loc) + .status(HttpResponseStatus.TEMPORARY_REDIRECT); + } else if (resource.isExistsIndexFile()) { + // internal redirect to default index file in this directory + logger.log(Level.FINEST, "internal redirect to default index file in this directory: " + resource.getIndexFileName()); + generateCacheableResource(context, resource); + } else { + // send forbidden, we do not allow directory access + context.status(HttpResponseStatus.FORBIDDEN); + } + context.done(); + } else { + generateCacheableResource(context, resource); + context.done(); + } + } catch (ParameterException e) { + logger.log(Level.WARNING, e.getMessage(), e); + context.status(HttpResponseStatus.BAD_REQUEST) + .setHeader(CONTENT_TYPE, HttpHeaderValues.TEXT_PLAIN) + .body(e.getMessage()) + .done(); } } diff --git a/net-http-server/src/main/java/org/xbib/net/http/server/resource/HtmlTemplateResourceHandler.java b/net-http-server/src/main/java/org/xbib/net/http/server/resource/HtmlTemplateResourceHandler.java index 9a0d146..0c10516 100644 --- a/net-http-server/src/main/java/org/xbib/net/http/server/resource/HtmlTemplateResourceHandler.java +++ b/net-http-server/src/main/java/org/xbib/net/http/server/resource/HtmlTemplateResourceHandler.java @@ -2,6 +2,8 @@ package org.xbib.net.http.server.resource; import java.io.IOException; import java.nio.file.Path; + +import org.xbib.net.ParameterException; import org.xbib.net.Resource; import org.xbib.net.http.server.route.HttpRouterContext; @@ -22,7 +24,8 @@ public class HtmlTemplateResourceHandler extends AbstractResourceHandler { } @Override - protected Resource createResource(HttpRouterContext httpRouterContext) throws IOException { + protected Resource createResource(HttpRouterContext httpRouterContext) + throws IOException, ParameterException { return new HtmlTemplateResource(this, httpRouterContext); }