WebResourceUrls.java
/*
* Copyright (c) 2007-2026 MetaSolutions AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.entrystore.rest.springboot.util;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.net.URI;
/**
* Supplies URLs for the static resources referenced by the Thymeleaf templates.
*
* <p>Exposed to the templates as the bean {@code webResources}, so a view can reference it
* without every controller having to add a model attribute. That matters because
* {@code auth.html} is also rendered from {@code AppExceptionHandler}, where
* {@code @ModelAttribute} advice does not run.
*
* <p>The paths are root-relative rather than relative to the page, because the same template is
* rendered at more than one path depth ({@code /auth/signup} and {@code /auth/signup/confirm}),
* and rather than absolute, so the link never pins a scheme or host the page was not served on.
* The prefix comes from {@code entrystore.baseurl.folder}: a reverse proxy may mount EntryStore
* under a path prefix and strip it before forwarding, in which case the browser must ask for the
* prefixed path while the application only ever sees the un-prefixed one.
*/
@Component("webResources")
public class WebResourceUrls {
private static final String STYLESHEET = "css/entrystore.css";
private final String stylesheetPath;
public WebResourceUrls(@Value("${entrystore.baseurl.folder:/}") String baseUrl) {
this.stylesheetPath = basePath(baseUrl) + STYLESHEET;
}
/**
* Extracts the path component of the configured base URL, normalised to start and end with a
* slash. Falls back to the root for a value that is not a parsable URI, so a misconfigured base
* URL costs styling rather than startup.
*/
static String basePath(String baseUrl) {
String path;
try {
path = URI.create(baseUrl).getPath();
} catch (IllegalArgumentException e) {
path = null;
}
if (path == null || path.isBlank()) {
return "/";
}
if (!path.startsWith("/")) {
path = "/" + path;
}
return path.endsWith("/") ? path : path + "/";
}
public String getStylesheetPath() {
return stylesheetPath;
}
}