Module: Rack::Utils

### Home Classes Methods

### In Files

- lib/rack/utils.rb

### Namespace

- MODULE Rack::Utils::Multipart
- CLASS Rack::Utils::Context
- CLASS Rack::Utils::HeaderHash

### Methods

- ::build_nested_query
- ::build_query
- ::bytesize
- ::delete_cookie_header!
- ::escape
- ::escape_html
- ::normalize_params
- ::parse_nested_query
- ::parse_query
- ::rfc2822
- ::select_best_encoding
- ::set_cookie_header!
- ::status_code
- ::unescape

### Files

- KNOWN-ISSUES
- README
- SPEC

### Class/Module Index

Quicksearch

- Rack
- Rack::Auth
- Rack::Auth::AbstractHandler
- Rack::Auth::AbstractRequest
- Rack::Auth::Basic
- Rack::Auth::Basic::Request
- Rack::Auth::Digest
- Rack::Auth::Digest::MD5
- Rack::Auth::Digest::Nonce
- Rack::Auth::Digest::Params
- Rack::Auth::Digest::Request
- Rack::Builder
- Rack::Cascade
- Rack::Chunked
- Rack::CommonLogger
- Rack::ConditionalGet
- Rack::Config
- Rack::ContentLength
- Rack::ContentType
- Rack::Deflater
- Rack::Deflater::DeflateStream
- Rack::Deflater::GzipStream
- Rack::Directory
- Rack::ETag
- Rack::File
- Rack::ForwardRequest
- Rack::Handler
- Rack::Handler::CGI
- Rack::Handler::EventedMongrel
- Rack::Handler::FastCGI
- Rack::Handler::LSWS
- Rack::Handler::Mongrel
- Rack::Handler::SCGI
- Rack::Handler::SwiftipliedMongrel
- Rack::Handler::Thin
- Rack::Handler::WEBrick
- Rack::Head
- Rack::Lint
- Rack::Lobster
- Rack::Lock
- Rack::Logger
- Rack::MethodOverride
- Rack::Mime
- Rack::MockRequest
- Rack::MockRequest::FatalWarner
- Rack::MockRequest::FatalWarning
- Rack::MockResponse
- Rack::NullLogger
- Rack::Recursive
- Rack::Reloader
- Rack::Reloader::Stat
- Rack::Request
- Rack::Response
- Rack::Response::Helpers
- Rack::RewindableInput
- Rack::RewindableInput::Tempfile
- Rack::Runtime
- Rack::Sendfile
- Rack::Server
- Rack::Server::Options
- Rack::Session
- Rack::Session::Abstract
- Rack::Session::Abstract::ID
- Rack::Session::Cookie
- Rack::Session::Memcache
- Rack::Session::Pool
- Rack::ShowExceptions
- Rack::ShowStatus
- Rack::Static
- Rack::URLMap
- Rack::Utils
- Rack::Utils::Context
- Rack::Utils::HeaderHash
- Rack::Utils::Multipart
- Rack::Utils::Multipart::UploadedFile
- FCGI
- FCGI::Stream

No matching classes.

# Rack::Utils

Rack::Utils contains a grab-bag of useful methods for writing web applications adopted from all kinds of Ruby libraries.

### Constants

DEFAULT_SEP
ESCAPE_HTML
ESCAPE_HTML_PATTERN
HTTP_STATUS_CODES

  Every standard HTTP code mapped to the appropriate message. Generated with:

      curl -s http://www.iana.org/assignments/http-status-codes | \
        ruby -ane 'm = /^(\d{3}) +(\S[^\[(]+)/.match($_) and
                   puts "      #{m[1]}  => \x27#{m[2].strip}x27,"'

STATUS_WITH_NO_ENTITY_BODY

  Responses with HTTP status codes that should not have an entity body

SYMBOL_TO_STATUS_CODE

### Public Class Methods

