Add Kemal::OverrideMethodHandler

This commit is contained in:
Serdar Dogruyol 2022-12-11 12:14:18 +03:00
parent 6a10ea8127
commit 3a85857be0
2 changed files with 62 additions and 0 deletions

View file

@ -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

View file

@ -0,0 +1,33 @@
module Kemal
# Adds support for `_method` magic parameter to simulate PUT, PATCH, DELETE requests in an html form.
#
# This middleware is **not** in the default Kemal handlers. You need to explicitly add this to your handlers:
#
# ```ruby
# add_handler Kemal::OverrideMethodHandler
# ```
#
# **Important:** This middleware consumes `params.body` to read the `_method` magic parameter.
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[OVERRIDE_METHOD_PARAM_KEY])
request.method = context.params.body["_method"].upcase
end
end
call_next(context)
end
private def override_method_valid?(override_method : String)
ALLOWED_METHODS.includes?(override_method.upcase)
end
end
end