diff --git a/lib/landline/dsl/methods_probe.rb b/lib/landline/dsl/methods_probe.rb index 9cd4cbb..e1c9c4c 100644 --- a/lib/landline/dsl/methods_probe.rb +++ b/lib/landline/dsl/methods_probe.rb @@ -4,6 +4,7 @@ require_relative '../response' require_relative '../util/multipart' require_relative '../util/parseutils' require_relative '../util/html' +require 'json' module Landline module DSL @@ -85,18 +86,12 @@ module Landline # Checks if current request has multipart/form-data associated with it # @return [Boolean] def form? - value, opts = Landline::Util::ParserCommon.parse_value( - request.headers["content-type"] - ) - if value == "multipart/form-data" and - opts["boundary"] - true - else - false - end + value, opts = _verify_content_type('multipart/form-data') + !!(value && opts && opts['boundary']) end # Returns formdata + # @note reads request.input - may nullify request.body. # @return [Hash{String=>(String,Landline::Util::FormPart)}] def form _, opts = Landline::Util::ParserCommon.parse_value( @@ -107,6 +102,39 @@ module Landline ).to_h end + # Checks if current request has urlencoded query string + # @return [Boolean] + def query? + !!_verify_content_type("application/x-www-form-urlencode") + end + + # Returns parsed query hash + # @note reads request.body - may nullify .input, .body data is memoized + # @return [Hash{String => Object}] query data + def query + Landline::Util::Query.new(request.body).parse + end + + # Returns shallow parsed query hash + # @note reads request.body - may nullify .input, .body data is memoized + # @return [Hash{String => Object}] query data + def query_shallow + Landline::Util::Query.new(request.body).parse_shallow + end + + # Check if body is a JSON object + # @return [Boolean] + def json? + !!_verify_content_type('application/json') + end + + # Return parse JSON object + # @note reads request.input - may nullify request.body. + # @return [Object] + def json + JSON.load(request.input) + end + # Open a file relative to current filepath # @see File.open def file(path, mode = "r", *all, &block) @@ -124,6 +152,22 @@ module Landline def unescape_html(text) Landline::Util.unescape_html(text) end + + private + + def _verify_content_type(type) + return false unless request.headers['content-type'] + + value, opts = Landline::Util::ParserCommon.parse_value( + request.headers["content-type"] + ) + if value == type and + request.input + [value, opts] + else + false + end + end end end end diff --git a/lib/landline/request.rb b/lib/landline/request.rb index 54274cf..d7967cf 100644 --- a/lib/landline/request.rb +++ b/lib/landline/request.rb @@ -41,12 +41,14 @@ module Landline end # Returns request body (if POST data exists) + # @note reads data from rack.input, which is not rewindable. .body data is memoized. # @return [nil, String] def body @body ||= @rack.input&.read end # Returns raw Rack input object + # @note Rack IO is not always rewindable - if it is read once, the data is gone (i.e. request.body will return nothing). # @return [IO] (May not entirely be compatible with IO, see Rack/SPEC.rdoc) def input @rack.input