module WEBrick::HTTPUtils
HTTPUtils
provides utility methods for working with the HTTP protocol.
This module is generally used internally by WEBrick
Constants
- DefaultMimeTypes
Default mime types
Public Class Methods
Removes quotes and escapes from str
# File lib/webrick/httputils.rb, line 222 def dequote(str) ret = (/\A"(.*)"\Z/ =~ str) ? $1 : str.dup ret.gsub!(/\\(.)/, "\\1") ret end
Loads Apache-compatible mime.types in file
.
# File lib/webrick/httputils.rb, line 111 def load_mime_types(file) # note: +file+ may be a "| command" for now; some people may # rely on this, but currently we do not use this method by default. open(file){ |io| hash = Hash.new io.each{ |line| next if /^#/ =~ line line.chomp! mimetype, ext0 = line.split(/\s+/, 2) next unless ext0 next if ext0.empty? ext0.split(/\s+/).each{ |ext| hash[ext] = mimetype } } hash } end
Returns the mime type of filename
from the list in mime_tab
. If no mime type was found application/octet-stream is returned.
# File lib/webrick/httputils.rb, line 133 def mime_type(filename, mime_tab) suffix1 = (/\.(\w+)$/ =~ filename && $1.downcase) suffix2 = (/\.(\w+)\.[\w\-]+$/ =~ filename && $1.downcase) mime_tab[suffix1] || mime_tab[suffix2] || "application/octet-stream" end
Normalizes a request path. Raises an exception if the path cannot be normalized.
# File lib/webrick/httputils.rb, line 31 def normalize_path(path) raise "abnormal path `#{path}'" if path[0] != ?/ ret = path.dup ret.gsub!(%r{/+}o, '/') # // => / while ret.sub!(%r'/\.(?:/|\Z)', '/'); end # /. => / while ret.sub!(%r'/(?!\.\./)[^/]+/\.\.(?:/|\Z)', '/'); end # /foo/.. => /foo raise "abnormal path `#{path}'" if %r{/\.\.(/|\Z)} =~ ret ret end
Parses form data in io
with the given boundary
# File lib/webrick/httputils.rb, line 394 def parse_form_data(io, boundary) boundary_regexp = /\A--#{Regexp.quote(boundary)}(--)?#{CRLF}\z/ form_data = Hash.new return form_data unless io data = nil io.each_line{|line| if boundary_regexp =~ line if data data.chop! key = data.name if form_data.has_key?(key) form_data[key].append_data(data) else form_data[key] = data end end data = FormData.new next else if data data << line end end } return form_data end
Parses an HTTP header raw
into a hash of header fields with an Array
of values.
# File lib/webrick/httputils.rb, line 144 def parse_header(raw) header = Hash.new([].freeze) field = nil raw.each_line{|line| case line when /^([A-Za-z0-9!\#$%&'*+\-.^_`|~]+):\s*(.*?)\s*\z/om field, value = $1, $2 field.downcase! header[field] = [] unless header.has_key?(field) header[field] << value when /^\s+(.*?)\s*\z/om value = $1 unless field raise HTTPStatus::BadRequest, "bad header '#{line}'." end header[field][-1] << " " << value else raise HTTPStatus::BadRequest, "bad header '#{line}'." end } header.each{|key, values| values.each(&:strip!) } header end
Parses the query component of a URI
in str
# File lib/webrick/httputils.rb, line 370 def parse_query(str) query = Hash.new if str str.split(/[&;]/).each{|x| next if x.empty? key, val = x.split(/=/,2) key = unescape_form(key) val = unescape_form(val.to_s) val = FormData.new(val) val.name = key if query.has_key?(key) query[key].append_data(val) next end query[key] = val } end query end
Parses q values in value
as used in Accept headers.
# File lib/webrick/httputils.rb, line 201 def parse_qvalues(value) tmp = [] if value parts = value.split(/,\s*/) parts.each {|part| if m = %r{^([^\s,]+?)(?:;\s*q=(\d+(?:\.\d+)?))?$}.match(part) val = m[1] q = (m[2] or 1).to_f tmp.push([val, q]) end } tmp = tmp.sort_by{|val, q| -q} tmp.collect!{|val, q| val} end return tmp end
Parses a Range
header value ranges_specifier
# File lib/webrick/httputils.rb, line 183 def parse_range_header(ranges_specifier) if /^bytes=(.*)/ =~ ranges_specifier byte_range_set = split_header_value($1) byte_range_set.collect{|range_spec| case range_spec when /^(\d+)-(\d+)/ then $1.to_i .. $2.to_i when /^(\d+)-/ then $1.to_i .. -1 when /^-(\d+)/ then -($1.to_i) .. -1 else return nil end } end end
Quotes and escapes quotes in str
# File lib/webrick/httputils.rb, line 232 def quote(str) '"' << str.gsub(/[\\\"]/o, "\\\1") << '"' end
Splits a header value str
according to HTTP specification.
# File lib/webrick/httputils.rb, line 174 def split_header_value(str) str.scan(%r'\G((?:"(?:\\.|[^"])+?"|[^",]+)+) (?:,\s*|\Z)'xn).flatten end
Public Instance Methods
Escapes HTTP reserved and unwise characters in str
# File lib/webrick/httputils.rb, line 466 def escape(str) _escape(str, UNESCAPED) end
Escapes 8 bit characters in str
# File lib/webrick/httputils.rb, line 507 def escape8bit(str) _escape(str, NONASCII) end
Escapes form reserved characters in str
# File lib/webrick/httputils.rb, line 480 def escape_form(str) ret = _escape(str, UNESCAPED_FORM) ret.gsub!(/ /, "+") ret end
Escapes path str
# File lib/webrick/httputils.rb, line 496 def escape_path(str) result = "" str.scan(%r{/([^/]*)}).each{|i| result << "/" << _escape(i[0], UNESCAPED_PCHAR) } return result end
Unescapes HTTP reserved and unwise characters in str
# File lib/webrick/httputils.rb, line 473 def unescape(str) _unescape(str, ESCAPED) end
Unescapes form reserved characters in str
# File lib/webrick/httputils.rb, line 489 def unescape_form(str) _unescape(str.gsub(/\+/, " "), ESCAPED) end
Private Instance Methods
Removes quotes and escapes from str
# File lib/webrick/httputils.rb, line 222 def dequote(str) ret = (/\A"(.*)"\Z/ =~ str) ? $1 : str.dup ret.gsub!(/\\(.)/, "\\1") ret end
Loads Apache-compatible mime.types in file
.
# File lib/webrick/httputils.rb, line 111 def load_mime_types(file) # note: +file+ may be a "| command" for now; some people may # rely on this, but currently we do not use this method by default. open(file){ |io| hash = Hash.new io.each{ |line| next if /^#/ =~ line line.chomp! mimetype, ext0 = line.split(/\s+/, 2) next unless ext0 next if ext0.empty? ext0.split(/\s+/).each{ |ext| hash[ext] = mimetype } } hash } end
Returns the mime type of filename
from the list in mime_tab
. If no mime type was found application/octet-stream is returned.
# File lib/webrick/httputils.rb, line 133 def mime_type(filename, mime_tab) suffix1 = (/\.(\w+)$/ =~ filename && $1.downcase) suffix2 = (/\.(\w+)\.[\w\-]+$/ =~ filename && $1.downcase) mime_tab[suffix1] || mime_tab[suffix2] || "application/octet-stream" end
Normalizes a request path. Raises an exception if the path cannot be normalized.
# File lib/webrick/httputils.rb, line 31 def normalize_path(path) raise "abnormal path `#{path}'" if path[0] != ?/ ret = path.dup ret.gsub!(%r{/+}o, '/') # // => / while ret.sub!(%r'/\.(?:/|\Z)', '/'); end # /. => / while ret.sub!(%r'/(?!\.\./)[^/]+/\.\.(?:/|\Z)', '/'); end # /foo/.. => /foo raise "abnormal path `#{path}'" if %r{/\.\.(/|\Z)} =~ ret ret end
Parses form data in io
with the given boundary
# File lib/webrick/httputils.rb, line 394 def parse_form_data(io, boundary) boundary_regexp = /\A--#{Regexp.quote(boundary)}(--)?#{CRLF}\z/ form_data = Hash.new return form_data unless io data = nil io.each_line{|line| if boundary_regexp =~ line if data data.chop! key = data.name if form_data.has_key?(key) form_data[key].append_data(data) else form_data[key] = data end end data = FormData.new next else if data data << line end end } return form_data end
Parses an HTTP header raw
into a hash of header fields with an Array
of values.
# File lib/webrick/httputils.rb, line 144 def parse_header(raw) header = Hash.new([].freeze) field = nil raw.each_line{|line| case line when /^([A-Za-z0-9!\#$%&'*+\-.^_`|~]+):\s*(.*?)\s*\z/om field, value = $1, $2 field.downcase! header[field] = [] unless header.has_key?(field) header[field] << value when /^\s+(.*?)\s*\z/om value = $1 unless field raise HTTPStatus::BadRequest, "bad header '#{line}'." end header[field][-1] << " " << value else raise HTTPStatus::BadRequest, "bad header '#{line}'." end } header.each{|key, values| values.each(&:strip!) } header end
Parses the query component of a URI
in str
# File lib/webrick/httputils.rb, line 370 def parse_query(str) query = Hash.new if str str.split(/[&;]/).each{|x| next if x.empty? key, val = x.split(/=/,2) key = unescape_form(key) val = unescape_form(val.to_s) val = FormData.new(val) val.name = key if query.has_key?(key) query[key].append_data(val) next end query[key] = val } end query end
Parses q values in value
as used in Accept headers.
# File lib/webrick/httputils.rb, line 201 def parse_qvalues(value) tmp = [] if value parts = value.split(/,\s*/) parts.each {|part| if m = %r{^([^\s,]+?)(?:;\s*q=(\d+(?:\.\d+)?))?$}.match(part) val = m[1] q = (m[2] or 1).to_f tmp.push([val, q]) end } tmp = tmp.sort_by{|val, q| -q} tmp.collect!{|val, q| val} end return tmp end
Parses a Range
header value ranges_specifier
# File lib/webrick/httputils.rb, line 183 def parse_range_header(ranges_specifier) if /^bytes=(.*)/ =~ ranges_specifier byte_range_set = split_header_value($1) byte_range_set.collect{|range_spec| case range_spec when /^(\d+)-(\d+)/ then $1.to_i .. $2.to_i when /^(\d+)-/ then $1.to_i .. -1 when /^-(\d+)/ then -($1.to_i) .. -1 else return nil end } end end
Quotes and escapes quotes in str
# File lib/webrick/httputils.rb, line 232 def quote(str) '"' << str.gsub(/[\\\"]/o, "\\\1") << '"' end
Splits a header value str
according to HTTP specification.
# File lib/webrick/httputils.rb, line 174 def split_header_value(str) str.scan(%r'\G((?:"(?:\\.|[^"])+?"|[^",]+)+) (?:,\s*|\Z)'xn).flatten end