mirror of
https://github.com/puma/puma.git
synced 2022-11-09 13:48:40 -05:00
88e51fb08e
Reduces runtime allocation by freezing string literals by default. We could also remove a ton of manual `.freeze` calls, however the ruby supported version is 2.2 and the magic comment only targets 2.3+.
129 lines
3 KiB
Ruby
129 lines
3 KiB
Ruby
# frozen_string_literal: true
|
|
major, minor, patch = RUBY_VERSION.split('.').map { |v| v.to_i }
|
|
|
|
if major == 1 && minor == 9 && patch == 3 && RUBY_PATCHLEVEL < 125
|
|
require 'puma/rack/backports/uri/common_193'
|
|
else
|
|
require 'uri/common'
|
|
end
|
|
|
|
module Puma
|
|
module Util
|
|
module_function
|
|
|
|
def pipe
|
|
IO.pipe
|
|
end
|
|
|
|
# Unescapes a URI escaped string with +encoding+. +encoding+ will be the
|
|
# target encoding of the string returned, and it defaults to UTF-8
|
|
if defined?(::Encoding)
|
|
def unescape(s, encoding = Encoding::UTF_8)
|
|
URI.decode_www_form_component(s, encoding)
|
|
end
|
|
else
|
|
def unescape(s, encoding = nil)
|
|
URI.decode_www_form_component(s, encoding)
|
|
end
|
|
end
|
|
module_function :unescape
|
|
|
|
DEFAULT_SEP = /[&;] */n
|
|
|
|
# Stolen from Mongrel, with some small modifications:
|
|
# Parses a query string by breaking it up at the '&'
|
|
# and ';' characters. You can also use this to parse
|
|
# cookies by changing the characters used in the second
|
|
# parameter (which defaults to '&;').
|
|
def parse_query(qs, d = nil, &unescaper)
|
|
unescaper ||= method(:unescape)
|
|
|
|
params = {}
|
|
|
|
(qs || '').split(d ? /[#{d}] */n : DEFAULT_SEP).each do |p|
|
|
next if p.empty?
|
|
k, v = p.split('=', 2).map(&unescaper)
|
|
|
|
if cur = params[k]
|
|
if cur.class == Array
|
|
params[k] << v
|
|
else
|
|
params[k] = [cur, v]
|
|
end
|
|
else
|
|
params[k] = v
|
|
end
|
|
end
|
|
|
|
return params
|
|
end
|
|
|
|
# A case-insensitive Hash that preserves the original case of a
|
|
# header when set.
|
|
class HeaderHash < Hash
|
|
def self.new(hash={})
|
|
HeaderHash === hash ? hash : super(hash)
|
|
end
|
|
|
|
def initialize(hash={})
|
|
super()
|
|
@names = {}
|
|
hash.each { |k, v| self[k] = v }
|
|
end
|
|
|
|
def each
|
|
super do |k, v|
|
|
yield(k, v.respond_to?(:to_ary) ? v.to_ary.join("\n") : v)
|
|
end
|
|
end
|
|
|
|
def to_hash
|
|
hash = {}
|
|
each { |k,v| hash[k] = v }
|
|
hash
|
|
end
|
|
|
|
def [](k)
|
|
super(k) || super(@names[k.downcase])
|
|
end
|
|
|
|
def []=(k, v)
|
|
canonical = k.downcase
|
|
delete k if @names[canonical] && @names[canonical] != k # .delete is expensive, don't invoke it unless necessary
|
|
@names[k] = @names[canonical] = k
|
|
super k, v
|
|
end
|
|
|
|
def delete(k)
|
|
canonical = k.downcase
|
|
result = super @names.delete(canonical)
|
|
@names.delete_if { |name,| name.downcase == canonical }
|
|
result
|
|
end
|
|
|
|
def include?(k)
|
|
@names.include?(k) || @names.include?(k.downcase)
|
|
end
|
|
|
|
alias_method :has_key?, :include?
|
|
alias_method :member?, :include?
|
|
alias_method :key?, :include?
|
|
|
|
def merge!(other)
|
|
other.each { |k, v| self[k] = v }
|
|
self
|
|
end
|
|
|
|
def merge(other)
|
|
hash = dup
|
|
hash.merge! other
|
|
end
|
|
|
|
def replace(other)
|
|
clear
|
|
other.each { |k, v| self[k] = v }
|
|
self
|
|
end
|
|
end
|
|
end
|
|
end
|