mirror of
https://gitea.invidious.io/iv-org/shard-kemal.git
synced 2024-08-15 00:53:36 +00:00
First I tried implementing this solution in such a way that it explicitly clears body and set `Content-Length` header to body's size. But for some reason, if I call the URL from cURL then `Content-Length` header was blank which defeats the very purpose of `HEAD` requests. I then later anticipated that since `HEAD` would be by-default implemented by `HTTP::Server` module, there is no need to explicit clears body and setting `Content-Length` but the way we have written our previous specs were returning body as well. We could have used some TestServer kind of thing but if we go to that route we explicitly need to test non-existent route which I thought would create some inconsistency among specs. Crystal has clearly written specs for HEAD requests to make sure body is not read for them. See https://github.com/manastech/crystal/commit/acd0b6afb5af438a30529c36b11b e7954336f23f. I decided to write simple specs which are easy to maintain in long-run. We are adding identical HEAD route for every GET route which will make HEAD requests available for all defined GET requests. https://github.com/sdogruyol/kemal/issues/19 Added comment for code line which is adding HEAD routes for defined GET routes.
187 lines
5.3 KiB
Crystal
187 lines
5.3 KiB
Crystal
require "./spec_helper"
|
|
|
|
describe "Kemal::Handler" do
|
|
it "routes" do
|
|
kemal = Kemal::Handler.new
|
|
kemal.add_route "GET", "/" do
|
|
"hello"
|
|
end
|
|
request = HTTP::Request.new("GET", "/")
|
|
response = kemal.call(request)
|
|
response.body.should eq("hello")
|
|
end
|
|
|
|
it "routes request with query string" do
|
|
kemal = Kemal::Handler.new
|
|
kemal.add_route "GET", "/" do |env|
|
|
"hello #{env.params["message"]}"
|
|
end
|
|
request = HTTP::Request.new("GET", "/?message=world")
|
|
response = kemal.call(request)
|
|
response.body.should eq("hello world")
|
|
end
|
|
|
|
it "routes request with multiple query strings" do
|
|
kemal = Kemal::Handler.new
|
|
kemal.add_route "GET", "/" do |env|
|
|
"hello #{env.params["message"]} time #{env.params["time"]}"
|
|
end
|
|
request = HTTP::Request.new("GET", "/?message=world&time=now")
|
|
response = kemal.call(request)
|
|
response.body.should eq("hello world time now")
|
|
end
|
|
|
|
it "route parameter has more precedence than query string arguments" do
|
|
kemal = Kemal::Handler.new
|
|
kemal.add_route "GET", "/:message" do |env|
|
|
"hello #{env.params["message"]}"
|
|
end
|
|
request = HTTP::Request.new("GET", "/world?message=coco")
|
|
response = kemal.call(request)
|
|
response.body.should eq("hello world")
|
|
end
|
|
|
|
it "parses simple JSON body" do
|
|
kemal = Kemal::Handler.new
|
|
kemal.add_route "POST", "/" do |env|
|
|
name = env.params["name"]
|
|
age = env.params["age"]
|
|
"Hello #{name} Age #{age}"
|
|
end
|
|
|
|
json_payload = {"name": "Serdar", "age": 26}
|
|
request = HTTP::Request.new(
|
|
"POST",
|
|
"/",
|
|
body: json_payload.to_json,
|
|
headers: HTTP::Headers{"Content-Type": "application/json"},
|
|
)
|
|
|
|
response = kemal.call(request)
|
|
response.body.should eq("Hello Serdar Age 26")
|
|
end
|
|
|
|
it "parses JSON with string array" do
|
|
kemal = Kemal::Handler.new
|
|
kemal.add_route "POST", "/" do |env|
|
|
skills = env.params["skills"] as Array
|
|
"Skills #{skills.each.join(',')}"
|
|
end
|
|
|
|
json_payload = {"skills": ["ruby", "crystal"]}
|
|
request = HTTP::Request.new(
|
|
"POST",
|
|
"/",
|
|
body: json_payload.to_json,
|
|
headers: HTTP::Headers{"Content-Type": "application/json"},
|
|
)
|
|
|
|
response = kemal.call(request)
|
|
response.body.should eq("Skills ruby,crystal")
|
|
end
|
|
|
|
it "parses JSON with json object array" do
|
|
kemal = Kemal::Handler.new
|
|
kemal.add_route "POST", "/" do |env|
|
|
skills = env.params["skills"] as Array
|
|
skills_from_languages = skills.map do |skill|
|
|
skill = skill as Hash
|
|
skill["language"]
|
|
end
|
|
"Skills #{skills_from_languages.each.join(',')}"
|
|
end
|
|
|
|
json_payload = {"skills": [{"language": "ruby"}, {"language": "crystal"}]}
|
|
request = HTTP::Request.new(
|
|
"POST",
|
|
"/",
|
|
body: json_payload.to_json,
|
|
headers: HTTP::Headers{"Content-Type": "application/json"},
|
|
)
|
|
|
|
response = kemal.call(request)
|
|
response.body.should eq("Skills ruby,crystal")
|
|
end
|
|
|
|
it "renders 404 on not found" do
|
|
kemal = Kemal::Handler.new
|
|
request = HTTP::Request.new("GET", "/?message=world")
|
|
response = kemal.call(request)
|
|
response.status_code.should eq 404
|
|
end
|
|
|
|
it "renders 500 on exception" do
|
|
kemal = Kemal::Handler.new
|
|
kemal.add_route "GET", "/" do
|
|
raise "Exception"
|
|
end
|
|
request = HTTP::Request.new("GET", "/?message=world")
|
|
response = kemal.call(request)
|
|
response.status_code.should eq 500
|
|
response.body.includes?("Exception").should eq true
|
|
end
|
|
|
|
it "checks for _method param in POST request to simulate PUT" do
|
|
kemal = Kemal::Handler.new
|
|
kemal.add_route "PUT", "/", do |env|
|
|
"Hello World from PUT"
|
|
end
|
|
request = HTTP::Request.new(
|
|
"POST",
|
|
"/",
|
|
body: "_method=PUT",
|
|
headers: HTTP::Headers{"Content-Type": "application/x-www-form-urlencoded"}
|
|
)
|
|
response = kemal.call(request)
|
|
response.body.should eq("Hello World from PUT")
|
|
end
|
|
|
|
it "checks for _method param in POST request to simulate PATCH" do
|
|
kemal = Kemal::Handler.new
|
|
kemal.add_route "PATCH", "/", do |env|
|
|
"Hello World from PATCH"
|
|
end
|
|
request = HTTP::Request.new(
|
|
"POST",
|
|
"/",
|
|
body: "_method=PATCH",
|
|
headers: HTTP::Headers{"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"}
|
|
)
|
|
response = kemal.call(request)
|
|
response.body.should eq("Hello World from PATCH")
|
|
end
|
|
|
|
it "checks for _method param in POST request to simulate DELETE" do
|
|
kemal = Kemal::Handler.new
|
|
kemal.add_route "DELETE", "/", do |env|
|
|
"Hello World from DELETE"
|
|
end
|
|
json_payload = {"_method": "DELETE"}
|
|
request = HTTP::Request.new(
|
|
"POST",
|
|
"/",
|
|
body: json_payload.to_json,
|
|
headers: HTTP::Headers{"Content-Type": "application/json"}
|
|
)
|
|
response = kemal.call(request)
|
|
response.body.should eq("Hello World from DELETE")
|
|
end
|
|
|
|
it "can process HTTP HEAD requests for defined GET routes" do
|
|
kemal = Kemal::Handler.new
|
|
kemal.add_route "GET", "/" do |env|
|
|
"Hello World from GET"
|
|
end
|
|
request = HTTP::Request.new("HEAD", "/")
|
|
response = kemal.call(request)
|
|
response.status_code.should eq(200)
|
|
end
|
|
|
|
it "can't process HTTP HEAD requests for undefined GET routes" do
|
|
kemal = Kemal::Handler.new
|
|
request = HTTP::Request.new("HEAD", "/")
|
|
response = kemal.call(request)
|
|
response.status_code.should eq(404)
|
|
end
|
|
|
|
end
|