From 0d517cda5fb257aa04160615b8102896d0c6dba0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mislav=20Marohnic=CC=81?= Date: Thu, 29 Dec 2011 02:01:05 +0100 Subject: [PATCH] remove Rack dependency --- faraday.gemspec | 1 - lib/faraday/adapter/test.rb | 6 +- lib/faraday/utils.rb | 140 +++++++++++++++++++++++++++++--- test/request_middleware_test.rb | 3 +- 4 files changed, 134 insertions(+), 16 deletions(-) diff --git a/faraday.gemspec b/faraday.gemspec index 32fb83d4..3b43ade2 100644 --- a/faraday.gemspec +++ b/faraday.gemspec @@ -34,7 +34,6 @@ Gem::Specification.new do |s| s.add_dependency 'addressable', '~> 2.2' s.add_dependency 'multipart-post', '~> 1.1' - s.add_dependency 'rack', '~> 1.1' s.add_development_dependency 'rake' s.add_development_dependency 'test-unit' s.add_development_dependency 'webmock' diff --git a/lib/faraday/adapter/test.rb b/lib/faraday/adapter/test.rb index faaa4a1e..9d1d9bc2 100644 --- a/lib/faraday/adapter/test.rb +++ b/lib/faraday/adapter/test.rb @@ -99,7 +99,7 @@ module Faraday def initialize(full, body, block) path, query = full.split('?') params = query ? - Rack::Utils.parse_nested_query(query) : + Faraday::Utils.parse_nested_query(query) : {} super path, params, body, block end @@ -107,7 +107,7 @@ module Faraday def matches?(request_uri, request_body) request_path, request_query = request_uri.split('?') request_params = request_query ? - Rack::Utils.parse_nested_query(request_query) : + Faraday::Utils.parse_nested_query(request_query) : {} request_path == path && params_match?(request_params) && @@ -141,7 +141,7 @@ module Faraday if stub = stubs.match(env[:method], normalized_path, env[:body]) env[:params] = (query = env[:url].query) ? - Rack::Utils.parse_nested_query(query) : + Faraday::Utils.parse_nested_query(query) : {} status, headers, body = stub.block.call(env) save_response(env, status, body, headers) diff --git a/lib/faraday/utils.rb b/lib/faraday/utils.rb index 59ec06cd..a4c86a0b 100644 --- a/lib/faraday/utils.rb +++ b/lib/faraday/utils.rb @@ -1,13 +1,17 @@ -require 'rack/utils' +require 'uri' module Faraday module Utils - include Rack::Utils - - extend Rack::Utils extend self - class Headers < HeaderHash + # Adapted from Rack::Utils::HeaderHash + class Headers < ::Hash + def initialize(hash={}) + super() + @names = {} + hash.each { |k, v| self[k] = v } + end + # symbol -> string mapper + cache KeyMap = Hash.new do |map, key| map[key] = if key.respond_to?(:to_str) then key @@ -20,17 +24,45 @@ module Faraday KeyMap[:etag] = "ETag" def [](k) - super(KeyMap[k]) + k = KeyMap[k] + super(k) || super(@names[k.downcase]) end def []=(k, v) + k = KeyMap[k] + @names[k.downcase] = k # join multiple values with a comma v = v.to_ary.join(', ') if v.respond_to? :to_ary - super(KeyMap[k], v) + super k, v end + def 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 alias_method :update, :merge! + def merge(other) + hash = dup + hash.merge! other + end + + def replace(other) + clear + other.each { |k, v| self[k] = v } + self + end + + def to_hash() ::Hash.new.update(self) end + def parse(header_string) return unless header_string && !header_string.empty? header_string.split(/\r\n/). @@ -102,10 +134,18 @@ module Faraday end end - # Make Rack::Utils methods public. - public :build_query, :parse_query + # Copied from Rack + def build_query(params) + params.map { |k, v| + if v.class == Array + build_query(v.map { |x| [k, x] }) + else + v.nil? ? escape(k) : "#{escape(k)}=#{escape(v)}" + end + }.join("&") + end - # Override Rack's version since it doesn't handle non-String values + # Rack's version modified to handle non-String values def build_nested_query(value, prefix = nil) case value when Array @@ -130,6 +170,86 @@ module Faraday end end + if ''.respond_to?(:bytesize) + def bytesize(string) string.bytesize end + else + def bytesize(string) string.size end + 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 + + DEFAULT_SEP = /[&;] */n + + # Adapted from Rack + def parse_query(qs) + params = {} + + (qs || '').split(DEFAULT_SEP).each do |p| + k, v = p.split('=', 2).map { |x| unescape(x) } + + if cur = params[k] + if cur.class == Array then params[k] << v + else params[k] = [cur, v] + end + else + params[k] = v + end + end + params + end + + def parse_nested_query(qs) + params = {} + + (qs || '').split(DEFAULT_SEP).each do |p| + k, v = p.split('=', 2).map { |s| unescape(s) } + normalize_params(params, k, v) + end + params + end + + # Stolen from Rack + def normalize_params(params, name, v = nil) + name =~ %r(\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 =~ %r(^\[\]\[([^\[\]]+)\]$) || after =~ %r(^\[\](.+)$) + 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 + # Receives a URL and returns just the path with the query string sorted. def normalize_path(url) (url.path != "" ? url.path : "/") + diff --git a/test/request_middleware_test.rb b/test/request_middleware_test.rb index 4439e6e2..3cf7a524 100644 --- a/test/request_middleware_test.rb +++ b/test/request_middleware_test.rb @@ -1,5 +1,4 @@ require File.expand_path(File.join(File.dirname(__FILE__), 'helper')) -require 'rack/utils' Faraday::CompositeReadIO.send :attr_reader, :ios @@ -89,7 +88,7 @@ class RequestMiddlewareTest < Faraday::TestCase response = @conn.post('/echo', { :user => {:name => 'Mislav', :web => 'mislav.net'} }) assert_equal 'application/x-www-form-urlencoded', response.headers['Content-Type'] expected = { 'user' => {'name' => 'Mislav', 'web' => 'mislav.net'} } - assert_equal expected, Rack::Utils.parse_nested_query(response.body) + assert_equal expected, Faraday::Utils.parse_nested_query(response.body) end def test_multipart