made form parser easier to use
This commit is contained in:
parent
bfc9a3066b
commit
bc8750daf7
|
@ -2,17 +2,12 @@
|
|||
|
||||
$LOAD_PATH.unshift("#{File.dirname(__FILE__)}/lib")
|
||||
require 'hyde'
|
||||
require 'hyde/util/multipart'
|
||||
require 'hyde/util/header'
|
||||
|
||||
app = Hyde::Server.new do
|
||||
root ENV["PWD"]
|
||||
index ["index.html"]
|
||||
post "/" do
|
||||
_, opts = Hyde::Util.parse_value(request.headers["content-type"])
|
||||
puts Hyde::Util::MultipartParser.new(
|
||||
request.input, opts["boundary"]
|
||||
).to_h.pretty_inspect
|
||||
puts form.pretty_inspect if form?
|
||||
bounce
|
||||
end
|
||||
serve "*.html"
|
||||
|
|
|
@ -12,8 +12,9 @@ app = Hyde::Server.new do
|
|||
end
|
||||
path "important" do
|
||||
preprocess do |req|
|
||||
|
||||
# Implement logging logic here
|
||||
puts "Client at #{req.headers['REMOTE_ADDR']} wanted to access something /important!"
|
||||
puts "Client at #{req.headers['remote-addr']} wanted to access something /important!"
|
||||
end
|
||||
get "answer" do
|
||||
header "content-type", "application/json"
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Hyde
|
||||
module DSL
|
||||
# Methods shared by probes, preprocessors and filters.
|
||||
module CommonMethods
|
||||
# Stop execution and generate a boilerplate response with the given code
|
||||
# @param errorcode [Integer]
|
||||
# @param backtrace [Array(String), nil]
|
||||
# @raise [UncaughtThrowError] throws :finish to return back to Server
|
||||
def die(errorcode, backtrace: nil)
|
||||
throw :finish, [errorcode].append(
|
||||
*(@origin.properties["handle.#{errorcode}"] or
|
||||
@origin.properties["handle.default"]).call(
|
||||
errorcode,
|
||||
backtrace: backtrace
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
# Bounce request to the next handler
|
||||
# @raise [UncaughtThrowError] throws :break to get out of the callback
|
||||
def bounce
|
||||
throw :break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,6 +1,8 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require_relative '../response'
|
||||
require_relative '../util/multipart'
|
||||
require_relative '../util/header'
|
||||
|
||||
module Hyde
|
||||
module DSL
|
||||
|
@ -12,31 +14,11 @@ module Hyde
|
|||
@origin.request
|
||||
end
|
||||
|
||||
# Stop execution and generate a boilerplate response with the given code
|
||||
# @param errorcode [Integer]
|
||||
# @param backtrace [Array(String), nil]
|
||||
# @raise [UncaughtThrowError] throws :finish to return back to Server
|
||||
def die(errorcode, backtrace: nil)
|
||||
throw :finish, [errorcode].append(
|
||||
*(@origin.properties["handle.#{errorcode}"] or
|
||||
@origin.properties["handle.default"]).call(
|
||||
errorcode,
|
||||
backtrace: backtrace
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
# Bounce request to the next handler
|
||||
# @raise [UncaughtThrowError] throws :break to get out of the callback
|
||||
def bounce
|
||||
throw :break
|
||||
end
|
||||
|
||||
# Set response status (generate response if one doesn't exist yet)
|
||||
# @param status [Integer] http status code
|
||||
def status(status)
|
||||
@response = (@response or Hyde::Response.new)
|
||||
@response.status = status
|
||||
@origin.response = (@origin.response or Hyde::Response.new)
|
||||
@origin.response.status = status
|
||||
end
|
||||
|
||||
alias code status
|
||||
|
@ -79,6 +61,27 @@ module Hyde
|
|||
|
||||
@origin.response.delete_header(key, value)
|
||||
end
|
||||
|
||||
# Checks if current request has multipart/form-data associated with it
|
||||
# @return [Boolean]
|
||||
def form?
|
||||
value, opts = Hyde::Util.parse_value(request.headers["content-type"])
|
||||
if value == "multipart/form-data" and
|
||||
opts["boundary"]
|
||||
true
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
# Returns formdata
|
||||
# @return [Hash{String=>(String,Hyde::Util::FormPart)}]
|
||||
def form
|
||||
_, opts = Hyde::Util.parse_value(request.headers["content-type"])
|
||||
Hyde::Util::MultipartParser.new(
|
||||
request.input, opts["boundary"]
|
||||
).to_h
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,10 +4,20 @@ require_relative 'pattern_matching'
|
|||
require_relative 'node'
|
||||
require_relative 'dsl/path_constructors'
|
||||
require_relative 'dsl/path_methods'
|
||||
require_relative 'dsl/common_methods'
|
||||
require_relative 'util/lookup'
|
||||
|
||||
module Hyde
|
||||
# Protected interface that provides DSL context for setup block.
|
||||
# Binding that provides execution context for filters and preprocessors.
|
||||
class ProcessorBinding
|
||||
include Hyde::DSL::CommonMethods
|
||||
|
||||
def initialize(path)
|
||||
@origin = path
|
||||
end
|
||||
end
|
||||
|
||||
# Binding that provides execution context for path setup block.
|
||||
class PathBinding
|
||||
include Hyde::DSL::PathConstructors
|
||||
include Hyde::DSL::PathMethods
|
||||
|
@ -19,6 +29,7 @@ module Hyde
|
|||
|
||||
# Primary building block of request navigation.
|
||||
class Path < Hyde::Node
|
||||
ProcBinding = Hyde::ProcessorBinding
|
||||
Binding = Hyde::PathBinding
|
||||
|
||||
# @param path [Object] Object to generate {Hyde::Pattern} from
|
||||
|
@ -32,9 +43,10 @@ module Hyde
|
|||
@preprocessors = []
|
||||
@postprocessors = []
|
||||
@filters = []
|
||||
|
||||
binding = Binding.new(self)
|
||||
# Bindings setup
|
||||
binding = self.class::Binding.new(self)
|
||||
binding.instance_exec(&setup)
|
||||
@procbinding = self.class::ProcBinding.new(self)
|
||||
end
|
||||
|
||||
# Method callback on successful request navigation.
|
||||
|
@ -92,7 +104,7 @@ module Hyde
|
|||
# @return [Boolean] true if request passed all filters
|
||||
def run_filters(request)
|
||||
@filters.each do |filter|
|
||||
return false if filter.call(request).is_a? FalseClass
|
||||
return false unless @procbinding.instance_exec(request, &filter)
|
||||
end
|
||||
true
|
||||
end
|
||||
|
@ -101,7 +113,7 @@ module Hyde
|
|||
# @param request [Hyde::Request]
|
||||
def run_preprocessors(request)
|
||||
@preprocessors.each do |preproc|
|
||||
preproc.call(request)
|
||||
@procbinding.instance_exec(request, &preproc)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -1,12 +1,16 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require_relative "../dsl/probe_methods"
|
||||
require_relative "../dsl/common_methods"
|
||||
|
||||
module Hyde
|
||||
# Binding that provides execution context for Probes.
|
||||
class ProbeBinding
|
||||
include Hyde::DSL::ProbeMethods
|
||||
include Hyde::DSL::CommonMethods
|
||||
|
||||
def initialize(origin)
|
||||
@origin = origin
|
||||
end
|
||||
include Hyde::DSL::ProbeMethods
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'cgi/escape'
|
||||
|
||||
module Hyde
|
||||
module Util
|
||||
# HTTP status codes and descriptions
|
||||
|
@ -40,6 +42,7 @@ module Hyde
|
|||
415 => 'Unsupported Media Type',
|
||||
416 => 'Request Range Not Satisfiable',
|
||||
417 => 'Expectation Failed',
|
||||
418 => "I'm a teapot",
|
||||
422 => 'Unprocessable Entity',
|
||||
423 => 'Locked',
|
||||
424 => 'Failed Dependency',
|
||||
|
@ -65,11 +68,14 @@ module Hyde
|
|||
# @param str [String]
|
||||
# @return [String]
|
||||
def self.escape_html(str)
|
||||
str.gsub("&", "&")
|
||||
.gsub("<", "<")
|
||||
.gsub(">", ">")
|
||||
.gsub("\"", """)
|
||||
.gsub("'", "'")
|
||||
CGI.escapeHTML(str)
|
||||
end
|
||||
|
||||
# Return string with unescaped HTML entities.
|
||||
# @param str [String]
|
||||
# @return [String]
|
||||
def self.unescape_html(str)
|
||||
CGI.unescapeHTML(str)
|
||||
end
|
||||
|
||||
# rubocop:disable Metrics/MethodLength
|
||||
|
|
|
@ -5,6 +5,7 @@ require_relative 'sorting'
|
|||
|
||||
module Hyde
|
||||
module Util
|
||||
# TODO: encoding support????
|
||||
# Query string parser
|
||||
class Query
|
||||
include Hyde::Util::ParserCommon
|
||||
|
@ -16,13 +17,13 @@ module Hyde
|
|||
# Shallow query parser (does not do PHP-like array keys)
|
||||
# @return [Hash]
|
||||
def parse_shallow
|
||||
URI.decode_www_form(@query, Encoding::UTF_8)
|
||||
URI.decode_www_form(@query)
|
||||
.sort_by { |array| array[0] }
|
||||
.to_h
|
||||
end
|
||||
|
||||
# Better(tm) query parser with
|
||||
# Returns a hash with arrays
|
||||
# Better(tm) query parser.
|
||||
# Returns a hash with arrays.
|
||||
# Key semantics:
|
||||
#
|
||||
# - `key=value` creates a key value pair
|
||||
|
@ -30,10 +31,10 @@ module Hyde
|
|||
# - `key[index]=value` sets `value` at `index` of array named `key`
|
||||
# @return [Hash]
|
||||
def parse
|
||||
construct_deep_hash(URI.decode_www_form(@query, Encoding::UTF_8))
|
||||
construct_deep_hash(URI.decode_www_form(@query))
|
||||
end
|
||||
|
||||
# Get key from query
|
||||
# Get key from query.
|
||||
# @param key [String]
|
||||
# @return [String,Array]
|
||||
def [](key)
|
||||
|
|
Loading…
Reference in New Issue