add prefix mode: router can manage a known prefix for a path, useful for web application hooks

This commit is contained in:
Jörg Prante 2023-03-23 17:38:16 +01:00
parent e488ed9d5a
commit d1910ce5cd
11 changed files with 53 additions and 27 deletions

View file

@ -76,18 +76,19 @@ public class BaseHttpService implements HttpService {
} }
BaseHttpService endpoint = (BaseHttpService) o; BaseHttpService endpoint = (BaseHttpService) o;
return Objects.equals(builder.methods, endpoint.builder.methods) && return Objects.equals(builder.methods, endpoint.builder.methods) &&
Objects.equals(builder.prefix, endpoint.builder.prefix) &&
Objects.equals(builder.pathSpec, endpoint.builder.pathSpec) && Objects.equals(builder.pathSpec, endpoint.builder.pathSpec) &&
Objects.equals(builder.handlers, endpoint.builder.handlers); Objects.equals(builder.handlers, endpoint.builder.handlers);
} }
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(builder.methods, builder.pathSpec, builder.handlers); return Objects.hash(builder.methods, builder.prefix, builder.pathSpec, builder.handlers);
} }
@Override @Override
public String toString() { public String toString() {
return "BaseHttpService[methods=" + builder.methods + ",path=" + builder.pathSpec + ",handler=" + builder.handlers + "]"; return "BaseHttpService[methods=" + builder.methods + ",prefix" + builder.prefix + ",path=" + builder.pathSpec + ",handler=" + builder.handlers + "]";
} }
} }

View file

