2016-07-17 11:43:13 +00:00
|
|
|
module Kemal
|
2017-10-06 11:53:53 +00:00
|
|
|
# Parses the request contents including query_params and body
|
|
|
|
# and converts them into a params hash which you can use within
|
|
|
|
# the environment context.
|
2016-07-17 11:43:13 +00:00
|
|
|
class ParamParser
|
|
|
|
URL_ENCODED_FORM = "application/x-www-form-urlencoded"
|
|
|
|
APPLICATION_JSON = "application/json"
|
2017-02-11 13:33:42 +00:00
|
|
|
MULTIPART_FORM = "multipart/form-data"
|
2018-01-26 15:32:24 +00:00
|
|
|
PARTS = %w(url query body json)
|
2016-11-10 13:38:29 +00:00
|
|
|
# :nodoc:
|
2018-06-16 15:03:00 +00:00
|
|
|
alias AllParamTypes = Nil | String | Int64 | Float64 | Bool | Hash(String, JSON::Any) | Array(JSON::Any)
|
2016-03-06 19:43:13 +00:00
|
|
|
|
2018-06-30 13:49:04 +00:00
|
|
|
def initialize(@request : HTTP::Request, @url : Hash(String, String) = {} of String => String)
|
2016-07-17 11:43:13 +00:00
|
|
|
@query = HTTP::Params.new({} of String => Array(String))
|
|
|
|
@body = HTTP::Params.new({} of String => Array(String))
|
|
|
|
@json = {} of String => AllParamTypes
|
|
|
|
@url_parsed = false
|
|
|
|
@query_parsed = false
|
|
|
|
@body_parsed = false
|
|
|
|
@json_parsed = false
|
|
|
|
end
|
2015-10-28 18:30:27 +00:00
|
|
|
|
2016-10-19 08:30:58 +00:00
|
|
|
private def unescape_url_param(value : String)
|
2018-11-01 11:29:05 +00:00
|
|
|
value.empty? ? value : URI.unescape(value)
|
2016-10-19 08:30:58 +00:00
|
|
|
rescue
|
|
|
|
value
|
2016-10-18 13:28:42 +00:00
|
|
|
end
|
|
|
|
|
2017-12-08 18:35:02 +00:00
|
|
|
{% for method in PARTS %}
|
2017-10-06 11:55:37 +00:00
|
|
|
def {{method.id}}
|
|
|
|
# check memoization
|
|
|
|
return @{{method.id}} if @{{method.id}}_parsed
|
2016-03-06 20:39:10 +00:00
|
|
|
|
2017-10-06 11:55:37 +00:00
|
|
|
parse_{{method.id}}
|
|
|
|
# memoize
|
|
|
|
@{{method.id}}_parsed = true
|
|
|
|
@{{method.id}}
|
|
|
|
end
|
2016-07-17 11:43:13 +00:00
|
|
|
{% end %}
|
2015-10-28 18:30:27 +00:00
|
|
|
|
2017-02-13 20:39:40 +00:00
|
|
|
private def parse_body
|
2018-06-30 13:49:04 +00:00
|
|
|
content_type = @request.headers["Content-Type"]?
|
2017-02-11 13:33:42 +00:00
|
|
|
return unless content_type
|
2017-11-20 12:01:16 +00:00
|
|
|
if content_type.try(&.starts_with?(URL_ENCODED_FORM))
|
|
|
|
@body = parse_part(@request.body)
|
|
|
|
return
|
|
|
|
end
|
2016-07-17 11:43:13 +00:00
|
|
|
end
|
2015-11-05 10:38:06 +00:00
|
|
|
|
2017-02-13 20:39:40 +00:00
|
|
|
private def parse_query
|
2016-07-17 11:43:13 +00:00
|
|
|
@query = parse_part(@request.query)
|
|
|
|
end
|
2015-11-05 10:38:06 +00:00
|
|
|
|
2017-02-13 20:39:40 +00:00
|
|
|
private def parse_url
|
2018-06-30 13:49:04 +00:00
|
|
|
@url.each { |key, value| @url[key] = unescape_url_param(value) }
|
2017-02-11 13:33:42 +00:00
|
|
|
end
|
|
|
|
|
2016-07-17 11:43:13 +00:00
|
|
|
# Parses JSON request body if Content-Type is `application/json`.
|
2017-10-06 11:53:53 +00:00
|
|
|
#
|
|
|
|
# - If request body is a JSON `Hash` then all the params are parsed and added into `params`.
|
|
|
|
# - If request body is a JSON `Array` it's added into `params` as `_json` and can be accessed like `params["_json"]`.
|
2017-02-13 20:39:40 +00:00
|
|
|
private def parse_json
|
2016-08-12 19:17:57 +00:00
|
|
|
return unless @request.body && @request.headers["Content-Type"]?.try(&.starts_with?(APPLICATION_JSON))
|
2015-11-10 11:30:16 +00:00
|
|
|
|
2016-11-25 07:45:25 +00:00
|
|
|
body = @request.body.not_nil!.gets_to_end
|
2016-07-17 11:43:13 +00:00
|
|
|
case json = JSON.parse(body).raw
|
|
|
|
when Hash
|
|
|
|
json.each do |key, value|
|
2018-06-16 15:03:00 +00:00
|
|
|
@json[key] = value.raw
|
2016-07-17 11:43:13 +00:00
|
|
|
end
|
|
|
|
when Array
|
|
|
|
@json["_json"] = json
|
2015-11-10 11:30:16 +00:00
|
|
|
end
|
2015-11-06 18:24:38 +00:00
|
|
|
end
|
|
|
|
|
2017-02-13 20:39:40 +00:00
|
|
|
private def parse_part(part : IO?)
|
2018-11-01 11:29:05 +00:00
|
|
|
HTTP::Params.parse(part ? part.gets_to_end : "")
|
2016-11-24 09:07:39 +00:00
|
|
|
end
|
|
|
|
|
2017-02-13 20:39:40 +00:00
|
|
|
private def parse_part(part : String?)
|
2018-11-01 11:29:05 +00:00
|
|
|
HTTP::Params.parse part.to_s
|
2016-07-17 11:43:13 +00:00
|
|
|
end
|
2015-11-05 10:38:06 +00:00
|
|
|
end
|
2015-10-28 18:30:27 +00:00
|
|
|
end
|