rest-core 2.0.4 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|