working on http router creation from settings

This commit is contained in:
Jörg Prante 2025-03-11 15:43:43 +01:00
parent 91fd31a85c
commit d4a8beaf65
64 changed files with 401 additions and 132 deletions

View file

@ -1,3 +1,3 @@
group = org.xbib group = org.xbib
name = net-http name = net-http
version = 4.9.0 version = 5.0.0

View file

@ -21,7 +21,7 @@ tasks.withType(JavaCompile) {
options.fork = true options.fork = true
options.forkOptions.jvmArgs += ['-Duser.language=en','-Duser.country=US'] options.forkOptions.jvmArgs += ['-Duser.language=en','-Duser.country=US']
options.encoding = 'UTF-8' options.encoding = 'UTF-8'
options.compilerArgs.add('-Xlint:all') options.compilerArgs.add('-Xlint:all,-exports')
options.compilerArgs.add("--module-path") options.compilerArgs.add("--module-path")
options.compilerArgs.add(classpath.asPath) options.compilerArgs.add(classpath.asPath)
classpath = files() classpath = files()

View file

@ -17,6 +17,9 @@ public class EventStreamTest {
private static final Logger logger = Logger.getLogger(EventStreamTest.class.getName()); private static final Logger logger = Logger.getLogger(EventStreamTest.class.getName());
public EventStreamTest() {
}
@Test @Test
void testSimpleJournalGateway() throws URISyntaxException, IOException, InterruptedException { void testSimpleJournalGateway() throws URISyntaxException, IOException, InterruptedException {
var uri = new URI("http://localhost:19531/entries?follow"); var uri = new URI("http://localhost:19531/entries?follow");

View file

@ -229,12 +229,16 @@ public class Https1ChannelInitializer implements HttpChannelInitializer {
throw new IllegalStateException(); throw new IllegalStateException();
} }
}; };
// TODO replace deprecation
Http2MultiplexCodecBuilder multiplexCodecBuilder = Http2MultiplexCodecBuilder.forClient(initializer) Http2MultiplexCodecBuilder multiplexCodecBuilder = Http2MultiplexCodecBuilder.forClient(initializer)
.initialSettings(nettyHttpClientConfig.getHttp2Settings()); .initialSettings(nettyHttpClientConfig.getHttp2Settings());
if (nettyHttpClientConfig.isDebug()) { if (nettyHttpClientConfig.isDebug()) {
multiplexCodecBuilder.frameLogger(new Http2FrameLogger(LogLevel.DEBUG, "client-frame")); multiplexCodecBuilder.frameLogger(new Http2FrameLogger(LogLevel.DEBUG, "client-frame"));
} }
Http2MultiplexCodec multiplexCodec = multiplexCodecBuilder.autoAckSettingsFrame(true).build(); // TODO replace deprecation
Http2MultiplexCodec multiplexCodec = multiplexCodecBuilder
.autoAckSettingsFrame(true)
.build();
pipeline.addLast("client-multiplex", multiplexCodec); pipeline.addLast("client-multiplex", multiplexCodec);
pipeline.addLast("client-messages", new Http2Messages(interaction)); pipeline.addLast("client-messages", new Http2Messages(interaction));
// simulate we are ready for HTTP/2 // simulate we are ready for HTTP/2

View file

@ -170,11 +170,13 @@ public class Https2ChannelInitializer implements HttpChannelInitializer {
throw new IllegalStateException(); throw new IllegalStateException();
} }
}; };
// TODO replace deprecation
Http2MultiplexCodecBuilder multiplexCodecBuilder = Http2MultiplexCodecBuilder.forClient(initializer) Http2MultiplexCodecBuilder multiplexCodecBuilder = Http2MultiplexCodecBuilder.forClient(initializer)
.initialSettings(nettyHttpClientConfig.getHttp2Settings()); .initialSettings(nettyHttpClientConfig.getHttp2Settings());
if (nettyHttpClientConfig.isDebug()) { if (nettyHttpClientConfig.isDebug()) {
multiplexCodecBuilder.frameLogger(new Http2FrameLogger(LogLevel.DEBUG, "client-frame")); multiplexCodecBuilder.frameLogger(new Http2FrameLogger(LogLevel.DEBUG, "client-frame"));
} }
// TODO replace deprecation
Http2MultiplexCodec multiplexCodec = multiplexCodecBuilder Http2MultiplexCodec multiplexCodec = multiplexCodecBuilder
.autoAckSettingsFrame(true) .autoAckSettingsFrame(true)
.autoAckPingFrame(true) .autoAckPingFrame(true)

View file

