module Merb::Parse
Constants
- CONTENT_TYPE_REGEX
- CRLF
- EOL
- FILENAME_REGEX
- NAME_REGEX
Public Class Methods
Parameters¶ ↑
- request<IO>
-
The raw request.
- boundary<String>
-
The boundary string.
- content_length<Fixnum>
-
The length of the content.
Raises¶ ↑
- ControllerExceptions::MultiPartParseError
-
Failed to parse request.
Returns¶ ↑
- Hash
-
The parsed request.
:api: plugin
# File lib/merb-core/dispatch/request_parsers.rb, line 49 def self.multipart(request, boundary, content_length) boundary = "--#{boundary}" paramhsh = {} buf = "" input = request input.binmode if defined? input.binmode boundary_size = boundary.size + EOL.size bufsize = 16384 content_length -= boundary_size key_memo = [] # status is boundary delimiter line status = input.read(boundary_size) return {} if status == nil || status.empty? raise ControllerExceptions::MultiPartParseError, "bad content body:\n'#{status}' should == '#{boundary + EOL}'" unless status == boundary + EOL rx = /(?:#{EOL})?#{Regexp.quote(boundary)}(#{EOL}|--)/n loop { head = nil body = '' filename = content_type = name = nil read_size = 0 until head && buf =~ rx i = buf.index("\r\n\r\n") if( i == nil && read_size == 0 && content_length == 0 ) content_length = -1 break end if !head && i head = buf.slice!(0, i+2) # First \r\n buf.slice!(0, 2) # Second \r\n # String#[] with 2nd arg here is returning # a group from match data filename = head[FILENAME_REGEX, 1] content_type = head[CONTENT_TYPE_REGEX, 1] name = head[NAME_REGEX, 1] if filename && !filename.empty? body = Tempfile.new(:Merb) body.binmode if defined? body.binmode end next end # Save the read body part. if head && (boundary_size+4 < buf.size) body << buf.slice!(0, buf.size - (boundary_size+4)) end read_size = bufsize < content_length ? bufsize : content_length if( read_size > 0 ) c = input.read(read_size) raise ControllerExceptions::MultiPartParseError, "bad content body" if c.nil? || c.empty? buf << c content_length -= c.size end end # Save the rest. if i = buf.index(rx) # correct value of i for some edge cases if (i > 2) && (j = buf.index(rx, i-2)) && (j < i) i = j end body << buf.slice!(0, i) buf.slice!(0, boundary_size+2) content_length = -1 if $1 == "--" end if filename && !filename.empty? body.rewind data = { :filename => File.basename(filename), :content_type => content_type, :tempfile => body, :size => File.size(body.path) } else data = body end unless key_memo.include?(name) && name !~ /\[\]/ paramhsh = normalize_params(paramhsh,name,data) end # Prevent from double processing files but process other params key_memo << name if filename && !filename.empty? break if buf.empty? || content_length == -1 } paramhsh end
Parameters¶ ↑
- value<Array, Hash, Dictionary ~to_s>
-
The value for the query string.
- prefix<~to_s>
-
The prefix to add to the query string keys.
Returns¶ ↑
- String
-
The query string.
Alternatives¶ ↑
If the value is a string, the prefix will be used as the key.
Examples¶ ↑
params_to_query_string(10, "page") # => "page=10" params_to_query_string({ :page => 10, :word => "ruby" }) # => "page=10&word=ruby" params_to_query_string({ :page => 10, :word => "ruby" }, "search") # => "search[page]=10&search[word]=ruby" params_to_query_string([ "ice-cream", "cake" ], "shopping_list") # => "shopping_list[]=ice-cream&shopping_list[]=cake"
:api: plugin
# File lib/merb-core/dispatch/request_parsers.rb, line 165 def self.params_to_query_string(value, prefix = nil) case value when Array value.map { |v| params_to_query_string(v, "#{prefix}[]") } * "&" when Hash, Dictionary value.map { |k, v| params_to_query_string(v, prefix ? "#{prefix}[#{escape(k)}]" : escape(k)) } * "&" else "#{prefix}=#{escape(value)}" end end
Parameters¶ ↑
- query_string<String>
-
The query string.
- delimiter<String>
-
The query string divider. Defaults to “&”.
- preserve_order<Boolean>
-
Preserve order of args. Defaults to false.
Returns¶ ↑
- Mash
-
The parsed query string (Dictionary if preserve_order is set).
Examples¶ ↑
Merb::Parse.query("bar=nik&post[body]=heya") # => { :bar => "nik", :post => { :body => "heya" } }
:api: plugin
# File lib/merb-core/dispatch/request_parsers.rb, line 17 def self.query(query_string, delimiter = '&;', preserve_order = false) query = preserve_order ? Dictionary.new : {} for pair in (query_string || '').split(/[#{delimiter}] */n) key, value = unescape(pair).split('=',2) next if key.nil? if key.include?('[') normalize_params(query, key, value) else query[key] = value end end preserve_order ? query : query.to_mash end
Parameter¶ ↑
- s<String>
-
String to URL unescape.
- encoding<String>
-
Encoding which we force to return. Only for Ruby 1.9. If encoding is not passed it defaults to Encoding.default_internal. When this is nil (default) no encoding forcing is done.
returns¶ ↑
- String
-
The unescaped string.
:api: public
# File lib/merb-core/dispatch/request_parsers.rb, line 204 def self.unescape(s, encoding = nil) s = s.tr('+', ' ').gsub(/((?:%[0-9a-fA-F]{2})+)/n){ [$1.delete('%')].pack('H*') } if RUBY_VERSION >= '1.9' encoding ||= Encoding.default_internal s.force_encoding(encoding) if encoding end s end
Private Class Methods
Converts a query string snippet to a hash and adds it to existing parameters.
Parameters¶ ↑
- parms<Hash>
-
Parameters to add the normalized parameters to.
- name<String>
-
The key of the parameter to normalize.
- val<String>
-
The value of the parameter.
Returns¶ ↑
- Hash
-
Normalized parameters
:api: private
# File lib/merb-core/dispatch/request_parsers.rb, line 240 def self.normalize_params(parms, name, val=nil) name =~ %r([\[\]]*([^\[\]]+)\]*) key = $1 || '' after = $' || '' if after == "" parms[key] = val elsif after == "[]" (parms[key] ||= []) << val elsif after =~ %r(^\[\]\[([^\[\]]+)\]$) child_key = $1 parms[key] ||= [] if parms[key].last.is_a?(Hash) && !parms[key].last.key?(child_key) parms[key].last.update(child_key => val) else parms[key] << { child_key => val } end else parms[key] ||= {} parms[key] = normalize_params(parms[key], after, val) end parms end