build_nested_query(value, prefix = nil) click to toggle source

    # File lib/rack/utils.rb, line 111
    def build_nested_query(value, prefix = nil)
      case value
      when Array
        value.map { |v|
          build_nested_query(v, "#{prefix}[]")
        }.join("&")
      when Hash
        value.map { |k, v|
          build_nested_query(v, prefix ? "#{prefix}[#{escape(k)}]" : escape(k))
        }.join("&")
      when String
        raise ArgumentError, "value must be a Hash" if prefix.nil?
        "#{prefix}=#{escape(value)}"
      else
        prefix
      end
    end

build_query(params) click to toggle source

    # File lib/rack/utils.rb, line 100
    def build_query(params)
      params.map { |k, v|
        if v.class == Array
          build_query(v.map { |x| [k, x] })
        else
          "#{escape(k)}=#{escape(v)}"
        end
      }.join("&")
    end

bytesize(string) click to toggle source

    # File lib/rack/utils.rb, line 237
    def bytesize(string)
      string.bytesize
    end

delete_cookie_header!(header, key, value = {}) click to toggle source

    # File lib/rack/utils.rb, line 206
    def delete_cookie_header!(header, key, value = {})
      case header["Set-Cookie"]
      when nil, ''
        cookies = []
      when String
        cookies = header["Set-Cookie"].split("\n")
      when Array
        cookies = header["Set-Cookie"]
      end

      cookies.reject! { |cookie|
        if value[:domain]
          cookie =~ /\A#{escape(key)}=.*domain=#{value[:domain]}/
        else
          cookie =~ /\A#{escape(key)}=/
        end
      }

      header["Set-Cookie"] = cookies.join("\n")

      set_cookie_header!(header, key,
                 {:value => '', :path => nil, :domain => nil,
                   :expires => Time.at(0) }.merge(value))

      nil
    end

escape(s) click to toggle source

Performs URI escaping so that you can construct proper query strings faster. Use this rather than the cgi.rb version since it’s faster. (Stolen from Camping).

    # File lib/rack/utils.rb, line 14
    def escape(s)
      s.to_s.gsub(/([^ a-zA-Z0-9_.-]+)/) {
        '%'+$1.unpack('H2'*bytesize($1)).join('%').upcase
      }.tr(' ', '+')
    end

escape_html(string) click to toggle source

Escape ampersands, brackets and quotes to their HTML/XML entities.

    # File lib/rack/utils.rb, line 140
    def escape_html(string)
      string.to_s.gsub(ESCAPE_HTML_PATTERN){|c| ESCAPE_HTML[c] }
    end

normalize_params(params, name, v = nil) click to toggle source

    # File lib/rack/utils.rb, line 68
    def normalize_params(params, name, v = nil)
      name =~ %(\A[\[\]]*([^\[\]]+)\]*)
      k = $1 || ''
      after = $' || ''

      return if k.empty?

      if after == ""
        params[k] = v
      elsif after == "[]"
        params[k] ||= []
        raise TypeError, "expected Array (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Array)
        params[k] << v
      elsif after =~ %(^\[\]\[([^\[\]]+)\]$) || after =~ %(^\[\](.+)$)
        child_key = $1
        params[k] ||= []
        raise TypeError, "expected Array (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Array)
        if params[k].last.is_a?(Hash) && !params[k].last.key?(child_key)
          normalize_params(params[k].last, child_key, v)
        else
          params[k] << normalize_params({}, child_key, v)
        end
      else
        params[k] ||= {}
        raise TypeError, "expected Hash (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Hash)
        params[k] = normalize_params(params[k], after, v)
      end

      return params
    end

