org.javawebstack.httpserver.HTTPServer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of http-server Show documentation
Show all versions of http-server Show documentation
This library provides a routing and request mapping stack on top of the well known and industry proven eclipse jetty http server. It also supports websockets.
The newest version!
package org.javawebstack.httpserver;
import org.javawebstack.abstractdata.AbstractMapper;
import org.javawebstack.abstractdata.NamingPolicy;
import org.javawebstack.httpserver.adapter.IHTTPSocketServer;
import org.javawebstack.httpserver.adapter.undertow.UndertowHTTPSocketServer;
import org.javawebstack.httpserver.handler.*;
import org.javawebstack.httpserver.router.DefaultRouteAutoInjector;
import org.javawebstack.httpserver.router.Route;
import org.javawebstack.httpserver.router.RouteAutoInjector;
import org.javawebstack.httpserver.router.RouteBinder;
import org.javawebstack.httpserver.transformer.response.ResponseTransformer;
import org.javawebstack.httpserver.transformer.route.DefaultRouteParamTransformer;
import org.javawebstack.httpserver.transformer.route.RouteParamTransformer;
import org.javawebstack.httpserver.transformer.route.RouteParamTransformerProvider;
import org.javawebstack.httpserver.util.DirectoryFileProvider;
import org.javawebstack.httpserver.util.ResourceFileProvider;
import org.javawebstack.httpserver.websocket.InternalWebSocketRequestHandler;
import org.reflections.Reflections;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.function.Function;
import java.util.logging.Level;
import java.util.logging.Logger;
public class HTTPServer implements RouteParamTransformerProvider {
private Logger logger = Logger.getLogger("HTTP-Server");
private final List routes = new ArrayList<>();
private final RouteBinder routeBinder = new RouteBinder(this);
private final List routeParamTransformers = new ArrayList<>();
private final List responseTransformers = new ArrayList<>();
private RequestHandler notFoundHandler = new DefaultNotFoundHandler();
private ExceptionHandler exceptionHandler = new ExceptionHandler.DefaultExceptionHandler();
private final List beforeRoutes = new ArrayList<>();
private final List afterRoutes = new ArrayList<>();
private final IHTTPSocketServer server;
private final List beforeInterceptors = new ArrayList<>();
private AbstractMapper abstractMapper = new AbstractMapper().setNamingPolicy(NamingPolicy.SNAKE_CASE);
private final List routeAutoInjectors = new ArrayList<>();
private final Map beforeMiddleware = new HashMap<>();
private final Map afterMiddleware = new HashMap<>();
private Function, Object> controllerInitiator = this::defaultControllerInitiator;
private boolean formMethods = true;
public HTTPServer() {
this(new UndertowHTTPSocketServer());
}
public HTTPServer(IHTTPSocketServer server) {
this.server = server;
routeParamTransformers.add(DefaultRouteParamTransformer.INSTANCE);
routeAutoInjectors.add(DefaultRouteAutoInjector.INSTANCE);
}
public HTTPServer maxThreads(int maxThreads) {
this.server.setMaxThreads(maxThreads);
return this;
}
public HTTPServer logger(Logger logger) {
this.logger = logger;
return this;
}
public HTTPServer abstractMapper(AbstractMapper mapper) {
this.abstractMapper = mapper;
return this;
}
public AbstractMapper getAbstractMapper() {
return abstractMapper;
}
public Logger getLogger() {
return logger;
}
public HTTPServer beforeInterceptor(RequestInterceptor handler) {
beforeInterceptors.add(handler);
return this;
}
public HTTPServer routeAutoInjector(RouteAutoInjector injector) {
routeAutoInjectors.add(injector);
return this;
}
public HTTPServer get(String pattern, RequestHandler... handlers) {
return route(HTTPMethod.GET, pattern, handlers);
}
public HTTPServer beforeGet(String pattern, RequestHandler... handlers) {
return beforeRoute(HTTPMethod.GET, pattern, handlers);
}
public HTTPServer afterGet(String pattern, AfterRequestHandler... handlers) {
return afterRoute(HTTPMethod.GET, pattern, handlers);
}
public HTTPServer post(String pattern, RequestHandler... handlers) {
return route(HTTPMethod.POST, pattern, handlers);
}
public HTTPServer beforePost(String pattern, RequestHandler... handlers) {
return beforeRoute(HTTPMethod.POST, pattern, handlers);
}
public HTTPServer afterPost(String pattern, AfterRequestHandler... handlers) {
return afterRoute(HTTPMethod.POST, pattern, handlers);
}
public HTTPServer put(String pattern, RequestHandler... handlers) {
return route(HTTPMethod.PUT, pattern, handlers);
}
public HTTPServer beforePut(String pattern, RequestHandler... handlers) {
return beforeRoute(HTTPMethod.PUT, pattern, handlers);
}
public HTTPServer afterPut(String pattern, AfterRequestHandler... handlers) {
return afterRoute(HTTPMethod.PUT, pattern, handlers);
}
public HTTPServer delete(String pattern, RequestHandler... handlers) {
return route(HTTPMethod.DELETE, pattern, handlers);
}
public HTTPServer staticDirectory(String pathPrefix, File directory) {
return staticHandler(pathPrefix, new StaticFileHandler().add(new DirectoryFileProvider(directory)));
}
public HTTPServer staticDirectory(String pathPrefix, String directory) {
return staticDirectory(pathPrefix, new File(directory));
}
public HTTPServer staticResourceDirectory(String pathPrefix, String prefix) {
return staticResourceDirectory(pathPrefix, null, prefix);
}
public HTTPServer staticResourceDirectory(String pathPrefix, ClassLoader classLoader, String prefix) {
return staticHandler(pathPrefix, new StaticFileHandler().add(new ResourceFileProvider(classLoader, prefix)));
}
public HTTPServer staticHandler(String pathPrefix, StaticFileHandler handler) {
return get(pathPrefix + (pathPrefix.endsWith("/") ? "" : "/") + "{*:path}", handler);
}
public HTTPServer beforeDelete(String pattern, RequestHandler... handlers) {
return beforeRoute(HTTPMethod.DELETE, pattern, handlers);
}
public HTTPServer afterDelete(String pattern, AfterRequestHandler... handlers) {
return afterRoute(HTTPMethod.DELETE, pattern, handlers);
}
public HTTPServer route(HTTPMethod method, String pattern, RequestHandler... handlers) {
routes.add(new Route(this, method, pattern, Arrays.asList(handlers)));
return this;
}
public HTTPServer beforeRoute(HTTPMethod method, String pattern, RequestHandler... handlers) {
beforeRoutes.add(new Route(this, method, pattern, Arrays.asList(handlers)));
return this;
}
public HTTPServer afterRoute(HTTPMethod method, String pattern, AfterRequestHandler... handlers) {
afterRoutes.add(new Route(this, method, pattern, null).setAfterHandlers(Arrays.asList(handlers)));
return this;
}
public HTTPServer route(HTTPMethod[] methods, String pattern, RequestHandler... handlers) {
for (HTTPMethod method : methods)
route(method, pattern, handlers);
return this;
}
public HTTPServer beforeRoute(HTTPMethod[] methods, String pattern, RequestHandler... handlers) {
for (HTTPMethod method : methods)
beforeRoute(method, pattern, handlers);
return this;
}
public HTTPServer afterRoute(HTTPMethod[] methods, String pattern, AfterRequestHandler... handlers) {
for (HTTPMethod method : methods)
afterRoute(method, pattern, handlers);
return this;
}
public HTTPServer any(String pattern, RequestHandler... handlers) {
return route(HTTPMethod.values(), pattern, handlers);
}
public HTTPServer beforeAny(String pattern, RequestHandler... handlers) {
return beforeRoute(HTTPMethod.values(), pattern, handlers);
}
public HTTPServer afterAny(String pattern, AfterRequestHandler... handlers) {
return afterRoute(HTTPMethod.values(), pattern, handlers);
}
public HTTPServer webSocket(String pattern, WebSocketHandler handler) {
if(!server.isWebSocketSupported())
throw new UnsupportedOperationException(server.getClass().getName() + " does not support websockets!");
return route(HTTPMethod.WEBSOCKET, pattern, new InternalWebSocketRequestHandler(handler));
}
public HTTPServer middleware(String name, RequestHandler handler) {
beforeMiddleware.put(name, handler);
return this;
}
public HTTPServer middleware(String name, AfterRequestHandler handler) {
afterMiddleware.put(name, handler);
return this;
}
public HTTPServer notFound(RequestHandler handler) {
notFoundHandler = handler;
return this;
}
public HTTPServer routeParamTransformer(RouteParamTransformer transformer) {
routeParamTransformers.add(transformer);
return this;
}
public HTTPServer responseTransformer(ResponseTransformer transformer) {
responseTransformers.add(transformer);
return this;
}
public HTTPServer exceptionHandler(ExceptionHandler handler) {
exceptionHandler = handler;
return this;
}
private Object defaultControllerInitiator (Class> clazz) {
try {
return clazz.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
public HTTPServer controllerInitiator (Function, Object> initiator) {
controllerInitiator = initiator;
return this;
}
public HTTPServer controller(Class> parentClass, Package p) {
return controller("", parentClass, p);
}
public HTTPServer controller(String globalPrefix, Class> parentClass, Package p) {
Reflections reflections = new Reflections(p.getName());
reflections.getSubTypesOf(parentClass)
.stream()
.map(controllerInitiator)
.forEach(c -> controller(globalPrefix, c));
return this;
}
public HTTPServer controller(Object controller) {
return controller("", controller);
}
public HTTPServer controller(String globalPrefix, Object controller) {
routeBinder.bind(globalPrefix, controller);
return this;
}
public HTTPServer port(int port) {
server.setPort(port);
return this;
}
public HTTPServer start() {
server.setHandler(socket -> execute(new Exchange(this, socket)));
try {
server.start();
logger.info("HTTP-Server started on port " + server.getPort());
} catch (Exception ex) {
throw new RuntimeException(ex);
}
return this;
}
public void join() {
server.join();
}
public void stop() {
try {
server.stop();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
public void execute(Exchange exchange) {
Exchange.exchanges.set(exchange);
try {
Object response = null;
try {
for (RequestInterceptor ic : beforeInterceptors) {
if (ic.intercept(exchange)) {
exchange.close();
Exchange.exchanges.remove();
return;
}
}
middlewares:
for (Route route : beforeRoutes) {
Map pathVariables = route.match(exchange);
if (pathVariables == null)
continue;
exchange.getPathVariables().putAll(pathVariables);
for (RequestHandler handler : route.getHandlers()) {
try {
response = handler.handle(exchange);
} catch (Throwable ex) {
response = exceptionHandler.handle(exchange, ex);
}
if (response != null)
break middlewares;
}
}
exchange.getPathVariables().clear();
if (response == null) {
routes:
for (Route route : routes) {
Map pathVariables = route.match(exchange);
if (pathVariables == null)
continue;
exchange.getPathVariables().putAll(pathVariables);
for (RequestHandler handler : route.getHandlers()) {
response = handler.handle(exchange);
if (exchange.getMethod() == HTTPMethod.WEBSOCKET) {
Exchange.exchanges.remove();
return;
}
if (response != null)
break routes;
}
exchange.getPathVariables().clear();
}
}
} catch (Throwable ex) {
response = exceptionHandler.handle(exchange, ex);
}
if (response == null)
response = notFoundHandler.handle(exchange);
exchange.getPathVariables().clear();
for (Route route : afterRoutes) {
Map pathVariables = route.match(exchange);
if (pathVariables == null)
continue;
exchange.getPathVariables().putAll(pathVariables);
for (AfterRequestHandler handler : route.getAfterHandlers())
response = handler.handleAfter(exchange, response);
exchange.getPathVariables().clear();
}
if (response != null)
exchange.write(transformResponse(exchange, response));
if (exchange.getMethod() != HTTPMethod.WEBSOCKET)
exchange.close();
Exchange.exchanges.remove();
return;
} catch (Throwable ex) {
try {
exchange.write(transformResponse(exchange, exceptionHandler.handle(exchange, ex)));
} catch (Throwable ex2) {
logger.log(Level.SEVERE, ex2, () -> "An error occured in the exception handler!");
}
}
Exchange.exchanges.remove();
exchange.close();
}
public List getRouteParamTransformer() {
return routeParamTransformers;
}
public RouteParamTransformer getRouteParamTransformer(String type) {
return routeParamTransformers.stream().filter(t -> t.canTransform(type)).findFirst().orElse(null);
}
public RequestHandler getBeforeMiddleware(String name) {
return beforeMiddleware.get(name);
}
public AfterRequestHandler getAfterMiddleware(String name) {
return afterMiddleware.get(name);
}
public List getRouteAutoInjectors() {
return routeAutoInjectors;
}
public byte[] transformResponse(Exchange exchange, Object object) {
for (ResponseTransformer t : responseTransformers) {
byte[] res = t.transformBytes(exchange, object);
if (res != null)
return res;
}
if(object instanceof byte[])
return (byte[]) object;
return object.toString().getBytes(StandardCharsets.UTF_8);
}
public ExceptionHandler getExceptionHandler() {
return exceptionHandler;
}
public boolean isFormMethods() {
return formMethods;
}
public HTTPServer disableFormMethods() {
formMethods = false;
return this;
}
}