diff --git a/server/src/main/java/io/kroki/server/error/ErrorHandler.java b/server/src/main/java/io/kroki/server/error/ErrorHandler.java index 53d964f4f..f34e64cd6 100644 --- a/server/src/main/java/io/kroki/server/error/ErrorHandler.java +++ b/server/src/main/java/io/kroki/server/error/ErrorHandler.java @@ -95,7 +95,9 @@ public void handle(RoutingContext context) { if (errorCode == 404) { statusMessage = "Not Found"; errorMessage = statusMessage; - } else if (failure instanceof BadRequestException || failure instanceof IllegalStateException) { + } else if (failure instanceof BadRequestException + || failure instanceof IllegalStateException + || failure instanceof MethodNotAllowedException) { if (failure instanceof BadRequestException) { int statusCode = ((BadRequestException) failure).getStatusCode(); if (statusCode != -1) { @@ -108,6 +110,9 @@ public void handle(RoutingContext context) { } else { statusMessage = statusMessageMap.getOrDefault(errorCode, "Bad Request"); } + if (failure instanceof MethodNotAllowedException) { + context.response().putHeader("Allow", ((MethodNotAllowedException) failure).getAllowMethods()); + } errorMessage = failure.getMessage(); if (failure instanceof BadRequestException) { htmlErrorMessage = ((BadRequestException) failure).getMessageHTML(); diff --git a/server/src/main/java/io/kroki/server/error/MethodNotAllowedException.java b/server/src/main/java/io/kroki/server/error/MethodNotAllowedException.java new file mode 100644 index 000000000..3af03c541 --- /dev/null +++ b/server/src/main/java/io/kroki/server/error/MethodNotAllowedException.java @@ -0,0 +1,22 @@ +package io.kroki.server.error; + +import java.util.List; + +public class MethodNotAllowedException extends RuntimeException { + + private final List allowMethods; + + public MethodNotAllowedException(List allowMethods) { + super(); + this.allowMethods = allowMethods; + } + + @Override + public String getMessage() { + return "Method not allowed. Please use a " + String.join(" or ", this.allowMethods) + " request."; + } + + public List getAllowMethods() { + return allowMethods; + } +} diff --git a/server/src/main/java/io/kroki/server/service/DiagramRegistry.java b/server/src/main/java/io/kroki/server/service/DiagramRegistry.java index 5f4afe7ff..cb70dab4e 100644 --- a/server/src/main/java/io/kroki/server/service/DiagramRegistry.java +++ b/server/src/main/java/io/kroki/server/service/DiagramRegistry.java @@ -1,17 +1,21 @@ package io.kroki.server.service; +import io.kroki.server.error.MethodNotAllowedException; +import io.kroki.server.error.UnsupportedFormatException; import io.kroki.server.response.Caching; +import io.vertx.core.http.HttpMethod; import io.vertx.ext.web.Router; import io.vertx.ext.web.handler.BodyHandler; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; public class DiagramRegistry { - private Map registry = new HashMap<>(); + private final Map registry = new HashMap<>(); private final Router router; private final BodyHandler bodyHandler; @@ -27,10 +31,33 @@ public void register(DiagramService diagramService, String... names) { router.get("/" + name + "/:output_format/:source_encoded") .handler(diagramHandler.createRequestReceived(name)) .handler(diagramHandler.createGet(name)); + router.route("/" + name) + .handler(event -> { + if (HttpMethod.POST.equals(event.request().method())) { + event.next(); + return; + } + event.fail(405, new MethodNotAllowedException(List.of("POST"))); + }); router.post("/" + name) .handler(bodyHandler) .handler(diagramHandler.createRequestReceived(name)) .handler(diagramHandler.createPost(name)); + router.route("/" + name + "/:output_format") + .handler(event -> { + if (HttpMethod.POST.equals(event.request().method())) { + event.next(); + return; + } + String outputFormat = event.pathParam("output_format"); + try { + diagramHandler.validate(name, outputFormat); + } catch (UnsupportedFormatException e) { + event.fail(e); + return; + } + event.fail(405, new MethodNotAllowedException(List.of("POST"))); + }); router.post("/" + name + "/:output_format") .handler(bodyHandler) .handler(diagramHandler.createRequestReceived(name))