Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 11 additions & 9 deletions src/main/java/org/juv25d/filter/CorsFilter.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,22 @@

import org.juv25d.http.HttpRequest;
import org.juv25d.http.HttpResponse;

import org.juv25d.util.ConfigLoader;
import java.io.IOException;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

public class CorsFilter implements Filter {

// Whitelist, allow known origins:
private static final Set<String> ALLOWED_ORIGINS = Set.of(
"http://localhost:3000"
);
private final Set <String> allowedOrigins;
private final String allowedMethods;

// Supported methods
private static final String ALLOWED_METHODS = "GET, POST, PUT, PATCH, DELETE, OPTIONS";
public CorsFilter() {
ConfigLoader config = ConfigLoader.getInstance();
this.allowedOrigins = new HashSet<>(config.getAllowedOrigins());
this.allowedMethods = String.join(",", config.getAllowedMethods());
}

@Override
public void doFilter(HttpRequest req, HttpResponse res, FilterChain chain) throws IOException {
Expand All @@ -28,7 +30,7 @@ public void doFilter(HttpRequest req, HttpResponse res, FilterChain chain) throw
}

// Origin exists but are not allowed, return no CORS headers
if (!ALLOWED_ORIGINS.contains(origin)) {
if (!allowedOrigins.contains(origin)) {
chain.doFilter(req, res);
return;
}
Expand All @@ -44,7 +46,7 @@ public void doFilter(HttpRequest req, HttpResponse res, FilterChain chain) throw

// Preflight, OPTIONS
if ("OPTIONS".equalsIgnoreCase(req.method())) {
res.setHeader("Access-Control-Allow-Methods", ALLOWED_METHODS);
res.setHeader("Access-Control-Allow-Methods", allowedMethods);

// If browser requests specific headers, mirror
String requestedHeaders = header(req.headers(), "Access-Control-Request-Headers");
Expand Down
47 changes: 46 additions & 1 deletion src/main/java/org/juv25d/util/ConfigLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
import org.jspecify.annotations.Nullable;
import org.juv25d.proxy.ProxyRoute;
import org.yaml.snakeyaml.Yaml;

import java.io.InputStream;
import java.util.*;


public class ConfigLoader {
@Nullable private static ConfigLoader instance;
private int port;
Expand All @@ -19,6 +19,8 @@ public class ConfigLoader {
private boolean requestBodySizeEnabled;
private List<String> trustedProxies;
private List<ProxyRoute> proxyRoutes = new ArrayList<>();
private List <String> allowedOrigins = List.of();
private List <String> allowedMethods = List.of();

private ConfigLoader() {
loadConfiguration(getClass().getClassLoader()
Expand Down Expand Up @@ -54,11 +56,14 @@ private void loadConfiguration(InputStream input) {
this.rootDirectory = "static";
this.logLevel = "INFO";
this.trustedProxies = List.of();
this.allowedOrigins = List.of();
this.allowedMethods = List.of("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS");

// server
Object serverObj = config.get("server");
if (serverObj != null) {
Map<String, Object> serverConfig = asStringObjectMap(serverObj);

Object portValue = serverConfig.get("port");
if (portValue instanceof Number n) this.port = n.intValue();

Expand Down Expand Up @@ -115,6 +120,38 @@ private void loadConfiguration(InputStream input) {
Long.parseLong(String.valueOf(rateLimitingConfig.getOrDefault("burst-capacity", 100L)));
}

//Cors
Object corsObj = config.get("cors");
if (corsObj != null) {
Map<String, Object> corsConfig = asStringObjectMap(corsObj);

//Allowed-origins
Object origins = corsConfig.get("allowed-origins");
if (origins instanceof List<?> list) {
this.allowedOrigins = list.stream()
.filter(Objects::nonNull)
.map(String::valueOf)
.map(String::trim)
.filter(s -> !s.isEmpty())
.toList();
}

//Allowed-methods
Object methods = corsConfig.get("allowed-methods");
if (methods instanceof List<?> methodList) {
List <String> parsedMethods = methodList.stream()
.filter(Objects::nonNull)
.map(String::valueOf)
.map(String::trim)
.filter(s -> !s.isEmpty())
.map(s -> s.toUpperCase(Locale.ROOT))
.toList();

this.allowedMethods = parsedMethods.isEmpty()
? List.of("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS")
: parsedMethods;
}
Comment thread
SandraNelj marked this conversation as resolved.
}
// request body size
this.requestBodySizeEnabled = false;
this.maxBodySizeMb = 10L;
Expand Down Expand Up @@ -185,4 +222,12 @@ public long getMaxBodySizeMb() {
public List<ProxyRoute> getProxyRoutes() {
return Collections.unmodifiableList(proxyRoutes);
}

public List<String> getAllowedOrigins() {
return allowedOrigins;
}
public List<String> getAllowedMethods() {
return allowedMethods;
}

}
10 changes: 10 additions & 0 deletions src/main/resources/application-properties.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,16 @@ rate-limiting:
requests-per-minute: 60
burst-capacity: 100

cors:
allowed-origins:
- http://localhost:3000
allowed-methods:
- GET
- POST
- PUT
- PATCH
- DELETE
- OPTIONS
request-body-size:
enabled: true
max-size-mb: 10