@ -15,6 +15,9 @@ public class AkamaiTest {
private static final Logger logger = Logger.getLogger(AkamaiTest.class.getName()); private static final Logger logger = Logger.getLogger(AkamaiTest.class.getName());
public AkamaiTest() {
}
/** /**
* Problems with akamai: * Problems with akamai:
* failing: Cannot invoke "io.netty.handler.codec.http2.AbstractHttp2StreamChannel.fireChildRead(io.netty.handler.codec.http2.Http2Frame)" because "channel" is null * demo/h2_demo_frame.html sends no content, only a push promise, and does not continue * failing: Cannot invoke "io.netty.handler.codec.http2.AbstractHttp2StreamChannel.fireChildRead(io.netty.handler.codec.http2.Http2Frame)" because "channel" is null * demo/h2_demo_frame.html sends no content, only a push promise, and does not continue

View file

@ -17,12 +17,17 @@ class ThreadLeakTest {
private static final Logger logger = Logger.getLogger(ThreadLeakTest.class.getName()); private static final Logger logger = Logger.getLogger(ThreadLeakTest.class.getName());
public ThreadLeakTest() {
}
@Test @Test
void testForLeaks() throws IOException { void testForLeaks() throws IOException {
NettyHttpClientConfig config = new NettyHttpsClientConfig(); NettyHttpClientConfig config = new NettyHttpsClientConfig();
try (NettyHttpClient client = NettyHttpClient.builder() try (NettyHttpClient client = NettyHttpClient.builder()
.setConfig(config) .setConfig(config)
.build()) { .build()) {
// do something with the client
client.getClientConfig();
} }
} }

View file

@ -66,11 +66,13 @@ public class Http2ChannelInitializer implements HttpChannelInitializer {
throw new IllegalStateException(); throw new IllegalStateException();
} }
}; };
// TODO replace deprecation
Http2MultiplexCodecBuilder multiplexCodecBuilder = Http2MultiplexCodecBuilder.forClient(initializer) Http2MultiplexCodecBuilder multiplexCodecBuilder = Http2MultiplexCodecBuilder.forClient(initializer)
.initialSettings(nettyHttpClientConfig.getHttp2Settings()); .initialSettings(nettyHttpClientConfig.getHttp2Settings());
if (nettyHttpClientConfig.isDebug()) { if (nettyHttpClientConfig.isDebug()) {
multiplexCodecBuilder.frameLogger(new Http2FrameLogger(LogLevel.DEBUG, "client-frame")); multiplexCodecBuilder.frameLogger(new Http2FrameLogger(LogLevel.DEBUG, "client-frame"));
} }
// TODO replace deprecation
Http2MultiplexCodec multiplexCodec = multiplexCodecBuilder Http2MultiplexCodec multiplexCodec = multiplexCodecBuilder
.autoAckPingFrame(true) .autoAckPingFrame(true)
.autoAckSettingsFrame(true) .autoAckSettingsFrame(true)

View file

@ -278,7 +278,7 @@ public class ExponentialBackOff implements BackOff {
if (currentIntervalMillis >= maxIntervalMillis / multiplier) { if (currentIntervalMillis >= maxIntervalMillis / multiplier) {
currentIntervalMillis = maxIntervalMillis; currentIntervalMillis = maxIntervalMillis;
} else { } else {
currentIntervalMillis *= multiplier; currentIntervalMillis = (int)(currentIntervalMillis * multiplier);
} }
} }

View file

@ -14,6 +14,9 @@ import static org.xbib.j2html.TagCreator.html;
public class BadRequestHandler extends J2HtmlResourceHandler { public class BadRequestHandler extends J2HtmlResourceHandler {
public BadRequestHandler() {
}
@Override @Override
protected Resource createResource(HttpRouterContext httpRouterContext) protected Resource createResource(HttpRouterContext httpRouterContext)
throws IOException, ParameterException { throws IOException, ParameterException {

View file

@ -19,6 +19,9 @@ import static org.xbib.j2html.TagCreator.pre;
public class InternalServerErrorHandler extends J2HtmlResourceHandler { public class InternalServerErrorHandler extends J2HtmlResourceHandler {
public InternalServerErrorHandler() {
}
@Override @Override
protected Resource createResource(HttpRouterContext httpRouterContext) protected Resource createResource(HttpRouterContext httpRouterContext)
throws IOException, ParameterException { throws IOException, ParameterException {

View file

@ -14,6 +14,9 @@ import static org.xbib.j2html.TagCreator.html;
public class NotFoundHandler extends J2HtmlResourceHandler { public class NotFoundHandler extends J2HtmlResourceHandler {
public NotFoundHandler() {
}
@Override @Override
protected Resource createResource(HttpRouterContext httpRouterContext) protected Resource createResource(HttpRouterContext httpRouterContext)
throws IOException, ParameterException { throws IOException, ParameterException {

View file

@ -14,6 +14,9 @@ import static org.xbib.j2html.TagCreator.html;
public class UnauthorizedHandler extends J2HtmlResourceHandler { public class UnauthorizedHandler extends J2HtmlResourceHandler {
public UnauthorizedHandler() {
}
@Override @Override
protected Resource createResource(HttpRouterContext httpRouterContext) protected Resource createResource(HttpRouterContext httpRouterContext)
throws IOException, ParameterException { throws IOException, ParameterException {

View file

@ -13,6 +13,9 @@ public class Http1Test {
private static final Logger logger = Logger.getLogger(Http1Test.class.getName()); private static final Logger logger = Logger.getLogger(Http1Test.class.getName());
public Http1Test() {
}
@Test @Test
void testGoogleConscrypt() throws Exception { void testGoogleConscrypt() throws Exception {

View file

@ -27,7 +27,7 @@ public class WebApplication extends BaseApplication {
@Override @Override
protected Codec<Session> newSessionCodec(HttpRouterContext httpRouterContext) { protected Codec<Session> newSessionCodec(HttpRouterContext httpRouterContext) {
return new FileJsonSessionCodec(sessionName, this, 1024, Duration.ofDays(1), return new FileJsonSessionCodec(getSessionName(), this, 1024, Duration.ofDays(1),
Paths.get("/var/tmp/session")); Paths.get("/var/tmp/session"));
} }

View file

@ -8,10 +8,10 @@ import org.xbib.settings.Settings;
public class WebApplicationBuilder extends BaseApplicationBuilder { public class WebApplicationBuilder extends BaseApplicationBuilder {
protected String profile;
protected String name; protected String name;
protected String profile;
protected WebApplicationBuilder() { protected WebApplicationBuilder() {
super(); super();
this.name = System.getProperty("application.name"); this.name = System.getProperty("application.name");
@ -28,11 +28,11 @@ public class WebApplicationBuilder extends BaseApplicationBuilder {
return this; return this;
} }
@Override /*@Override
public WebApplicationBuilder setSettings(Settings settings) { public WebApplicationBuilder setSettings(Settings settings) {
this.settings = settings; this.settings = settings;
return this; return this;
} }*/
@Override @Override
public WebApplicationBuilder setSecret(String secret) { public WebApplicationBuilder setSecret(String secret) {

View file

@ -174,7 +174,7 @@ public final class Bootstrap {
.build(); .build();
WebApplication application = WebApplication.builder() WebApplication application = WebApplication.builder()
.setSettings(settings) //.setSettings(settings)
.setSecret("1088e6b7ad58d64d09961e1357bf95544447051c6ad1332cd626e3a33bb5786b") .setSecret("1088e6b7ad58d64d09961e1357bf95544447051c6ad1332cd626e3a33bb5786b")
.setExecutor(executor) .setExecutor(executor)
.setRouter(httpRouter) .setRouter(httpRouter)

View file

@ -46,8 +46,6 @@ import java.nio.charset.StandardCharsets;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.Optional;
import java.util.ServiceLoader;
import static org.xbib.j2html.TagCreator.body; import static org.xbib.j2html.TagCreator.body;
import static org.xbib.j2html.TagCreator.h1; import static org.xbib.j2html.TagCreator.h1;
@ -57,7 +55,7 @@ public final class Bootstrap {
private Bootstrap() { private Bootstrap() {
} }
public static void main(String[] args) throws Exception { public static void main(String[] args) {
String profile = args.length > 0 ? args[0] : System.getProperty("application.profile"); String profile = args.length > 0 ? args[0] : System.getProperty("application.profile");
ConfigParams configParams; ConfigParams configParams;
ConfigLoader configLoader; ConfigLoader configLoader;
@ -181,7 +179,7 @@ public final class Bootstrap {
.build(); .build();
WebApplication application = WebApplication.builder() WebApplication application = WebApplication.builder()
.setSettings(settings) //.setSettings(settings)
.setSecret("1088e6b7ad58d64d09961e1357bf95544447051c6ad1332cd626e3a33bb5786b") .setSecret("1088e6b7ad58d64d09961e1357bf95544447051c6ad1332cd626e3a33bb5786b")
.setExecutor(executor) .setExecutor(executor)
.setRouter(httpRouter) .setRouter(httpRouter)

View file

@ -55,7 +55,7 @@ public class Https2Handler extends ChannelDuplexHandler {
.setRemoteAddress((InetSocketAddress) ctx.channel().remoteAddress()) .setRemoteAddress((InetSocketAddress) ctx.channel().remoteAddress())
.setStreamId(streamId); .setStreamId(streamId);
if ("PRI".equals(fullHttpRequest.method().name())) { if ("PRI".equals(fullHttpRequest.method().name())) {
nettyHttpServer.dispatch(httpsRequestBuilder, httpsResponseBuilder, HttpResponseStatus.HTTP_VERSION_NOT_SUPPORTED); nettyHttpServer.dispatchError(httpsRequestBuilder, httpsResponseBuilder, HttpResponseStatus.HTTP_VERSION_NOT_SUPPORTED);
return; return;
} }
httpsResponseBuilder.shouldClose("close".equalsIgnoreCase(fullHttpRequest.headers().get(HttpHeaderNames.CONNECTION))); httpsResponseBuilder.shouldClose("close".equalsIgnoreCase(fullHttpRequest.headers().get(HttpHeaderNames.CONNECTION)));

View file

@ -34,6 +34,9 @@ public class NettyHttps2ServerMultiRequestLoadTest {
private static final Logger logger = Logger.getLogger(NettyHttps2ServerMultiRequestLoadTest.class.getName()); private static final Logger logger = Logger.getLogger(NettyHttps2ServerMultiRequestLoadTest.class.getName());
public NettyHttps2ServerMultiRequestLoadTest() {
}
@Test @Test
public void testHttps2Load() throws Exception { public void testHttps2Load() throws Exception {
// client HTTP 2.0, server HTTP 2.0 // client HTTP 2.0, server HTTP 2.0

View file

@ -34,6 +34,9 @@ public class NettyHttps2ServerTest {
private static final Logger logger = Logger.getLogger(NettyHttps2ServerTest.class.getName()); private static final Logger logger = Logger.getLogger(NettyHttps2ServerTest.class.getName());
public NettyHttps2ServerTest() {
}
@Test @Test
public void testHttps2() throws Exception { public void testHttps2() throws Exception {
// client HTTP 2.0 + server HTTP 2.0 (no upgrade) // client HTTP 2.0 + server HTTP 2.0 (no upgrade)

View file

@ -36,6 +36,9 @@ public class NettyHttpsServerMultiRequestLoadTest {
private static final Logger logger = Logger.getLogger(NettyHttpsServerMultiRequestLoadTest.class.getName()); private static final Logger logger = Logger.getLogger(NettyHttpsServerMultiRequestLoadTest.class.getName());
public NettyHttpsServerMultiRequestLoadTest() {
}
@Test @Test
public void testHttps1Load() throws Exception { public void testHttps1Load() throws Exception {
// client HTTP 1.1, server HTTP 1.1 (no upgrade) // client HTTP 1.1, server HTTP 1.1 (no upgrade)

View file

@ -39,6 +39,9 @@ public class NettyHttpsServerTest {
private static final Logger logger = Logger.getLogger(NettyHttpsServerTest.class.getName()); private static final Logger logger = Logger.getLogger(NettyHttpsServerTest.class.getName());
public NettyHttpsServerTest() {
}
@Test @Test
public void testHttps1() throws Exception { public void testHttps1() throws Exception {
// client HTTP 1.1 + server HTTP 1.1 (no upgrade) // client HTTP 1.1 + server HTTP 1.1 (no upgrade)

View file

@ -189,7 +189,7 @@ public class NettyHttpServer implements HttpServer {
} }
@Override @Override
public void dispatch(HttpRequestBuilder requestBuilder, public void dispatchError(HttpRequestBuilder requestBuilder,
HttpResponseBuilder responseBuilder, HttpResponseBuilder responseBuilder,
HttpResponseStatus responseStatus) { HttpResponseStatus responseStatus) {
Callable<?> callable = (Callable<Object>) () -> { Callable<?> callable = (Callable<Object>) () -> {

View file

@ -17,6 +17,9 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
public class HttpRequestTest { public class HttpRequestTest {
public HttpRequestTest() {
}
@Test @Test
public void testFormAsMultiMap() { public void testFormAsMultiMap() {
Parameter parameter = Parameter.builder().domain(Parameter.Domain.FORM) Parameter parameter = Parameter.builder().domain(Parameter.Domain.FORM)

View file

@ -32,6 +32,9 @@ public class NettyHttp2ServerMultiRequestLoadTest {
private static final Logger logger = Logger.getLogger(NettyHttp2ServerMultiRequestLoadTest.class.getName()); private static final Logger logger = Logger.getLogger(NettyHttp2ServerMultiRequestLoadTest.class.getName());
public NettyHttp2ServerMultiRequestLoadTest() {
}
@Test @Test
public void testHttp2Multi() throws Exception { public void testHttp2Multi() throws Exception {

View file

@ -31,6 +31,9 @@ public class NettyHttp2ServerTest {
private static final Logger logger = Logger.getLogger(NettyHttp2ServerTest.class.getName()); private static final Logger logger = Logger.getLogger(NettyHttp2ServerTest.class.getName());
public NettyHttp2ServerTest() {
}
@Test @Test
public void testHttp2() throws Exception { public void testHttp2() throws Exception {
// note that h2c in cleartext is very uncommon, browser do not support this. // note that h2c in cleartext is very uncommon, browser do not support this.

View file

@ -30,6 +30,9 @@ public class NettyHttpServerBodyTest {
private static final Logger logger = Logger.getLogger(NettyHttpServerBodyTest.class.getName()); private static final Logger logger = Logger.getLogger(NettyHttpServerBodyTest.class.getName());
public NettyHttpServerBodyTest() {
}
@Test @Test
public void testHttp() throws Exception { public void testHttp() throws Exception {
URL url = URL.from("http://localhost:8008/domain/"); URL url = URL.from("http://localhost:8008/domain/");

View file

@ -36,6 +36,9 @@ public class NettyHttpServerFailureTest {
private static final Logger logger = Logger.getLogger(NettyHttpServerTest.class.getName()); private static final Logger logger = Logger.getLogger(NettyHttpServerTest.class.getName());
public NettyHttpServerFailureTest() {
}
@Test @Test
public void testBadRequest() throws Exception { public void testBadRequest() throws Exception {
URL url = URL.from("http://localhost:8008/domain/"); URL url = URL.from("http://localhost:8008/domain/");

View file

@ -39,6 +39,9 @@ public class NettyHttpServerFileUploadTest {
private static final Logger logger = Logger.getLogger(NettyHttpServerFileUploadTest.class.getName()); private static final Logger logger = Logger.getLogger(NettyHttpServerFileUploadTest.class.getName());
public NettyHttpServerFileUploadTest() {
}
@Test @Test
public void testSimpleFileUpload() throws Exception { public void testSimpleFileUpload() throws Exception {
URL url = URL.from("http://localhost:8008/"); URL url = URL.from("http://localhost:8008/");

View file

@ -32,6 +32,9 @@ public class NettyHttpServerMultiRequestLoadTest {
private static final Logger logger = Logger.getLogger(NettyHttpServerMultiRequestLoadTest.class.getName()); private static final Logger logger = Logger.getLogger(NettyHttpServerMultiRequestLoadTest.class.getName());
public NettyHttpServerMultiRequestLoadTest() {
}
@Test @Test
public void testHttp1Multi() throws Exception { public void testHttp1Multi() throws Exception {

View file

@ -35,6 +35,9 @@ public class NettyHttpServerRequestTest {
private static final Logger logger = Logger.getLogger(NettyHttpServerRequestTest.class.getName()); private static final Logger logger = Logger.getLogger(NettyHttpServerRequestTest.class.getName());
public NettyHttpServerRequestTest() {
}
@Test @Test
public void testHttpRequest() throws Exception { public void testHttpRequest() throws Exception {
URL url = URL.from("http://localhost:8008/test/"); URL url = URL.from("http://localhost:8008/test/");

View file

@ -35,6 +35,9 @@ public class NettyHttpServerTest {
private static final Logger logger = Logger.getLogger(NettyHttpServerTest.class.getName()); private static final Logger logger = Logger.getLogger(NettyHttpServerTest.class.getName());
public NettyHttpServerTest() {
}
@Test @Test
public void testHttp() throws Exception { public void testHttp() throws Exception {
URL url = URL.from("http://localhost:8008/domain/"); URL url = URL.from("http://localhost:8008/domain/");

View file

@ -144,7 +144,7 @@ public class NioHttpServer implements HttpServer {
} }
@Override @Override
public void dispatch(org.xbib.net.http.server.HttpRequestBuilder requestBuilder, public void dispatchError(org.xbib.net.http.server.HttpRequestBuilder requestBuilder,
org.xbib.net.http.server.HttpResponseBuilder responseBuilder, org.xbib.net.http.server.HttpResponseBuilder responseBuilder,
HttpResponseStatus responseStatus) { HttpResponseStatus responseStatus) {
HttpRouterContext httpRouterContext = builder.application.createContext(null, requestBuilder, responseBuilder); HttpRouterContext httpRouterContext = builder.application.createContext(null, requestBuilder, responseBuilder);

View file

@ -8,6 +8,10 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertThrows;
public class ByteArrayTest { public class ByteArrayTest {
public ByteArrayTest() {
}
@Test @Test
public void should_return_inserted_data_when_insert_some_bytes_and_call_getCopyArray_given_a_ByteArray() { public void should_return_inserted_data_when_insert_some_bytes_and_call_getCopyArray_given_a_ByteArray() {
ByteArray byteArray = new ByteArray(); ByteArray byteArray = new ByteArray();

View file

@ -17,6 +17,9 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
public class HttpRequestParserTest { public class HttpRequestParserTest {
public HttpRequestParserTest() {
}
@Test @Test
public void should_parse_get_request_success() { public void should_parse_get_request_success() {
HttpRequestParser parser = new HttpRequestParser(); HttpRequestParser parser = new HttpRequestParser();

View file

@ -22,6 +22,9 @@ import java.nio.charset.StandardCharsets;
public class NioHttpServerTest { public class NioHttpServerTest {
public NioHttpServerTest() {
}
@Disabled @Disabled
@Test @Test
public void nioServerTest() throws Exception { public void nioServerTest() throws Exception {

View file

@ -146,7 +146,7 @@ public class SimpleHttpServer implements HttpServer {
} }
@Override @Override
public void dispatch(org.xbib.net.http.server.HttpRequestBuilder requestBuilder, public void dispatchError(org.xbib.net.http.server.HttpRequestBuilder requestBuilder,
org.xbib.net.http.server.HttpResponseBuilder responseBuilder, org.xbib.net.http.server.HttpResponseBuilder responseBuilder,
HttpResponseStatus responseStatus) { HttpResponseStatus responseStatus) {
HttpRouterContext httpRouterContext = builder.application.createContext(null, requestBuilder, responseBuilder); HttpRouterContext httpRouterContext = builder.application.createContext(null, requestBuilder, responseBuilder);

View file

@ -27,6 +27,9 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
public class HttpRouterTest { public class HttpRouterTest {
public HttpRouterTest() {
}
@Test @Test
public void routerTest() throws Exception { public void routerTest() throws Exception {
URL url = URL.http().host("localhost").port(8008).build(); URL url = URL.http().host("localhost").port(8008).build();

View file

@ -22,6 +22,9 @@ import java.nio.charset.StandardCharsets;
public class SimpleHttpServerTest { public class SimpleHttpServerTest {
public SimpleHttpServerTest() {
}
@Disabled @Disabled
@Test @Test
public void simpleServerTest() throws Exception { public void simpleServerTest() throws Exception {

View file

@ -92,6 +92,7 @@ public abstract class BaseHttpResponseBuilder implements HttpResponseBuilder {
*/ */
protected Attributes attributes; protected Attributes attributes;
@SuppressWarnings("this-escape")
protected BaseHttpResponseBuilder() { protected BaseHttpResponseBuilder() {
reset(); reset();
} }

View file

@ -13,13 +13,12 @@ public interface HttpServer extends Closeable {
void loop() throws IOException; void loop() throws IOException;
Collection<HttpDomain> getDomains();
void dispatch(HttpRequestBuilder requestBuilder, void dispatch(HttpRequestBuilder requestBuilder,
HttpResponseBuilder responseBuilder); HttpResponseBuilder responseBuilder);
void dispatch(HttpRequestBuilder requestBuilder, void dispatchError(HttpRequestBuilder requestBuilder,
HttpResponseBuilder responseBuilder, HttpResponseBuilder responseBuilder,
HttpResponseStatus responseStatus); HttpResponseStatus responseStatus);
Collection<HttpDomain> getDomains();
} }

View file

@ -18,7 +18,6 @@ import org.xbib.net.http.server.executor.Executor;
import org.xbib.net.http.server.route.HttpRouter; import org.xbib.net.http.server.route.HttpRouter;
import org.xbib.net.http.server.session.SessionListener; import org.xbib.net.http.server.session.SessionListener;
import org.xbib.net.mime.MimeTypeService; import org.xbib.net.mime.MimeTypeService;
import org.xbib.settings.Settings;
public interface Application extends SessionListener, Resolver<Path>, Closeable { public interface Application extends SessionListener, Resolver<Path>, Closeable {
@ -28,10 +27,14 @@ public interface Application extends SessionListener, Resolver<Path>, Closeable
Path getHome(); Path getHome();
String getPrefix();
Collection<HttpDomain> getDomains(); Collection<HttpDomain> getDomains();
Set<HttpAddress> getAddresses(); Set<HttpAddress> getAddresses();
boolean shouldNegotiateLocale();
Locale getLocale(); Locale getLocale();
ZoneId getZoneId(); ZoneId getZoneId();
@ -40,8 +43,6 @@ public interface Application extends SessionListener, Resolver<Path>, Closeable
String getContextPath(); String getContextPath();
Settings getSettings();
void addModule(ApplicationModule applicationModule); void addModule(ApplicationModule applicationModule);
Collection<ApplicationModule> getModules(); Collection<ApplicationModule> getModules();

View file

@ -13,6 +13,8 @@ public interface ApplicationBuilder {
ApplicationBuilder setHome(Path home); ApplicationBuilder setHome(Path home);
ApplicationBuilder setPrefix(String prefix);
ApplicationBuilder setContextPath(String contextPath); ApplicationBuilder setContextPath(String contextPath);
ApplicationBuilder setSecret(String hexSecret); ApplicationBuilder setSecret(String hexSecret);
@ -21,6 +23,8 @@ public interface ApplicationBuilder {
ApplicationBuilder setSessionsEnabled(boolean sessionsEnabled); ApplicationBuilder setSessionsEnabled(boolean sessionsEnabled);
ApplicationBuilder shouldNegotiateLocale(boolean shouldNegotiate);
ApplicationBuilder setLocale(Locale locale); ApplicationBuilder setLocale(Locale locale);
ApplicationBuilder setZoneId(ZoneId zoneId); ApplicationBuilder setZoneId(ZoneId zoneId);

View file

@ -9,7 +9,6 @@ import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
@ -41,7 +40,6 @@ import org.xbib.net.http.server.auth.MemoryPropertiesUserProfileCodec;
import org.xbib.net.http.server.validate.HttpRequestValidator; import org.xbib.net.http.server.validate.HttpRequestValidator;
import org.xbib.net.mime.MimeTypeService; import org.xbib.net.mime.MimeTypeService;
import org.xbib.net.util.RandomUtil; import org.xbib.net.util.RandomUtil;
import org.xbib.settings.Settings;
public class BaseApplication implements Application { public class BaseApplication implements Application {
@ -49,8 +47,6 @@ public class BaseApplication implements Application {
protected BaseApplicationBuilder builder; protected BaseApplicationBuilder builder;
protected final String sessionName;
private final HttpResponseRenderer httpResponseRenderer; private final HttpResponseRenderer httpResponseRenderer;
private final Attributes attributes; private final Attributes attributes;
@ -61,30 +57,9 @@ public class BaseApplication implements Application {
protected BaseApplication(BaseApplicationBuilder builder) { protected BaseApplication(BaseApplicationBuilder builder) {
this.builder = builder; this.builder = builder;
this.sessionName = builder.settings.get("session.name", "SESS");
this.httpResponseRenderer = newResponseRenderer();
this.attributes = newAttributes(); this.attributes = newAttributes();
this.applicationModuleList = new ArrayList<>(); this.applicationModuleList = new ArrayList<>();
for (Map.Entry<String, Settings> entry : builder.settings.getGroups("module").entrySet()) { this.httpResponseRenderer = newResponseRenderer();
String moduleName = entry.getKey();
Settings moduleSettings = entry.getValue();
if (moduleSettings.getAsBoolean("enabled", true)) {
try {
String className = moduleSettings.get("class");
@SuppressWarnings("unchecked")
Class<ApplicationModule> clazz =
(Class<ApplicationModule>) Class.forName(className, true, builder.classLoader);
ApplicationModule applicationModule = clazz.getConstructor(Application.class, String.class, Settings.class)
.newInstance(this, moduleName, moduleSettings);
applicationModuleList.add(applicationModule);
} catch (Exception e) {
logger.log(Level.WARNING, e.getMessage(), e);
throw new IllegalArgumentException("class not found or not loadable: " + e.getMessage());
}
} else {
logger.log(Level.WARNING, "disabled module: " + moduleName);
}
}
} }
public static BaseApplicationBuilder builder() { public static BaseApplicationBuilder builder() {
@ -111,6 +86,16 @@ public class BaseApplication implements Application {
return builder.home; return builder.home;
} }
@Override
public String getPrefix() {
return builder.prefix;
}
@Override
public boolean shouldNegotiateLocale() {
return builder.shouldNegotiateLocale;
}
@Override @Override
public Locale getLocale() { public Locale getLocale() {
return builder.locale; return builder.locale;
@ -131,19 +116,6 @@ public class BaseApplication implements Application {
return builder.contextPath; return builder.contextPath;
} }
@Override
public Settings getSettings() {
return builder.settings;
}
public String getSecret() {
return builder.secret;
}
public Set<String> getStaticFileSuffixes() {
return builder.staticFileSuffixes;
}
@Override @Override
public Collection<ApplicationModule> getModules() { public Collection<ApplicationModule> getModules() {
return applicationModuleList; return applicationModuleList;
@ -195,6 +167,18 @@ public class BaseApplication implements Application {
} }
} }
public String getSessionName() {
return "SESS_" + getProfile().toLowerCase(Locale.ROOT);
}
public String getSecret() {
return builder.secret;
}
public Set<String> getStaticFileSuffixes() {
return builder.staticFileSuffixes;
}
protected HttpRequestValidator newRequestValidator() { protected HttpRequestValidator newRequestValidator() {
return new HttpRequestValidator(); return new HttpRequestValidator();
} }
@ -216,7 +200,7 @@ public class BaseApplication implements Application {
} }
protected Codec<Session> newSessionCodec(HttpRouterContext httpRouterContext) { protected Codec<Session> newSessionCodec(HttpRouterContext httpRouterContext) {
return new MemoryPropertiesSessionCodec(sessionName,this, 1024, Duration.ofDays(1)); return new MemoryPropertiesSessionCodec(getSessionName(),this, 1024, Duration.ofDays(1));
} }
protected Codec<UserProfile> newUserProfileCodec(HttpRouterContext httpRouterContext) { protected Codec<UserProfile> newUserProfileCodec(HttpRouterContext httpRouterContext) {
@ -227,7 +211,7 @@ public class BaseApplication implements Application {
return new IncomingContextHandler(userProfileCodec, return new IncomingContextHandler(userProfileCodec,
getSecret(), getSecret(),
"HmacSHA1", "HmacSHA1",
sessionName, getSessionName(),
sessionCodec, sessionCodec,
getStaticFileSuffixes(), getStaticFileSuffixes(),
() -> RandomUtil.randomString(16)); () -> RandomUtil.randomString(16));
@ -237,7 +221,7 @@ public class BaseApplication implements Application {
return new OutgoingContextHandler( return new OutgoingContextHandler(
getSecret(), getSecret(),
"HmacSHA1", "HmacSHA1",
sessionName, getSessionName(),
getStaticFileSuffixes(), getStaticFileSuffixes(),
Duration.ofDays(1), Duration.ofDays(1),
true, true,
@ -254,13 +238,13 @@ public class BaseApplication implements Application {
@Override @Override
public void onCreated(Session session) { public void onCreated(Session session) {
logger.log(Level.FINER, "session name = " + sessionName + " created = " + session); logger.log(Level.FINER, "session created = " + session);
applicationModuleList.forEach(module -> module.onOpen(session)); applicationModuleList.forEach(module -> module.onOpen(session));
} }
@Override @Override
public void onDestroy(Session session) { public void onDestroy(Session session) {
logger.log(Level.FINER, "session name = " + sessionName + " destroyed = " + session); logger.log(Level.FINER, "session destroyed = " + session);
if (throwable != null) { if (throwable != null) {
applicationModuleList.forEach(module -> module.onFail(session, throwable)); applicationModuleList.forEach(module -> module.onFail(session, throwable));
} else { } else {

View file

@ -12,7 +12,6 @@ import org.xbib.net.http.server.executor.BaseExecutor;
import org.xbib.net.http.server.executor.Executor; import org.xbib.net.http.server.executor.Executor;
import org.xbib.net.http.server.route.HttpRouter; import org.xbib.net.http.server.route.HttpRouter;
import org.xbib.net.mime.MimeTypeService; import org.xbib.net.mime.MimeTypeService;
import org.xbib.settings.Settings;
public class BaseApplicationBuilder implements ApplicationBuilder { public class BaseApplicationBuilder implements ApplicationBuilder {
@ -25,9 +24,9 @@ public class BaseApplicationBuilder implements ApplicationBuilder {
protected Path home; protected Path home;
protected ClassLoader classLoader; protected String prefix;
protected Settings settings; protected ClassLoader classLoader;
protected String contextPath; protected String contextPath;
@ -37,6 +36,8 @@ public class BaseApplicationBuilder implements ApplicationBuilder {
protected boolean sessionsEnabled; protected boolean sessionsEnabled;
protected boolean shouldNegotiateLocale;
protected Locale locale; protected Locale locale;
protected ZoneId zoneId; protected ZoneId zoneId;
@ -62,14 +63,16 @@ public class BaseApplicationBuilder implements ApplicationBuilder {
this.profile = profile; this.profile = profile;
return this; return this;
} }
@Override @Override
public BaseApplicationBuilder setHome(Path home) { public BaseApplicationBuilder setHome(Path home) {
this.home = home; this.home = home;
return this; return this;
} }
public BaseApplicationBuilder setSettings(Settings settings) { @Override
this.settings = settings; public BaseApplicationBuilder setPrefix(String prefix) {
this.prefix = prefix;
return this; return this;
} }
@ -102,6 +105,12 @@ public class BaseApplicationBuilder implements ApplicationBuilder {
return this; return this;
} }
@Override
public ApplicationBuilder shouldNegotiateLocale(boolean shouldNegotiateLocale) {
this.shouldNegotiateLocale = shouldNegotiateLocale;
return this;
}
@Override @Override
public ApplicationBuilder setLocale(Locale locale) { public ApplicationBuilder setLocale(Locale locale) {
this.locale = locale; this.locale = locale;
@ -150,8 +159,8 @@ public class BaseApplicationBuilder implements ApplicationBuilder {
if (this.home == null) { if (this.home == null) {
this.home = Paths.get(System.getProperty("application.home", ".")); this.home = Paths.get(System.getProperty("application.home", "."));
} }
if (this.settings == null) { if (this.prefix == null) {
this.settings = Settings.emptySettings(); this.prefix = "/";
} }
if (this.classLoader == null) { if (this.classLoader == null) {
this.classLoader = getClass().getClassLoader(); this.classLoader = getClass().getClassLoader();
@ -177,6 +186,26 @@ public class BaseApplicationBuilder implements ApplicationBuilder {
if (executor == null) { if (executor == null) {
this.executor = BaseExecutor.builder().build(); this.executor = BaseExecutor.builder().build();
} }
/*for (Map.Entry<String, Settings> entry : settings.getGroups("module").entrySet()) {
String moduleName = entry.getKey();
Settings moduleSettings = entry.getValue();
if (moduleSettings.getAsBoolean("enabled", true)) {
try {
String className = moduleSettings.get("class");
@SuppressWarnings("unchecked")
Class<ApplicationModule> clazz =
(Class<ApplicationModule>) Class.forName(className, true, builder.classLoader);
ApplicationModule applicationModule = clazz.getConstructor(Application.class, String.class, Settings.class)
.newInstance(this, moduleName, moduleSettings);
applicationModuleList.add(applicationModule);
} catch (Exception e) {
logger.log(Level.WARNING, e.getMessage(), e);
throw new IllegalArgumentException("class not found or not loadable: " + e.getMessage());
}
} else {
logger.log(Level.WARNING, "disabled module: " + moduleName);
}
}*/
return new BaseApplication(this); return new BaseApplication(this);
} }
} }

View file

@ -1,8 +1,6 @@
package org.xbib.net.http.server.ldap; package org.xbib.net.http.server.ldap;
import java.io.IOException; import java.io.IOException;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.Properties; import java.util.Properties;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
@ -12,7 +10,6 @@ import javax.naming.directory.InitialDirContext;
import javax.naming.ldap.InitialLdapContext; import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.StartTlsRequest; import javax.naming.ldap.StartTlsRequest;
import javax.naming.ldap.StartTlsResponse; import javax.naming.ldap.StartTlsResponse;
import javax.security.auth.Subject;
import javax.security.auth.login.Configuration; import javax.security.auth.login.Configuration;
import javax.security.auth.login.LoginContext; import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException; import javax.security.auth.login.LoginException;
@ -135,15 +132,13 @@ public class LdapContextFactory {
try { try {
LoginContext lc = new LoginContext(getClass().getName(), new CallbackHandlerImpl(principal, credentials)); LoginContext lc = new LoginContext(getClass().getName(), new CallbackHandlerImpl(principal, credentials));
lc.login(); lc.login();
initialDirContext = Subject.doAs(lc.getSubject(), (PrivilegedExceptionAction<InitialDirContext>) () -> {
Properties env = new Properties(); Properties env = new Properties();
env.put(Context.INITIAL_CONTEXT_FACTORY, factory); env.put(Context.INITIAL_CONTEXT_FACTORY, factory);
env.put(Context.PROVIDER_URL, providerUrl); env.put(Context.PROVIDER_URL, providerUrl);
env.put(Context.REFERRAL, referral); env.put(Context.REFERRAL, referral);
logger.log(Level.FINE, "new initial LDAP context: " + env); logger.log(Level.FINE, "new initial LDAP context: " + env);
return new InitialLdapContext(env, null); initialDirContext = new InitialLdapContext(env, null);
}); } catch (LoginException e) {
} catch (LoginException | PrivilegedActionException e) {
NamingException namingException = new NamingException(e.getMessage()); NamingException namingException = new NamingException(e.getMessage());
namingException.initCause(e); namingException.initCause(e);
throw namingException; throw namingException;

View file

@ -54,7 +54,7 @@ public class HtmlTemplateResource implements HttpServerResource {
this.templateResourceHandler = templateResourceHandler; this.templateResourceHandler = templateResourceHandler;
this.application = httpRouterContext.getAttributes().get(Application.class, "application"); this.application = httpRouterContext.getAttributes().get(Application.class, "application");
Objects.requireNonNull(application); Objects.requireNonNull(application);
this.shouldNegotiateLocale = application.getSettings().getAsBoolean("negotiateLocale", false); this.shouldNegotiateLocale = application.shouldNegotiateLocale();
this.responseBuilder = httpRouterContext.getAttributes().get(HttpResponseBuilder.class, "responsebuilder"); this.responseBuilder = httpRouterContext.getAttributes().get(HttpResponseBuilder.class, "responsebuilder");
Objects.requireNonNull(responseBuilder); Objects.requireNonNull(responseBuilder);
Path root = templateResourceHandler.getRoot(); Path root = templateResourceHandler.getRoot();
@ -64,17 +64,18 @@ public class HtmlTemplateResource implements HttpServerResource {
} }
this.resourcePath = httpRouterContext.getRequestBuilder().getRequestPath().substring(1); this.resourcePath = httpRouterContext.getRequestBuilder().getRequestPath().substring(1);
this.path = !resourcePath.isEmpty() ? root.resolve(resourcePath) : root; this.path = !resourcePath.isEmpty() ? root.resolve(resourcePath) : root;
String indexFileName = templateResourceHandler.getIndexFileName();
logger.log(Level.FINEST, "class = " + getClass().getName() + logger.log(Level.FINEST, "class = " + getClass().getName() +
" root = " + root + " root = " + root +
" resource path = " + resourcePath + " resource path = " + resourcePath +
" path = " + path + " path = " + path +
" index file name = " + templateResourceHandler.getIndexFileName()); " index file name = " + indexFileName);
this.name = path.getFileName().toString(); this.name = path.getFileName().toString();
this.baseName = AbstractResourceHandler.basename(name); this.baseName = AbstractResourceHandler.basename(name);
this.suffix = AbstractResourceHandler.suffix(name); this.suffix = AbstractResourceHandler.suffix(name);
if (Files.isDirectory(path)) { if (Files.isDirectory(path)) {
if (getIndexFileName() != null) { if (indexFileName != null) {
Path indexPath = path.resolve(templateResourceHandler.getIndexFileName()); Path indexPath = path.resolve(indexFileName);
logger.log(Level.FINEST, "resolved to index path = " + indexPath); logger.log(Level.FINEST, "resolved to index path = " + indexPath);
if (Files.exists(indexPath)) { if (Files.exists(indexPath)) {
logger.log(Level.FINEST, "index path exists"); logger.log(Level.FINEST, "index path exists");
@ -191,11 +192,14 @@ public class HtmlTemplateResource implements HttpServerResource {
} }
public String url(HttpRequest request, String rel, boolean absolute) { public String url(HttpRequest request, String rel, boolean absolute) {
String webPrefix = application.getSettings().get("web.prefix", "/"); String prefix = application.getPrefix();
if (!webPrefix.endsWith("/")) { if (prefix == null) {
webPrefix = webPrefix + "/"; prefix = "/";
} }
URL url = request.getBaseURL().resolve(webPrefix).resolve(rel); if (!prefix.endsWith("/")) {
prefix = prefix + "/";
}
URL url = request.getBaseURL().resolve(prefix).resolve(rel);
return absolute ? url.toExternalForm() : toOrigin(url); return absolute ? url.toExternalForm() : toOrigin(url);
} }

View file

@ -21,9 +21,9 @@ public class LocaleNegotiator {
} }
lang = lang.trim(); lang = lang.trim();
if ((pos = lang.indexOf('-')) == -1) { if ((pos = lang.indexOf('-')) == -1) {
locale = new Locale(lang, Locale.getDefault().getCountry()); locale = Locale.of(lang, Locale.getDefault().getCountry());
} else { } else {
locale = new Locale(lang.substring(0, pos), lang.substring(pos + 1)); locale = Locale.of(lang.substring(0, pos), lang.substring(pos + 1));
} }
} }
} }

View file

@ -59,16 +59,17 @@ public class BaseHttpRoute implements HttpRoute {
} }
@Override @Override
public String getPrefix() { public final String getPrefix() {
return prefix; return prefix;
} }
@Override @Override
public String getPath() { public final String getPath() {
return path; return path;
} }
public String getEffectivePath() { @Override
public final String getEffectivePath() {
String path = getPath(); String path = getPath();
if (getPrefix() != null && !getPrefix().isEmpty()) { if (getPrefix() != null && !getPrefix().isEmpty()) {
path = path.replaceFirst(getPrefix(), ""); path = path.replaceFirst(getPrefix(), "");

View file

@ -1,5 +1,6 @@
package org.xbib.net.http.server.route; package org.xbib.net.http.server.route;
import java.security.KeyStoreException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
@ -7,8 +8,17 @@ import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import org.xbib.net.URL;
import org.xbib.net.http.HttpAddress;
import org.xbib.net.http.HttpMethod;
import org.xbib.net.http.HttpVersion;
import org.xbib.net.http.server.HttpHandler; import org.xbib.net.http.server.HttpHandler;
import org.xbib.net.http.server.HttpServiceBuilder;
import org.xbib.net.http.server.domain.BaseHttpDomain;
import org.xbib.net.http.server.domain.HttpDomain; import org.xbib.net.http.server.domain.HttpDomain;
import org.xbib.net.http.server.domain.HttpDomainBuilder;
import org.xbib.net.http.server.domain.HttpSecurityDomain;
import org.xbib.net.http.server.handler.BadRequestHandler; import org.xbib.net.http.server.handler.BadRequestHandler;
import org.xbib.net.http.server.handler.ForbiddenHandler; import org.xbib.net.http.server.handler.ForbiddenHandler;
import org.xbib.net.http.server.handler.InternalServerErrorHandler; import org.xbib.net.http.server.handler.InternalServerErrorHandler;
@ -16,7 +26,11 @@ import org.xbib.net.http.server.handler.NotFoundHandler;
import org.xbib.net.http.server.handler.NotImplementedHandler; import org.xbib.net.http.server.handler.NotImplementedHandler;
import org.xbib.net.http.server.handler.UnauthorizedHandler; import org.xbib.net.http.server.handler.UnauthorizedHandler;
import org.xbib.net.http.server.handler.VersionNotSupportedHandler; import org.xbib.net.http.server.handler.VersionNotSupportedHandler;
import org.xbib.net.http.server.service.BaseHttpService;
import org.xbib.net.http.server.service.HttpService; import org.xbib.net.http.server.service.HttpService;
import org.xbib.settings.Settings;
import javax.net.ssl.SSLException;
public class BaseHttpRouterBuilder implements HttpRouterBuilder { public class BaseHttpRouterBuilder implements HttpRouterBuilder {
@ -31,16 +45,17 @@ public class BaseHttpRouterBuilder implements HttpRouterBuilder {
protected HttpRouteResolver<HttpService> httpRouteResolver; protected HttpRouteResolver<HttpService> httpRouteResolver;
protected BaseHttpRouterBuilder() { protected BaseHttpRouterBuilder() {
prefix = ""; this.prefix = "";
domains = new ArrayList<>(); this.domains = new ArrayList<>();
handlers = new HashMap<>(); this.handlers = new HashMap<>();
handlers.put(400, new BadRequestHandler()); // default handlers
handlers.put(401, new UnauthorizedHandler()); this.handlers.put(400, new BadRequestHandler());
handlers.put(403, new ForbiddenHandler()); this.handlers.put(401, new UnauthorizedHandler());
handlers.put(404, new NotFoundHandler()); this.handlers.put(403, new ForbiddenHandler());
handlers.put(500, new InternalServerErrorHandler()); this.handlers.put(404, new NotFoundHandler());
handlers.put(501, new NotImplementedHandler()); this.handlers.put(500, new InternalServerErrorHandler());
handlers.put(505, new VersionNotSupportedHandler()); this.handlers.put(501, new NotImplementedHandler());
this.handlers.put(505, new VersionNotSupportedHandler());
} }
@Override @Override
@ -55,7 +70,9 @@ public class BaseHttpRouterBuilder implements HttpRouterBuilder {
@Override @Override
public BaseHttpRouterBuilder setHandler(Integer code, HttpHandler httpHandler) { public BaseHttpRouterBuilder setHandler(Integer code, HttpHandler httpHandler) {
if (httpHandler != null) {
handlers.put(code, httpHandler); handlers.put(code, httpHandler);
}
return this; return this;
} }
@ -71,6 +88,31 @@ public class BaseHttpRouterBuilder implements HttpRouterBuilder {
return this; return this;
} }
@Override
public HttpRouterBuilder fromSettings(Settings settings) {
fromSettings(settings, null);
return this;
}
@Override
public HttpRouterBuilder fromSettings(Settings settings,
Map<String, HttpSecurityDomain> securityDomainMap) {
// global prefix
if (settings.containsSetting("prefix")) {
setPrefix(settings.get("prefix"));
}
// global handlers
for (Map.Entry<String, Settings> entry : settings.getGroups("handler").entrySet()) {
String codeString = entry.getKey();
Settings handlerSettings = entry.getValue();
setHandler(Integer.parseInt(codeString), createHttpHandler(handlerSettings));
}
// handler domains
for (Map.Entry<String, Settings> entry : settings.getGroups("domain").entrySet()) {
addDomain(createHttpDomain(entry.getValue(), securityDomainMap));
}
return this;
}
@Override @Override
public BaseHttpRouter build() { public BaseHttpRouter build() {
if (domains.isEmpty()) { if (domains.isEmpty()) {
@ -95,4 +137,79 @@ public class BaseHttpRouterBuilder implements HttpRouterBuilder {
} }
return new BaseHttpRouter(this); return new BaseHttpRouter(this);
} }
private HttpDomain createHttpDomain(Settings settings,
Map<String, HttpSecurityDomain> securityDomainMap) {
if (settings.getAsBoolean("enabled", true)) {
try {
HttpDomainBuilder httpDomainBuilder = BaseHttpDomain.builder();
httpDomainBuilder.setHttpAddress(createHttpAddress(settings));
for (String name : settings.getAsArray("name")) {
httpDomainBuilder.addName(name);
}
for (Map.Entry<String, Settings> entry : settings.getGroups("service").entrySet()) {
httpDomainBuilder.addService(createHttpService(securityDomainMap, prefix, entry.getKey(), entry.getValue()));
}
return httpDomainBuilder.build();
} catch (Exception e) {
logger.log(Level.WARNING, e.getMessage(), e);
throw new IllegalArgumentException("class not found or not loadable: " + e.getMessage());
}
} else {
logger.log(Level.WARNING, "disabled: " + settings.getAsMap());
}
return null;
}
private HttpAddress createHttpAddress(Settings settings) throws KeyStoreException, SSLException {
HttpAddress.Builder httpAddressBuilder = HttpAddress.builder();
if (settings.containsSetting("url")) {
URL url = URL.create(settings.get("url"));
httpAddressBuilder.setHost(url.getHost());
httpAddressBuilder.setPort(url.getPort());
httpAddressBuilder.setSecure("https".equals(url.getScheme()) || "h2".equals(url.getScheme()));
httpAddressBuilder.setVersion(url.getScheme().startsWith("http") ? HttpVersion.HTTP_1_1 : HttpVersion.HTTP_2_0);
} else {
httpAddressBuilder.setHost(settings.get("host", "localhost"));
boolean isSecure = settings.getAsBoolean("secure", false);
httpAddressBuilder.setSecure(isSecure);
httpAddressBuilder.setPort(settings.getAsInt("port", isSecure ? 443 : 80));
httpAddressBuilder.setVersion(HttpVersion.valueOf(settings.get("version", "HTTP_1_1")));
}
return httpAddressBuilder.build();
}
private HttpService createHttpService(Map<String, HttpSecurityDomain> securityDomainMap,
String prefix,
String path,
Settings settings) {
HttpServiceBuilder httpServiceBuilder = BaseHttpService.builder();
if (settings.containsSetting("securitydomain")) {
if (securityDomainMap != null) {
httpServiceBuilder.setSecurityDomain(securityDomainMap.get(settings.get("securitydomain")));
}
}
httpServiceBuilder.setPrefix(prefix);
httpServiceBuilder.setPath(path);
httpServiceBuilder.setMethod(HttpMethod.valueOf(settings.get("method", "GET")));
httpServiceBuilder.setHandler(createHttpHandler(settings));
return httpServiceBuilder.build();
}
private HttpHandler createHttpHandler(Settings settings) {
if (settings.getAsBoolean("enabled", true)) {
try {
String className = settings.get("class");
@SuppressWarnings("unchecked")
Class<HttpHandler> clazz = (Class<HttpHandler>) Class.forName(className, true, getClass().getClassLoader());
return clazz.getConstructor().newInstance();
} catch (Exception e) {
logger.log(Level.WARNING, e.getMessage(), e);
throw new IllegalArgumentException("class not found or not loadable: " + e.getMessage());
}
} else {
logger.log(Level.WARNING, "disabled: " + settings.getAsMap());
}
return null;
}
} }

View file

@ -2,7 +2,11 @@ package org.xbib.net.http.server.route;
import org.xbib.net.http.server.HttpHandler; import org.xbib.net.http.server.HttpHandler;
import org.xbib.net.http.server.domain.HttpDomain; import org.xbib.net.http.server.domain.HttpDomain;
import org.xbib.net.http.server.domain.HttpSecurityDomain;
import org.xbib.net.http.server.service.HttpService; import org.xbib.net.http.server.service.HttpService;
import org.xbib.settings.Settings;
import java.util.Map;
public interface HttpRouterBuilder { public interface HttpRouterBuilder {
@ -14,5 +18,10 @@ public interface HttpRouterBuilder {
HttpRouterBuilder setRouteResolver(HttpRouteResolver<HttpService> httpRouteResolver); HttpRouterBuilder setRouteResolver(HttpRouteResolver<HttpService> httpRouteResolver);
HttpRouterBuilder fromSettings(Settings settings);
HttpRouterBuilder fromSettings(Settings settings,
Map<String, HttpSecurityDomain> securityDomainMap);
HttpRouter build(); HttpRouter build();
} }

View file

@ -131,7 +131,7 @@ public class BaseSession implements Session {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override
public Object put(String key, Object value) { public final Object put(String key, Object value) {
Object v = value; Object v = value;
if (key.startsWith(CACHE_PREFIX)) { if (key.startsWith(CACHE_PREFIX)) {
if (value instanceof Map) { if (value instanceof Map) {
@ -147,7 +147,7 @@ public class BaseSession implements Session {
@SuppressWarnings({"unchecked", "rawtypes"}) @SuppressWarnings({"unchecked", "rawtypes"})
@Override @Override
public void putAll(Map map) { public final void putAll(Map map) {
if (map == null) { if (map == null) {
throw new NullPointerException("unexpected null map for putAll"); throw new NullPointerException("unexpected null map for putAll");
} }

View file

@ -3,6 +3,8 @@ module org.xbib.net.http.server.test {
requires org.xbib.net; requires org.xbib.net;
requires org.xbib.net.http; requires org.xbib.net.http;
requires org.xbib.net.http.server; requires org.xbib.net.http.server;
requires org.xbib.datastructures.json.tiny;
requires org.xbib.settings.api;
exports org.xbib.net.http.server.test.base; exports org.xbib.net.http.server.test.base;
exports org.xbib.net.http.server.test.ldap; exports org.xbib.net.http.server.test.ldap;
exports org.xbib.net.http.server.test.session; exports org.xbib.net.http.server.test.session;

View file

@ -14,6 +14,9 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
public class BaseHttpRouteResolverTest { public class BaseHttpRouteResolverTest {
public BaseHttpRouteResolverTest() {
}
@Test @Test
public void testEmptyRouteResolver() { public void testEmptyRouteResolver() {
BaseHttpRouteResolver.Builder<Integer> builder = BaseHttpRouteResolver.builder(); BaseHttpRouteResolver.Builder<Integer> builder = BaseHttpRouteResolver.builder();

View file

@ -0,0 +1,21 @@
package org.xbib.net.http.server.test.base;
import org.junit.jupiter.api.Test;
import org.xbib.net.http.server.route.BaseHttpRouter;
import org.xbib.net.http.server.route.HttpRouter;
import org.xbib.settings.Settings;
public class RouterBuilderTest {
public RouterBuilderTest() {
}
@Test
void buildFromSettings() {
// java.lang.NullPointerException: Cannot invoke "org.xbib.settings.SettingsBuilder.build()" because the return value of "org.xbib.settings.Settings$Holder.createBuilder()" is null
Settings settings = Settings.emptySettings();
HttpRouter httpRouter = BaseHttpRouter.builder()
.fromSettings(settings)
.build();
}
}

View file

@ -20,6 +20,8 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
public class LdapRealmTest { public class LdapRealmTest {
public LdapRealmTest() {
}
@Disabled @Disabled
@Test @Test

View file

@ -13,6 +13,9 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
public class LdapTest { public class LdapTest {
public LdapTest() {
}
@Disabled @Disabled
@Test @Test
public void testLdap() { public void testLdap() {

View file

@ -15,6 +15,9 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
public class JsonSessionTest { public class JsonSessionTest {
public JsonSessionTest() {
}
@Test @Test
void testJsonSession() throws IOException { void testJsonSession() throws IOException {
Codec<Session> sessionCodec = newSessionCodec(); Codec<Session> sessionCodec = newSessionCodec();

View file

@ -1,6 +1,7 @@
package org.xbib.net.http.server.test.userprofile; package org.xbib.net.http.server.test.userprofile;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.xbib.datastructures.json.tiny.JsonBuilder;
import org.xbib.net.UserProfile; import org.xbib.net.UserProfile;
import org.xbib.net.http.server.persist.Codec; import org.xbib.net.http.server.persist.Codec;
import org.xbib.net.http.server.auth.FileJsonUserProfileCodec; import org.xbib.net.http.server.auth.FileJsonUserProfileCodec;
@ -12,6 +13,8 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
public class JsonUserProfileTest { public class JsonUserProfileTest {
public JsonUserProfileTest() {
}
@Test @Test
void testJsonUserProfile() throws IOException { void testJsonUserProfile() throws IOException {

View file

@ -115,16 +115,19 @@ public abstract class DefaultMarkupTemplate extends BaseTemplate {
} }
public String url(String rel, boolean absolute) { public String url(String rel, boolean absolute) {
String webPrefix = application.getSettings().get("web.prefix", "/"); String prefix = application.getPrefix();
if (!webPrefix.endsWith("/")) { if (prefix == null) {
webPrefix = webPrefix + "/"; prefix = "/";
}
if (!prefix.endsWith("/")) {
prefix = prefix + "/";
} }
if (request != null) { if (request != null) {
URL url = request.getBaseURL().resolve(webPrefix).resolve(rel); URL url = request.getBaseURL().resolve(prefix).resolve(rel);
return absolute ? url.toExternalForm() : toOrigin(url); return absolute ? url.toExternalForm() : toOrigin(url);
} else { } else {
logger.log(Level.WARNING, "request is null, returning " + webPrefix + rel); logger.log(Level.WARNING, "request is null, returning " + prefix + rel);
return webPrefix + rel; return prefix + rel;
} }
} }

View file

@ -72,7 +72,7 @@ public class GroovyMarkupTemplateHandler implements HttpHandler {
} }
} }
protected TemplateConfiguration createConfiguration(Class<? extends BaseTemplate> templateClass, protected final TemplateConfiguration createConfiguration(Class<? extends BaseTemplate> templateClass,
Locale locale, Locale locale,
boolean autoEscape, boolean autoEscape,
boolean autoIndent, boolean autoIndent,

View file

@ -7,8 +7,6 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/**
*/
public class HttpHeaders implements Headers { public class HttpHeaders implements Headers {
private final List<Pair<String, String>> list; private final List<Pair<String, String>> list;

View file

@ -35,7 +35,7 @@ public class DefaultCookie implements Cookie {
throw new IllegalArgumentException("empty name"); throw new IllegalArgumentException("empty name");
} }
if (value != null) { if (value != null) {
setValue(value); this.value = Objects.requireNonNull(value, "value");
} }
} }