@ -18,15 +18,15 @@ public class ClassLoaderResourceHandler extends AbstractResourceHandler {
private final ClassLoader classLoader; private final ClassLoader classLoader;
private final String prefix; private final String resourcePrefix;
public ClassLoaderResourceHandler(ClassLoader classLoader) { public ClassLoaderResourceHandler(ClassLoader classLoader) {
this(classLoader, null); this(classLoader, null);
} }
public ClassLoaderResourceHandler(ClassLoader classLoader, String prefix) { public ClassLoaderResourceHandler(ClassLoader classLoader, String resourcePrefix) {
this.classLoader = classLoader; this.classLoader = classLoader;
this.prefix = prefix; this.resourcePrefix = resourcePrefix;
} }
@Override @Override
@ -74,11 +74,11 @@ public class ClassLoaderResourceHandler extends AbstractResourceHandler {
private URL url; private URL url;
ClassLoaderResource(HttpServerContext httpServerContext) throws IOException { protected ClassLoaderResource(HttpServerContext httpServerContext) throws IOException {
String requestPath = httpServerContext.request().getRequestPath().substring(1); String contextPath = httpServerContext.getContextPath();
this.mimeType = mimeTypeService.getContentType(requestPath); this.mimeType = mimeTypeService.getContentType(contextPath);
this.resourcePath = requestPath.startsWith("/") ? requestPath.substring(1) : requestPath; this.resourcePath = contextPath.startsWith("/") ? contextPath.substring(1) : contextPath;
String path = prefix != null ? (prefix.endsWith("/") ? prefix : prefix + "/") : "/"; String path = resourcePrefix != null ? (resourcePrefix.endsWith("/") ? resourcePrefix : resourcePrefix + "/") : "/";
path = resourcePath.startsWith("/") ? path + resourcePath.substring(1) : path + resourcePath; path = resourcePath.startsWith("/") ? path + resourcePath.substring(1) : path + resourcePath;
String normalizedPath = PathNormalizer.normalize(resourcePath); String normalizedPath = PathNormalizer.normalize(resourcePath);
if (normalizedPath.startsWith("/")) { if (normalizedPath.startsWith("/")) {
@ -88,7 +88,7 @@ public class ClassLoaderResourceHandler extends AbstractResourceHandler {
this.name = normalizedPath; this.name = normalizedPath;
this.baseName = basename(name); this.baseName = basename(name);
this.suffix = suffix(name); this.suffix = suffix(name);
logger.log(Level.FINER, "trying: path=" + path + " classLoader=" + classLoader); logger.log(Level.FINER, "trying: path = " + path + " normalizedPath = " + normalizedPath);
java.net.URL url = classLoader.getResource(path); java.net.URL url = classLoader.getResource(path);
if (url != null) { if (url != null) {
this.url = URL.create(url.toString()); this.url = URL.create(url.toString());

View file

@ -39,7 +39,7 @@ public class FileResourceHandler extends AbstractResourceHandler {
protected Resource createResource(HttpServerContext httpServerContext) throws IOException { protected Resource createResource(HttpServerContext httpServerContext) throws IOException {
String pathSpec = httpServerContext.attributes().containsKey("templatePath") ? String pathSpec = httpServerContext.attributes().containsKey("templatePath") ?
(String) httpServerContext.attributes().get("templatePath") : (String) httpServerContext.attributes().get("templatePath") :
pathNameOfResource != null ? pathNameOfResource : httpServerContext.httpRequest().getRequestPath(); pathNameOfResource != null ? pathNameOfResource : httpServerContext.getContextPath();
if (pathSpec == null || pathSpec.isEmpty()) { if (pathSpec == null || pathSpec.isEmpty()) {
throw new IllegalArgumentException("path must not be null or empty"); throw new IllegalArgumentException("path must not be null or empty");
} }

View file

@ -47,7 +47,7 @@ public class HtmlTemplateResource implements HttpServerResource {
String indexFileName = templateResourceHandler.getIndexFileName(); String indexFileName = templateResourceHandler.getIndexFileName();
Application application = httpServerContext.attributes().get(Application.class, "application"); Application application = httpServerContext.attributes().get(Application.class, "application");
this.negotiateLocale = application.getSettings().getAsBoolean("negotiateLocale", false); this.negotiateLocale = application.getSettings().getAsBoolean("negotiateLocale", false);
Path root = templateResourceHandler.getPrefix(); Path root = templateResourceHandler.getRoot();
root = root != null ? root : application.getHome(); root = root != null ? root : application.getHome();
if (root == null) { if (root == null) {
throw new IllegalArgumentException("no home path set for template resource resolving"); throw new IllegalArgumentException("no home path set for template resource resolving");

View file

@ -8,16 +8,16 @@ import java.nio.file.Path;
public class HtmlTemplateResourceHandler extends AbstractResourceHandler { public class HtmlTemplateResourceHandler extends AbstractResourceHandler {
protected final Path prefix; protected final Path root;
protected final String suffix; protected final String suffix;
protected final String indexFileName; protected final String indexFileName;
public HtmlTemplateResourceHandler(Path prefix, public HtmlTemplateResourceHandler(Path root,
String suffix, String suffix,
String indexFileName) { String indexFileName) {
this.prefix = prefix; this.root = root;
this.suffix = suffix; this.suffix = suffix;
this.indexFileName = indexFileName; this.indexFileName = indexFileName;
} }
@ -47,8 +47,8 @@ public class HtmlTemplateResourceHandler extends AbstractResourceHandler {
return 0; return 0;
} }
public Path getPrefix() { public Path getRoot() {
return prefix; return root;
} }
public String getSuffix() { public String getSuffix() {

View file

@ -100,7 +100,7 @@ public class BaseHttpRouter implements HttpRouter {
requestBuilder.setRequestPath(extractPath(requestBuilder.getRequestURI())); requestBuilder.setRequestPath(extractPath(requestBuilder.getRequestURI()));
HttpRoute httpRoute = new BaseHttpRoute(httpDomain.getAddress(), HttpRoute httpRoute = new BaseHttpRoute(httpDomain.getAddress(),
Set.of(requestBuilder.getMethod()), Set.of(requestBuilder.getMethod()),
"", builder.prefix,
requestBuilder.getRequestPath(), requestBuilder.getRequestPath(),
true); true);
httpRouteResolver.resolve(httpRoute, httpRouteResolverResults::add); httpRouteResolver.resolve(httpRoute, httpRouteResolverResults::add);

View file

@ -18,11 +18,14 @@ import org.xbib.net.http.server.handler.VersionNotSupportedHandler;
public class BaseHttpRouterBuilder implements HttpRouterBuilder { public class BaseHttpRouterBuilder implements HttpRouterBuilder {
protected String prefix;
protected final Collection<HttpDomain> domains; protected final Collection<HttpDomain> domains;
protected final Map<Integer, HttpHandler> handlers; protected final Map<Integer, HttpHandler> handlers;
protected BaseHttpRouterBuilder() { protected BaseHttpRouterBuilder() {
prefix = "";
domains = new ArrayList<>(); domains = new ArrayList<>();
handlers = new HashMap<>(); handlers = new HashMap<>();
handlers.put(400, new BadRequestHandler()); handlers.put(400, new BadRequestHandler());
@ -34,6 +37,12 @@ public class BaseHttpRouterBuilder implements HttpRouterBuilder {
handlers.put(505, new VersionNotSupportedHandler()); handlers.put(505, new VersionNotSupportedHandler());
} }
@Override
public BaseHttpRouterBuilder setPrefix(String prefix) {
this.prefix = prefix;
return this;
}
@Override @Override
public BaseHttpRouterBuilder setHandler(Integer code, HttpHandler httpHandler) { public BaseHttpRouterBuilder setHandler(Integer code, HttpHandler httpHandler) {
handlers.put(code, httpHandler); handlers.put(code, httpHandler);

View file

@ -5,6 +5,8 @@ import org.xbib.net.http.server.HttpHandler;
public interface HttpRouterBuilder { public interface HttpRouterBuilder {
HttpRouterBuilder setPrefix(String prefix);
HttpRouterBuilder setHandler(Integer code, HttpHandler httpHandler); HttpRouterBuilder setHandler(Integer code, HttpHandler httpHandler);
HttpRouterBuilder addDomain(HttpDomain domain); HttpRouterBuilder addDomain(HttpDomain domain);

View file

@ -158,10 +158,10 @@ public class IncomingSessionHandler implements HttpHandler {
if (m == null) { if (m == null) {
return userProfile; return userProfile;
} }
if (m.containsKey(sessionUserName)) { if (sessionUserName != null && m.containsKey(sessionUserName)) {
userProfile.setUserId((String) m.get(sessionUserName)); userProfile.setUserId((String) m.get(sessionUserName));
} }
if (m.containsKey(sessionEffectiveUserName)) { if (sessionEffectiveUserName != null && m.containsKey(sessionEffectiveUserName)) {
userProfile.setEffectiveUserId((String) m.get(sessionEffectiveUserName)); userProfile.setEffectiveUserId((String) m.get(sessionEffectiveUserName));
} }
if (session != null && userProfile.getUserId() != null) { if (session != null && userProfile.getUserId() != null) {

View file

@ -107,8 +107,12 @@ public class OutgoingSessionHandler implements HttpHandler {
try { try {
if (userProfile != null) { if (userProfile != null) {
logger.log(Level.FINE, "user profile present: " + userProfile); logger.log(Level.FINE, "user profile present: " + userProfile);
session.put(sessionUserName, userProfile.getUserId()); if (sessionUserName != null) {
session.put(sessionEffectiveUserName, userProfile.getEffectiveUserId()); session.put(sessionUserName, userProfile.getUserId());
}
if (sessionEffectiveUserName != null) {
session.put(sessionEffectiveUserName, userProfile.getEffectiveUserId());
}
} }
sessionCodec.write(session.id(), session); sessionCodec.write(session.id(), session);
Cookie cookie = encodeCookie(session, host, path); Cookie cookie = encodeCookie(session, host, path);
@ -141,8 +145,12 @@ public class OutgoingSessionHandler implements HttpHandler {
return createEmptyCookie(host, path); return createEmptyCookie(host, path);
} }
Map<String, Object> map = new HashMap<>(); Map<String, Object> map = new HashMap<>();
map.put(sessionUserName, session.get(sessionUserName)); if (sessionUserName != null) {
map.put(sessionEffectiveUserName, session.get(sessionEffectiveUserName)); map.put(sessionUserName, session.get(sessionUserName));
}
if (sessionEffectiveUserName != null) {
map.put(sessionEffectiveUserName, session.get(sessionEffectiveUserName));
}
String payload = CookieSignatureUtil.toString(map); String payload = CookieSignatureUtil.toString(map);
String sig = CookieSignatureUtil.hmac(payload, sessionSecret, sessionCookieAlgorithm); String sig = CookieSignatureUtil.hmac(payload, sessionSecret, sessionCookieAlgorithm);
String cookieValue = String.join(":", id, payload, sig); String cookieValue = String.join(":", id, payload, sig);

View file

@ -113,8 +113,14 @@ public abstract class DefaultMarkupTemplate extends BaseTemplate {
} }
public String urlProto(String rel, boolean absolute) { public String urlProto(String rel, boolean absolute) {
URL url = request.getServerURL().resolve(rel); String prefix = application.getSettings().get("web.prefix", "/");
logger.log(Level.FINE, "server URL = " + request.getServerURL() + " rel = " + rel + " --> " + url); if (!prefix.endsWith("/")) {
prefix = prefix + "/";
}
URL url = request.getServerURL().resolve(prefix).resolve(rel);
logger.log(Level.FINE, "server base URL = " + request.getServerURL() +
" prefix = " + prefix +
" rel = " + rel + " --> " + url);
return absolute ? url.toExternalForm() : toOrigin(url); return absolute ? url.toExternalForm() : toOrigin(url);
} }