Skip to content

Commit 1860e60

Browse files
committed
Handle CORS preflight (OPTIONS) requests up-front
1 parent e167732 commit 1860e60

1 file changed

Lines changed: 41 additions & 5 deletions

File tree

src/main/java/org/tinystruct/system/TomcatServer.java

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -371,7 +371,7 @@ public void service(HttpServletRequest request, HttpServletResponse response) th
371371
String query = _request.getParameter("q");
372372
if (query != null) {
373373
Action.Mode mode = Action.Mode.fromName(request.getMethod());
374-
handleRequest(query, context, _response, mode);
374+
handleRequest(query, context, _request, _response, mode);
375375
} else {
376376
handleDefaultPage(context, _response);
377377
}
@@ -451,13 +451,48 @@ else if(call instanceof String) {
451451
* @param mode
452452
* @throws IOException if an I/O error occurs
453453
*/
454-
private void handleRequest(String query, org.tinystruct.application.Context context, Response<HttpServletResponse, ServletOutputStream> response, Action.Mode mode) throws IOException, ApplicationException {
454+
private void handleRequest(String query, org.tinystruct.application.Context context, Request request, Response<HttpServletResponse, ServletOutputStream> response, Action.Mode mode) throws IOException, ApplicationException {
455+
// Handle CORS preflight (OPTIONS) requests up-front: these have no body.
456+
if ("OPTIONS".equalsIgnoreCase(request.method().name())) {
457+
String origin = request.headers().get(Header.ORIGIN).toString();
458+
String acrMethod = request.headers().get(Header.ACCESS_CONTROL_REQUEST_METHOD).toString();
459+
String acrHeaders = request.headers().get(Header.ACCESS_CONTROL_REQUEST_HEADERS).toString();
460+
461+
// Allow origins: prefer explicit setting, otherwise echo Origin or wildcard
462+
String allowOrigin = settings.getOrDefault("cors.allowed.origins", origin != null ? origin : "*");
463+
response.addHeader("Access-Control-Allow-Origin", allowOrigin);
464+
// Make responses vary by Origin when echoing it
465+
if (origin != null) {
466+
response.addHeader("Vary", "Origin");
467+
}
468+
469+
// Allow methods: prefer configured list, otherwise echo requested or use sensible defaults
470+
String allowMethods = settings.getOrDefault("cors.allowed.methods", acrMethod != null ? acrMethod : "GET,POST,PUT,DELETE,OPTIONS");
471+
response.addHeader("Access-Control-Allow-Methods", allowMethods);
472+
473+
// Allow headers: prefer configured list, otherwise echo requested or common headers
474+
String allowHeaders = settings.getOrDefault("cors.allowed.headers", acrHeaders != null ? acrHeaders : "Content-Type,Authorization");
475+
response.addHeader("Access-Control-Allow-Headers", allowHeaders);
476+
477+
// Allow credentials if explicitly enabled in settings
478+
if ("true".equalsIgnoreCase(settings.get("cors.allow.credentials"))) {
479+
response.addHeader("Access-Control-Allow-Credentials", "true");
480+
}
481+
482+
// Cache the preflight response for a configurable duration (seconds)
483+
String maxAge = settings.getOrDefault("cors.preflight.maxage", "3600");
484+
response.addHeader("Access-Control-Max-Age", maxAge);
485+
486+
// No response body for preflight; return 204 No Content
487+
response.setStatus(ResponseStatus.NO_CONTENT);
488+
return;
489+
}
490+
455491
// Handle request
456492
query = StringUtilities.htmlSpecialChars(query);
457493
Object message = ApplicationManager.call(query, context, mode);
458494
if (message != null) {
459-
if (message instanceof byte[]) {
460-
byte[] bytes = (byte[]) message;
495+
if (message instanceof byte[] bytes) {
461496
response.addHeader(Header.CONTENT_LENGTH.name(), String.valueOf(bytes.length));
462497
response.get().write(bytes);
463498
} else {
@@ -518,7 +553,8 @@ private boolean isSSL() {
518553
}
519554

520555
private String getProtocol(HttpServletRequest request) {
521-
return isSSL() ? "https://" : "http://";
556+
// Use the request object to determine the protocol
557+
return request.isSecure() ? "https://" : "http://";
522558
}
523559

524560
private String getHost(HttpServletRequest request) {

0 commit comments

Comments
 (0)