parse_nested_query(qs, d = nil) click to toggle source

    # File lib/rack/utils.rb, line 56
    def parse_nested_query(qs, d = nil)
      params = {}

      (qs || '').split(d ? /[#{d}] */ : DEFAULT_SEP).each do |p|
        k, v = unescape(p).split('=', 2)
        normalize_params(params, k, v)
      end

      return params
    end

parse_query(qs, d = nil) click to toggle source

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 ‘&;’).

    # File lib/rack/utils.rb, line 36
    def parse_query(qs, d = nil)
      params = {}

      (qs || '').split(d ? /[#{d}] */ : DEFAULT_SEP).each do |p|
        k, v = p.split('=', 2).map { |x| unescape(x) }
        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

rfc2822(time) click to toggle source

Modified version of stdlib time.rb Time#rfc2822 to use ‘%d-%b-%Y’ instead of ‘% %b %Y’. It assumes that the time is in GMT to comply to the RFC 2109.

NOTE: I’m not sure the RFC says it requires GMT, but is ambigous enough that I’m certain someone implemented only that option. Do not use %a and %b from Time.strptime, it would use localized names for weekday and month.

    # File lib/rack/utils.rb, line 256
    def rfc2822(time)
      wday = Time::RFC2822_DAY_NAME[time.wday]
      mon = Time::RFC2822_MONTH_NAME[time.mon - 1]
      time.strftime("#{wday}, %d-#{mon}-%Y %T GMT")
    end

select_best_encoding(available_encodings, accept_encoding) click to toggle source

    # File lib/rack/utils.rb, line 145
    def select_best_encoding(available_encodings, accept_encoding)
      # http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html

      expanded_accept_encoding =
        accept_encoding.map { |m, q|
          if m == "*"
            (available_encodings - accept_encoding.map { |m2, _| m2 }).map { |m2| [m2, q] }
          else
            [[m, q]]
          end
        }.inject([]) { |mem, list|
          mem + list
        }

      encoding_candidates = expanded_accept_encoding.sort_by { |_, q| -q }.map { |m, _| m }

      unless encoding_candidates.include?("identity")
        encoding_candidates.push("identity")
      end

      expanded_accept_encoding.find_all { |m, q|
        q == 0.0
      }.each { |m, _|
        encoding_candidates.delete(m)
      }

      return (encoding_candidates & available_encodings)[0]
    end

set_cookie_header!(header, key, value) click to toggle source

    # File lib/rack/utils.rb, line 175
    def set_cookie_header!(header, key, value)
      case value
      when Hash
        domain  = "; domain="  + value[:domain] if value[:domain]
        path    = "; path="    + value[:path]   if value[:path]
        # According to RFC 2109, we need dashes here.
        # N.B.: cgi.rb uses spaces...
        expires = "; expires=" +
          rfc2822(value[:expires].clone.gmtime) if value[:expires]
        secure = "; secure"  if value[:secure]
        httponly = "; HttpOnly" if value[:httponly]
        value = value[:value]
      end
      value = [value] unless Array === value
      cookie = escape(key) + "=" +
        value.map { |v| escape v }.join("&") +
        "#{domain}#{path}#{expires}#{secure}#{httponly}"

      case header["Set-Cookie"]
      when nil, ''
        header["Set-Cookie"] = cookie
      when String
        header["Set-Cookie"] = [header["Set-Cookie"], cookie].join("\n")
      when Array
        header["Set-Cookie"] = (header["Set-Cookie"] + [cookie]).join("\n")
      end

      nil
    end

status_code(status) click to toggle source

    # File lib/rack/utils.rb, line 429
    def status_code(status)
      if status.is_a?(Symbol)
        SYMBOL_TO_STATUS_CODE[status] || 500
      else
        status.to_i
      end
    end

unescape(s) click to toggle source

Unescapes a URI escaped string. (Stolen from Camping).

    # File lib/rack/utils.rb, line 22
    def unescape(s)
      s.tr('+', ' ').gsub(/((?:%[0-9a-fA-F]{2})+)/){
        [$1.delete('%')].pack('H*')
      }
    end

[Validate]

Generated with the Darkfish Rdoc Generator 2.