From 3f7c8b45772cbc5c5459d8a4f5ee501e917f2457 Mon Sep 17 00:00:00 2001 From: Serdar Dogruyol Date: Fri, 26 Oct 2018 15:00:24 +0300 Subject: [PATCH] Add Kemal::OverrideMethodHandler --- spec/override_method_handler_spec.cr | 29 ++++++++++++++++++++++++++++ src/kemal/override_method_handler.cr | 24 +++++++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 spec/override_method_handler_spec.cr create mode 100644 src/kemal/override_method_handler.cr diff --git a/spec/override_method_handler_spec.cr b/spec/override_method_handler_spec.cr new file mode 100644 index 0000000..2b34e29 --- /dev/null +++ b/spec/override_method_handler_spec.cr @@ -0,0 +1,29 @@ +require "./spec_helper" + +describe "Kemal::OverrideMethodHandler" do + it "does not override method without _method for POST requests" do + request = HTTP::Request.new( + "POST", + "/", + body: "_not_method=PATCH", + headers: HTTP::Headers{"Content-Type" => "application/x-www-form-urlencoded; charset=UTF-8"} + ) + + context = create_request_and_return_io_and_context(Kemal::OverrideMethodHandler::INSTANCE, request)[1] + + context.request.method.should eq "POST" + end + + it "overrides method with _method for POST requests" do + request = HTTP::Request.new( + "POST", + "/", + body: "_method=PATCH", + headers: HTTP::Headers{"Content-Type" => "application/x-www-form-urlencoded; charset=UTF-8"} + ) + + context = create_request_and_return_io_and_context(Kemal::OverrideMethodHandler::INSTANCE, request)[1] + + context.request.method.should eq "PATCH" + end +end diff --git a/src/kemal/override_method_handler.cr b/src/kemal/override_method_handler.cr new file mode 100644 index 0000000..097dee9 --- /dev/null +++ b/src/kemal/override_method_handler.cr @@ -0,0 +1,24 @@ +module Kemal + class OverrideMethodHandler + include HTTP::Handler + INSTANCE = new + + ALLOWED_METHODS = ["PUT", "PATCH", "DELETE"] + OVERRIDE_METHOD = "POST" + OVERRIDE_METHOD_PARAM_KEY = "_method" + + def call(context) + request = context.request + if request.method == OVERRIDE_METHOD + if context.params.body.has_key?(OVERRIDE_METHOD_PARAM_KEY) && override_method_valid?(context.params.body["_method"]) + request.method = context.params.body["_method"].upcase + end + end + call_next(context) + end + + def override_method_valid?(override_method : String) + ALLOWED_METHODS.includes?(override_method.upcase) + end + end +end