rest-core 2.0.4 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGES.md +33 -0
- data/Gemfile +1 -1
- data/README.md +1 -1
- data/Rakefile +13 -0
- data/lib/rest-core.rb +2 -0
- data/lib/rest-core/client.rb +22 -13
- data/lib/rest-core/engine/em-http-request.rb +37 -8
- data/lib/rest-core/engine/rest-client.rb +6 -4
- data/lib/rest-core/middleware.rb +24 -3
- data/lib/rest-core/middleware/auth_basic.rb +1 -1
- data/lib/rest-core/middleware/cache.rb +2 -2
- data/lib/rest-core/middleware/default_headers.rb +1 -1
- data/lib/rest-core/middleware/default_payload.rb +1 -1
- data/lib/rest-core/middleware/default_query.rb +1 -1
- data/lib/rest-core/middleware/oauth1_header.rb +3 -13
- data/lib/rest-core/middleware/oauth2_header.rb +1 -1
- data/lib/rest-core/middleware/oauth2_query.rb +1 -1
- data/lib/rest-core/test.rb +48 -0
- data/lib/rest-core/util/payload.rb +162 -0
- data/lib/rest-core/version.rb +1 -1
- data/rest-core.gemspec +14 -7
- data/task/gemgem.rb +7 -6
- data/test/test_auth_basic.rb +7 -5
- data/test/test_cache.rb +6 -0
- data/test/test_client_oauth1.rb +22 -22
- data/test/test_default_payload.rb +38 -0
- data/test/test_default_query.rb +10 -8
- data/test/{test_em_http_request.rb → test_em-http-request.rb} +40 -0
- data/test/test_follow_redirect.rb +9 -12
- data/test/test_json_response.rb +8 -12
- data/test/test_oauth1_header.rb +53 -53
- data/test/test_payload.rb +189 -22
- data/test/test_rest-client.rb +40 -0
- data/test/test_timeout.rb +8 -10
- metadata +25 -9
@@ -0,0 +1,162 @@
|
|
1
|
+
|
2
|
+
# stolen and modified from rest-client
|
3
|
+
|
4
|
+
require 'rest-core/error'
|
5
|
+
|
6
|
+
require 'mime/types'
|
7
|
+
|
8
|
+
require 'stringio'
|
9
|
+
require 'tempfile'
|
10
|
+
|
11
|
+
module RestCore; end
|
12
|
+
module RestCore::Payload
|
13
|
+
include RestCore
|
14
|
+
module_function
|
15
|
+
|
16
|
+
def generate payload
|
17
|
+
if payload.respond_to?(:read)
|
18
|
+
Streamed.new(payload)
|
19
|
+
|
20
|
+
elsif payload.kind_of?(String)
|
21
|
+
StreamedString.new(payload)
|
22
|
+
|
23
|
+
elsif payload.kind_of?(Hash)
|
24
|
+
if Middleware.contain_binary?(payload)
|
25
|
+
Multipart.new(payload)
|
26
|
+
|
27
|
+
else
|
28
|
+
UrlEncoded.new(payload)
|
29
|
+
end
|
30
|
+
|
31
|
+
else
|
32
|
+
raise Error.new("Payload should be either String, Hash, or" \
|
33
|
+
" responding to `read', but: #{payload.inspect}")
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class Streamed
|
38
|
+
def initialize payload
|
39
|
+
@io = payload
|
40
|
+
end
|
41
|
+
|
42
|
+
attr_reader :io
|
43
|
+
alias_method :to_io, :io
|
44
|
+
|
45
|
+
def read bytes=nil
|
46
|
+
io.read(bytes)
|
47
|
+
end
|
48
|
+
|
49
|
+
def headers
|
50
|
+
{'Content-Length' => size.to_s}
|
51
|
+
end
|
52
|
+
|
53
|
+
def size
|
54
|
+
if io.respond_to?(:size)
|
55
|
+
io.size
|
56
|
+
elsif io.respond_to?(:stat)
|
57
|
+
io.stat.size
|
58
|
+
else
|
59
|
+
0
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def close ; io.close unless closed?; end
|
64
|
+
def closed?; io.closed? ; end
|
65
|
+
end
|
66
|
+
|
67
|
+
class StreamedString < Streamed
|
68
|
+
def initialize payload
|
69
|
+
super(StringIO.new(payload))
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
class UrlEncoded < StreamedString
|
74
|
+
def initialize payload
|
75
|
+
super(RestCore::Middleware.percent_encode(payload))
|
76
|
+
end
|
77
|
+
|
78
|
+
def headers
|
79
|
+
super.merge('Content-Type' => 'application/x-www-form-urlencoded')
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
class Multipart < Streamed
|
84
|
+
EOL = "\r\n"
|
85
|
+
|
86
|
+
def initialize payload
|
87
|
+
super(Tempfile.new("rest-core.payload.#{boundary}"))
|
88
|
+
|
89
|
+
io.binmode
|
90
|
+
|
91
|
+
payload.each_with_index do |(k, v), i|
|
92
|
+
if v.kind_of?(Array)
|
93
|
+
v.each{ |vv| part(k, vv) }
|
94
|
+
else
|
95
|
+
part(k, v)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
io.write("--#{boundary}--#{EOL}")
|
99
|
+
io.rewind
|
100
|
+
end
|
101
|
+
|
102
|
+
def part k, v
|
103
|
+
io.write("--#{boundary}#{EOL}Content-Disposition: form-data")
|
104
|
+
io.write("; name=\"#{k}\"") if k
|
105
|
+
if v.respond_to?(:read)
|
106
|
+
part_binary(k, v)
|
107
|
+
else
|
108
|
+
part_plantext(k, v)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def part_plantext k, v
|
113
|
+
io.write("#{EOL}#{EOL}#{v}#{EOL}")
|
114
|
+
end
|
115
|
+
|
116
|
+
def part_binary k, v
|
117
|
+
if v.respond_to?(:original_filename) # Rails
|
118
|
+
io.write("; filename=\"#{v.original_filename}\"#{EOL}")
|
119
|
+
elsif v.respond_to?(:path) # files
|
120
|
+
io.write("; filename=\"#{File.basename(v.path)}\"#{EOL}")
|
121
|
+
else # io
|
122
|
+
io.write("; filename=\"#{k}\"#{EOL}")
|
123
|
+
end
|
124
|
+
|
125
|
+
# supply your own content type for regular files, will you?
|
126
|
+
if v.respond_to?(:content_type) # Rails
|
127
|
+
io.write("Content-Type: #{v.content_type}#{EOL}#{EOL}")
|
128
|
+
elsif v.respond_to?(:path) && type = mime_type(v.path) # files
|
129
|
+
io.write("Content-Type: #{type}#{EOL}#{EOL}")
|
130
|
+
else
|
131
|
+
io.write(EOL)
|
132
|
+
end
|
133
|
+
|
134
|
+
while data = v.read(8192)
|
135
|
+
io.write(data)
|
136
|
+
end
|
137
|
+
|
138
|
+
io.write(EOL)
|
139
|
+
|
140
|
+
ensure
|
141
|
+
v.close if v.respond_to?(:close)
|
142
|
+
end
|
143
|
+
|
144
|
+
def mime_type path
|
145
|
+
mime = MIME::Types.type_for(path)
|
146
|
+
mime.first && mime.first.content_type
|
147
|
+
end
|
148
|
+
|
149
|
+
def boundary
|
150
|
+
@boundary ||= rand(1_000_000).to_s
|
151
|
+
end
|
152
|
+
|
153
|
+
def headers
|
154
|
+
super.merge('Content-Type' =>
|
155
|
+
"multipart/form-data; boundary=#{boundary}")
|
156
|
+
end
|
157
|
+
|
158
|
+
def close
|
159
|
+
io.close! unless io.closed?
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
data/lib/rest-core/version.rb
CHANGED
data/rest-core.gemspec
CHANGED
@@ -2,14 +2,14 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = "rest-core"
|
5
|
-
s.version = "2.0
|
5
|
+
s.version = "2.1.0"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = [
|
9
9
|
"Cardinal Blue",
|
10
10
|
"Lin Jen-Shin (godfat)"]
|
11
|
-
s.date = "2013-
|
12
|
-
s.description = "Modular Ruby clients interface for REST APIs
|
11
|
+
s.date = "2013-05-08"
|
12
|
+
s.description = "Modular Ruby clients interface for REST APIs.\n\nThere has been an explosion in the number of REST APIs available today.\nTo address the need for a way to access these APIs easily and elegantly,\nwe have developed rest-core, which consists of composable middleware\nthat allows you to build a REST client for any REST API. Or in the case of\ncommon APIs such as Facebook, Github, and Twitter, you can simply use the\ndedicated clients provided by [rest-more][].\n\n[rest-more]: https://github.com/cardinalblue/rest-more"
|
13
13
|
s.email = ["dev (XD) cardinalblue.com"]
|
14
14
|
s.files = [
|
15
15
|
".gitignore",
|
@@ -68,6 +68,7 @@ Gem::Specification.new do |s|
|
|
68
68
|
"lib/rest-core/util/hmac.rb",
|
69
69
|
"lib/rest-core/util/json.rb",
|
70
70
|
"lib/rest-core/util/parse_query.rb",
|
71
|
+
"lib/rest-core/util/payload.rb",
|
71
72
|
"lib/rest-core/version.rb",
|
72
73
|
"lib/rest-core/wrapper.rb",
|
73
74
|
"rest-core.gemspec",
|
@@ -78,8 +79,9 @@ Gem::Specification.new do |s|
|
|
78
79
|
"test/test_cache.rb",
|
79
80
|
"test/test_client.rb",
|
80
81
|
"test/test_client_oauth1.rb",
|
82
|
+
"test/test_default_payload.rb",
|
81
83
|
"test/test_default_query.rb",
|
82
|
-
"test/
|
84
|
+
"test/test_em-http-request.rb",
|
83
85
|
"test/test_error_detector.rb",
|
84
86
|
"test/test_error_detector_http.rb",
|
85
87
|
"test/test_error_handler.rb",
|
@@ -88,22 +90,26 @@ Gem::Specification.new do |s|
|
|
88
90
|
"test/test_json_response.rb",
|
89
91
|
"test/test_oauth1_header.rb",
|
90
92
|
"test/test_payload.rb",
|
93
|
+
"test/test_rest-client.rb",
|
91
94
|
"test/test_simple.rb",
|
92
95
|
"test/test_timeout.rb",
|
93
96
|
"test/test_universal.rb",
|
94
97
|
"test/test_wrapper.rb"]
|
95
98
|
s.homepage = "https://github.com/cardinalblue/rest-core"
|
99
|
+
s.licenses = ["Apache License 2.0"]
|
100
|
+
s.post_install_message = "# [rest-core] Incompatible changes for POST requests:\n\n* We no longer support Rails-like POST payload, like translating\n `{:foo => [1, 2]}` to `'foo[]=1&foo[]=2'`. It would now be translated to\n `'foo=1&foo=2'`. If you like `'foo[]'` as the key, simply pass it as\n `{'foo[]' => [1, 2]}`.\n\n* This also applies to nested hashes like `{:foo => {:bar => 1}`. If you\n want that behaviour, just pass `{'foo[bar]' => 1}` which would then be\n translated to `'foo[bar]=1'`.\n"
|
96
101
|
s.require_paths = ["lib"]
|
97
|
-
s.rubygems_version = "2.0.
|
98
|
-
s.summary = "Modular Ruby clients interface for REST APIs"
|
102
|
+
s.rubygems_version = "2.0.3"
|
103
|
+
s.summary = "Modular Ruby clients interface for REST APIs."
|
99
104
|
s.test_files = [
|
100
105
|
"test/test_auth_basic.rb",
|
101
106
|
"test/test_builder.rb",
|
102
107
|
"test/test_cache.rb",
|
103
108
|
"test/test_client.rb",
|
104
109
|
"test/test_client_oauth1.rb",
|
110
|
+
"test/test_default_payload.rb",
|
105
111
|
"test/test_default_query.rb",
|
106
|
-
"test/
|
112
|
+
"test/test_em-http-request.rb",
|
107
113
|
"test/test_error_detector.rb",
|
108
114
|
"test/test_error_detector_http.rb",
|
109
115
|
"test/test_error_handler.rb",
|
@@ -112,6 +118,7 @@ Gem::Specification.new do |s|
|
|
112
118
|
"test/test_json_response.rb",
|
113
119
|
"test/test_oauth1_header.rb",
|
114
120
|
"test/test_payload.rb",
|
121
|
+
"test/test_rest-client.rb",
|
115
122
|
"test/test_simple.rb",
|
116
123
|
"test/test_timeout.rb",
|
117
124
|
"test/test_universal.rb",
|
data/task/gemgem.rb
CHANGED
@@ -14,6 +14,7 @@ module Gemgem
|
|
14
14
|
|
15
15
|
s.description = description.join
|
16
16
|
s.summary = description.first
|
17
|
+
s.license = readme['LICENSE'].sub(/.+\n\n/, '').lines.first.strip
|
17
18
|
|
18
19
|
s.rubygems_version = Gem::VERSION
|
19
20
|
s.date = Time.now.strftime('%Y-%m-%d')
|
@@ -33,8 +34,8 @@ module Gemgem
|
|
33
34
|
@readme ||=
|
34
35
|
if path
|
35
36
|
ps = "##{File.read(path)}".
|
36
|
-
scan(/((#+)[^\n]+\n\n.+?(
|
37
|
-
ps.inject(
|
37
|
+
scan(/((#+)[^\n]+\n\n.+?(?=(\n\n\2[^#\n]+\n)|\Z))/m).map(&:first)
|
38
|
+
ps.inject('HEADER' => ps.first){ |r, s, i|
|
38
39
|
r[s[/\w+/]] = s
|
39
40
|
r
|
40
41
|
}
|
@@ -44,7 +45,7 @@ module Gemgem
|
|
44
45
|
end
|
45
46
|
|
46
47
|
def description
|
47
|
-
@description ||= (readme['DESCRIPTION']||'').sub(/.+\n\n/, '').lines
|
48
|
+
@description ||= (readme['DESCRIPTION']||'').sub(/.+\n\n/, '').lines
|
48
49
|
end
|
49
50
|
|
50
51
|
def changes
|
@@ -104,9 +105,9 @@ module Gemgem
|
|
104
105
|
end
|
105
106
|
|
106
107
|
def split_lines ruby
|
107
|
-
ruby.gsub(/(.+?)\[(.+?)\]/){ |s|
|
108
|
+
ruby.gsub(/(.+?)\s*=\s*\[(.+?)\]/){ |s|
|
108
109
|
if $2.index(',')
|
109
|
-
"#{$1}[\n #{$2.split(',').map(&:strip).join(",\n ")}]"
|
110
|
+
"#{$1} = [\n #{$2.split(',').map(&:strip).join(",\n ")}]"
|
110
111
|
else
|
111
112
|
s
|
112
113
|
end
|
@@ -179,7 +180,7 @@ namespace :gem do
|
|
179
180
|
|
180
181
|
desc 'Install gem'
|
181
182
|
task :install => [:build] do
|
182
|
-
sh("#{Gem.ruby} -S gem install pkg/#{Gemgem.gem_tag}")
|
183
|
+
sh("#{Gem.ruby} -S gem install pkg/#{Gemgem.gem_tag}.gem")
|
183
184
|
end
|
184
185
|
|
185
186
|
desc 'Build gem'
|
data/test/test_auth_basic.rb
CHANGED
@@ -6,6 +6,8 @@ describe RC::AuthBasic do
|
|
6
6
|
@auth = RC::AuthBasic.new(RC::Dry.new, nil, nil)
|
7
7
|
end
|
8
8
|
|
9
|
+
env = {RC::REQUEST_HEADERS => {}}
|
10
|
+
|
9
11
|
should 'do nothing' do
|
10
12
|
@auth.call({}){ |res| res.should.eq({}) }
|
11
13
|
end
|
@@ -14,9 +16,9 @@ describe RC::AuthBasic do
|
|
14
16
|
@auth.instance_eval{@username = 'Aladdin'}
|
15
17
|
@auth.instance_eval{@password = 'open sesame'}
|
16
18
|
|
17
|
-
@auth.call(
|
18
|
-
res.should.eq(
|
19
|
-
{'Authorization' => 'Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=='}
|
19
|
+
@auth.call(env){ |res|
|
20
|
+
res.should.eq(RC::REQUEST_HEADERS =>
|
21
|
+
{'Authorization' => 'Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=='})
|
20
22
|
}
|
21
23
|
|
22
24
|
acc = {'Accept' => 'text/plain'}
|
@@ -30,11 +32,11 @@ describe RC::AuthBasic do
|
|
30
32
|
|
31
33
|
should 'leave a log if username are not both provided' do
|
32
34
|
@auth.instance_eval{@username = 'Aladdin'}
|
33
|
-
@auth.call(
|
35
|
+
@auth.call(env){ |res| res[RC::LOG].size.should.eq 1 }
|
34
36
|
end
|
35
37
|
|
36
38
|
should 'leave a log if password are not both provided' do
|
37
39
|
@auth.instance_eval{@password = 'open sesame'}
|
38
|
-
@auth.call(
|
40
|
+
@auth.call(env){ |res| res[RC::LOG].size.should.eq 1 }
|
39
41
|
end
|
40
42
|
end
|
data/test/test_cache.rb
CHANGED
@@ -149,6 +149,12 @@ describe RC::Cache do
|
|
149
149
|
}
|
150
150
|
end
|
151
151
|
|
152
|
+
should 'not cache dry run' do
|
153
|
+
c = RC::Builder.client{use RC::Cache, {}, nil}.new
|
154
|
+
c.url('test')
|
155
|
+
c.cache.should.eq({})
|
156
|
+
end
|
157
|
+
|
152
158
|
should 'update cache if there is cache option set to false' do
|
153
159
|
url, body = "https://cache", 'ok'
|
154
160
|
stub_request(:get, url).to_return(:body => body)
|
data/test/test_client_oauth1.rb
CHANGED
@@ -18,30 +18,30 @@ describe RC::ClientOauth1 do
|
|
18
18
|
sig = Digest::MD5.hexdigest('e&a=b&c=d')
|
19
19
|
data_sig = data.merge('sig' => sig)
|
20
20
|
data_json = RC::Json.encode(data_sig)
|
21
|
-
|
21
|
+
c = client.new(:data => data, :consumer_secret => 'e')
|
22
22
|
|
23
|
-
|
24
|
-
|
23
|
+
c.send(:calculate_sig).should.eq sig
|
24
|
+
c.data_json.should.eq data_json
|
25
25
|
|
26
|
-
|
27
|
-
|
26
|
+
c.data_json = data_json
|
27
|
+
c.data.should.eq data_sig
|
28
28
|
|
29
|
-
|
30
|
-
|
29
|
+
c.data_json = RC::Json.encode(data_sig.merge('sig' => 'wrong'))
|
30
|
+
c.data.should.eq({})
|
31
31
|
|
32
|
-
|
33
|
-
|
32
|
+
c.data_json = data_json
|
33
|
+
c.data.should.eq data_sig
|
34
34
|
|
35
|
-
|
36
|
-
|
35
|
+
c.data_json = 'bad json'
|
36
|
+
c.data.should.eq({})
|
37
37
|
end
|
38
38
|
|
39
39
|
should 'have correct default data' do
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
40
|
+
c = client.new
|
41
|
+
c.data.should.eq({})
|
42
|
+
c.data = nil
|
43
|
+
c.data['a'] = 'b'
|
44
|
+
c.data['a'].should.eq 'b'
|
45
45
|
end
|
46
46
|
|
47
47
|
should 'authorize' do
|
@@ -51,12 +51,12 @@ describe RC::ClientOauth1 do
|
|
51
51
|
stub_request(:post, 'http://nocalhost').
|
52
52
|
to_return(:body => 'user_id=123&haha=point')
|
53
53
|
|
54
|
-
|
55
|
-
|
56
|
-
|
54
|
+
c = client.new(:request_token_path => 'http://localhost',
|
55
|
+
:authorize_path => 'http://mocalhost',
|
56
|
+
:access_token_path => 'http://nocalhost')
|
57
57
|
|
58
|
-
|
59
|
-
|
60
|
-
|
58
|
+
c.authorize_url!.should.eq 'http://mocalhost?oauth_token=abc'
|
59
|
+
c.authorize!.should.eq('user_id' => '123', 'haha' => 'point',
|
60
|
+
'authorized' => 'true')
|
61
61
|
end
|
62
62
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
|
2
|
+
require 'rest-core/test'
|
3
|
+
|
4
|
+
describe RC::DefaultPayload do
|
5
|
+
app = RC::DefaultPayload.new(RC::Dry.new, {})
|
6
|
+
env = {RC::REQUEST_PAYLOAD => {}}
|
7
|
+
|
8
|
+
should 'do nothing' do
|
9
|
+
app.call(env){ |r| r[RC::REQUEST_PAYLOAD].should.eq({}) }
|
10
|
+
end
|
11
|
+
|
12
|
+
should 'merge payload' do
|
13
|
+
app.instance_eval{@payload = {'pay' => 'load'}}
|
14
|
+
|
15
|
+
app.call(env){ |r| r.should.eq({RC::REQUEST_PAYLOAD =>
|
16
|
+
{'pay' => 'load'}}) }
|
17
|
+
|
18
|
+
format = {'format' => 'json'}
|
19
|
+
env = {RC::REQUEST_PAYLOAD => format}
|
20
|
+
|
21
|
+
app.call(env){ |r| r.should.eq({RC::REQUEST_PAYLOAD =>
|
22
|
+
{'pay' => 'load'}.merge(format)})}
|
23
|
+
end
|
24
|
+
|
25
|
+
should 'accept non-hash payload' do
|
26
|
+
u = RC::Universal.new(:log_method => false)
|
27
|
+
env = {RC::REQUEST_PAYLOAD => 'payload'}
|
28
|
+
u.request_full(env, u.dry)[RC::REQUEST_PAYLOAD].should.eq('payload')
|
29
|
+
|
30
|
+
u.payload = 'default'
|
31
|
+
u.request_full(env, u.dry)[RC::REQUEST_PAYLOAD].should.eq('payload')
|
32
|
+
u.request_full({} , u.dry)[RC::REQUEST_PAYLOAD].should.eq('default')
|
33
|
+
|
34
|
+
u = RC::Builder.client{use RC::DefaultPayload, 'maylord'}.new
|
35
|
+
u.request_full({} , u.dry)[RC::REQUEST_PAYLOAD].should.eq('maylord')
|
36
|
+
u.request_full(env, u.dry)[RC::REQUEST_PAYLOAD].should.eq('payload')
|
37
|
+
end
|
38
|
+
end
|
data/test/test_default_query.rb
CHANGED
@@ -6,34 +6,36 @@ describe RC::DefaultQuery do
|
|
6
6
|
@app = RC::DefaultQuery.new(RC::Dry.new, {})
|
7
7
|
end
|
8
8
|
|
9
|
+
env = {RC::REQUEST_QUERY => {}}
|
10
|
+
|
9
11
|
describe 'when given query' do
|
10
12
|
should 'do nothing' do
|
11
|
-
@app.call(
|
13
|
+
@app.call(env){ |r| r[RC::REQUEST_QUERY].should.eq({}) }
|
12
14
|
end
|
13
15
|
|
14
16
|
should 'merge query' do
|
15
17
|
@app.instance_eval{@query = {'q' => 'uery'}}
|
16
18
|
|
17
|
-
@app.call(
|
19
|
+
@app.call(env){ |r| r.should.eq({RC::REQUEST_QUERY => {'q' => 'uery'}}) }
|
18
20
|
|
19
21
|
format = {'format' => 'json'}
|
20
|
-
|
22
|
+
e = {RC::REQUEST_QUERY => format}
|
21
23
|
|
22
|
-
@app.call(
|
24
|
+
@app.call(e){ |r|
|
23
25
|
r.should.eq({RC::REQUEST_QUERY => {'q' => 'uery'}.merge(format)}) }
|
24
26
|
end
|
25
27
|
|
26
28
|
should 'string_keys in query' do
|
27
|
-
|
28
|
-
@app.call(env){ |r|
|
29
|
-
r.should.eq({RC::REQUEST_QUERY => {'symbol' => 'value'}}.merge(
|
29
|
+
e = {'query' => {:symbol => 'value'}}
|
30
|
+
@app.call(env.merge(e)){ |r|
|
31
|
+
r.should.eq({RC::REQUEST_QUERY => {'symbol' => 'value'}}.merge(e))
|
30
32
|
}
|
31
33
|
end
|
32
34
|
end
|
33
35
|
|
34
36
|
describe 'when not given query' do
|
35
37
|
should 'merge query with {}' do
|
36
|
-
@app.call(
|
38
|
+
@app.call(env){ |r| r.should.eq(RC::REQUEST_QUERY => {}) }
|
37
39
|
end
|
38
40
|
end
|
39
41
|
end
|