rest-core 3.6.0 → 4.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitmodules +3 -0
- data/.travis.yml +0 -1
- data/CHANGES.md +28 -0
- data/Gemfile +0 -2
- data/README.md +14 -95
- data/Rakefile +16 -3
- data/example/simple.rb +1 -0
- data/example/use-cases.rb +15 -3
- data/lib/rest-core.rb +38 -75
- data/lib/rest-core/client/universal.rb +3 -1
- data/lib/rest-core/client_oauth1.rb +64 -59
- data/lib/rest-core/event.rb +9 -11
- data/lib/rest-core/middleware/auth_basic.rb +21 -21
- data/lib/rest-core/middleware/bypass.rb +8 -8
- data/lib/rest-core/middleware/cache.rb +94 -90
- data/lib/rest-core/middleware/clash_response.rb +15 -14
- data/lib/rest-core/middleware/common_logger.rb +27 -26
- data/lib/rest-core/middleware/default_headers.rb +8 -8
- data/lib/rest-core/middleware/default_payload.rb +8 -8
- data/lib/rest-core/middleware/default_query.rb +8 -8
- data/lib/rest-core/middleware/default_site.rb +12 -12
- data/lib/rest-core/middleware/defaults.rb +38 -38
- data/lib/rest-core/middleware/error_detector.rb +10 -10
- data/lib/rest-core/middleware/error_detector_http.rb +6 -4
- data/lib/rest-core/middleware/error_handler.rb +14 -14
- data/lib/rest-core/middleware/follow_redirect.rb +28 -27
- data/lib/rest-core/middleware/json_request.rb +13 -11
- data/lib/rest-core/middleware/json_response.rb +29 -28
- data/lib/rest-core/middleware/oauth1_header.rb +84 -83
- data/lib/rest-core/middleware/oauth2_header.rb +27 -25
- data/lib/rest-core/middleware/oauth2_query.rb +15 -15
- data/lib/rest-core/middleware/query_response.rb +14 -14
- data/lib/rest-core/middleware/retry.rb +25 -23
- data/lib/rest-core/middleware/smash_response.rb +15 -14
- data/lib/rest-core/middleware/timeout.rb +18 -19
- data/lib/rest-core/test.rb +1 -18
- data/lib/rest-core/util/clash.rb +38 -37
- data/lib/rest-core/util/config.rb +40 -39
- data/lib/rest-core/util/dalli_extension.rb +11 -10
- data/lib/rest-core/util/hmac.rb +9 -8
- data/lib/rest-core/util/json.rb +55 -54
- data/lib/rest-core/util/parse_link.rb +13 -12
- data/lib/rest-core/util/parse_query.rb +24 -22
- data/lib/rest-core/version.rb +1 -1
- data/rest-core.gemspec +121 -158
- data/test/test_cache.rb +2 -0
- data/test/test_default_payload.rb +1 -1
- data/test/test_error_handler.rb +5 -4
- data/test/test_timeout.rb +9 -8
- data/test/test_universal.rb +8 -0
- metadata +9 -73
- data/lib/rest-core/builder.rb +0 -162
- data/lib/rest-core/client.rb +0 -277
- data/lib/rest-core/client/simple.rb +0 -2
- data/lib/rest-core/engine.rb +0 -36
- data/lib/rest-core/engine/dry.rb +0 -9
- data/lib/rest-core/engine/http-client.rb +0 -41
- data/lib/rest-core/error.rb +0 -5
- data/lib/rest-core/event_source.rb +0 -137
- data/lib/rest-core/middleware.rb +0 -151
- data/lib/rest-core/promise.rb +0 -249
- data/lib/rest-core/thread_pool.rb +0 -131
- data/lib/rest-core/timer.rb +0 -58
- data/lib/rest-core/util/payload.rb +0 -173
- data/test/test_builder.rb +0 -40
- data/test/test_client.rb +0 -177
- data/test/test_event_source.rb +0 -159
- data/test/test_future.rb +0 -16
- data/test/test_httpclient.rb +0 -118
- data/test/test_payload.rb +0 -204
- data/test/test_promise.rb +0 -146
- data/test/test_simple.rb +0 -38
- data/test/test_thread_pool.rb +0 -10
data/test/test_event_source.rb
DELETED
@@ -1,159 +0,0 @@
|
|
1
|
-
|
2
|
-
require 'socket'
|
3
|
-
require 'rest-core/test'
|
4
|
-
|
5
|
-
describe RC::EventSource do
|
6
|
-
after do
|
7
|
-
Muack.verify
|
8
|
-
WebMock.reset!
|
9
|
-
end
|
10
|
-
|
11
|
-
client = RC::Builder.client{use RC::Cache, {}, nil}.new
|
12
|
-
server = lambda do |close=true|
|
13
|
-
serv = TCPServer.new(0)
|
14
|
-
port = serv.addr[1]
|
15
|
-
path = "http://localhost:#{port}/"
|
16
|
-
payload = <<-SSE
|
17
|
-
event: put
|
18
|
-
data: {}
|
19
|
-
|
20
|
-
event: keep-alive
|
21
|
-
data: null
|
22
|
-
SSE
|
23
|
-
m = [{'event' => 'put' , 'data' => '{}'},
|
24
|
-
{'event' => 'keep-alive', 'data' => 'null'}]
|
25
|
-
|
26
|
-
t = Thread.new do
|
27
|
-
sock = serv.accept
|
28
|
-
sock.readline("\r\n\r\n")
|
29
|
-
sock.puts("HTTP/1.1 200 OK\r")
|
30
|
-
sock.puts("Content-Type: text/event-stream\r")
|
31
|
-
sock.puts
|
32
|
-
sock.puts(payload)
|
33
|
-
sock.close if close
|
34
|
-
end
|
35
|
-
|
36
|
-
[client.event_source(path, :a => 'b'), m, t]
|
37
|
-
end
|
38
|
-
|
39
|
-
would 'work regularly' do
|
40
|
-
es, m, t = server.call
|
41
|
-
flag = 0
|
42
|
-
|
43
|
-
es.onopen do |sock|
|
44
|
-
sock.should.kind_of? IO
|
45
|
-
flag.should.eq 0
|
46
|
-
flag += 1
|
47
|
-
end.
|
48
|
-
onmessage do |event, data, sock|
|
49
|
-
{'event' => event, 'data' => data}.should.eq m.shift
|
50
|
-
sock.should.kind_of? IO
|
51
|
-
sock.should.not.closed?
|
52
|
-
flag += 1
|
53
|
-
end.
|
54
|
-
onerror do |error, sock|
|
55
|
-
error.should.kind_of? EOFError
|
56
|
-
m.should.empty?
|
57
|
-
sock.should.closed?
|
58
|
-
flag.should.eq 3
|
59
|
-
flag += 1
|
60
|
-
end.start.wait
|
61
|
-
|
62
|
-
flag.should.eq 4
|
63
|
-
t.join
|
64
|
-
end
|
65
|
-
|
66
|
-
would 'close' do
|
67
|
-
es, _, t = server.call(false)
|
68
|
-
flag = 0
|
69
|
-
es.onmessage do
|
70
|
-
es.close
|
71
|
-
flag += 1
|
72
|
-
end.start.wait
|
73
|
-
|
74
|
-
flag.should.eq 1
|
75
|
-
t.join
|
76
|
-
end
|
77
|
-
|
78
|
-
would 'reconnect' do
|
79
|
-
stub_select_for_stringio
|
80
|
-
stub_request(:get, 'https://a?b=c').to_return(:body => <<-SSE)
|
81
|
-
event: put
|
82
|
-
data: 0
|
83
|
-
|
84
|
-
event: put
|
85
|
-
data: 1
|
86
|
-
SSE
|
87
|
-
stub_request(:get, 'https://a?c=d').to_return(:body => <<-SSE)
|
88
|
-
event: put
|
89
|
-
data: 2
|
90
|
-
|
91
|
-
event: put
|
92
|
-
data: 3
|
93
|
-
SSE
|
94
|
-
es = client.event_source('https://a', :b => 'c')
|
95
|
-
m = ('0'..'3').to_a
|
96
|
-
es.onmessage do |event, data|
|
97
|
-
data.should.eq m.shift
|
98
|
-
|
99
|
-
end.onerror do |error|
|
100
|
-
error.should.kind_of? EOFError
|
101
|
-
es.query = {:c => 'd'}
|
102
|
-
|
103
|
-
end.onreconnect do |error, sock|
|
104
|
-
error.should.kind_of? EOFError
|
105
|
-
sock.should.respond_to? :read
|
106
|
-
!m.empty? # not empty to reconnect
|
107
|
-
|
108
|
-
end.start.wait
|
109
|
-
m.should.empty?
|
110
|
-
end
|
111
|
-
|
112
|
-
would 'not cache' do
|
113
|
-
stub_select_for_stringio
|
114
|
-
stub_request(:get, 'https://a?b=c').to_return(:body => <<-SSE)
|
115
|
-
event: put
|
116
|
-
data: 0
|
117
|
-
|
118
|
-
event: put
|
119
|
-
data: 1
|
120
|
-
SSE
|
121
|
-
es = client.event_source('https://a', :b => 'c')
|
122
|
-
m = %w[0 1 0 1]
|
123
|
-
es.onmessage do |event, data|
|
124
|
-
data.should.eq m.shift
|
125
|
-
|
126
|
-
end.onerror do |error|
|
127
|
-
error.should.kind_of? EOFError
|
128
|
-
|
129
|
-
end.onreconnect do |error, sock|
|
130
|
-
error.should.kind_of? EOFError
|
131
|
-
sock.should.respond_to? :read
|
132
|
-
!m.empty? # not empty to reconnect
|
133
|
-
|
134
|
-
end.start.wait
|
135
|
-
m.should.empty?
|
136
|
-
end
|
137
|
-
|
138
|
-
would 'not deadlock without ErrorHandler' do
|
139
|
-
c = RC::Simple.new.event_source('http://localhost:1')
|
140
|
-
c.onerror{ |e| e.should.kind_of?(Errno::ECONNREFUSED) }
|
141
|
-
c.start.wait
|
142
|
-
end
|
143
|
-
|
144
|
-
would 'not deadlock with ErrorHandler' do
|
145
|
-
c = RC::Universal.new(:log_method => false).
|
146
|
-
event_source('http://localhost:1')
|
147
|
-
c.onerror{ |e| e.should.kind_of?(Errno::ECONNREFUSED) }
|
148
|
-
c.start.wait
|
149
|
-
end
|
150
|
-
|
151
|
-
would 'not deadlock if errors in onmessage' do
|
152
|
-
err = nil
|
153
|
-
es, _, _ = server.call
|
154
|
-
es.onmessage do |event, data|
|
155
|
-
raise err = "error"
|
156
|
-
end.start.wait
|
157
|
-
err.should.eq "error"
|
158
|
-
end
|
159
|
-
end
|
data/test/test_future.rb
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
|
2
|
-
require 'stringio'
|
3
|
-
require 'rest-core/test'
|
4
|
-
|
5
|
-
describe RC::Promise::Future do
|
6
|
-
would 'fulfill the future' do
|
7
|
-
promise = RC::Promise.new(RC::FAIL => [])
|
8
|
-
promise.fulfill('body', 200, {'A' => 'B'}, StringIO.new)
|
9
|
-
|
10
|
-
promise.future_body .should.eq 'body'
|
11
|
-
promise.future_status .should.eq 200
|
12
|
-
promise.future_headers .should.eq('A' => 'B')
|
13
|
-
promise.future_socket .should.kind_of?(StringIO)
|
14
|
-
promise.future_failures.should.eq []
|
15
|
-
end
|
16
|
-
end
|
data/test/test_httpclient.rb
DELETED
@@ -1,118 +0,0 @@
|
|
1
|
-
|
2
|
-
require 'rest-core/test'
|
3
|
-
|
4
|
-
require 'openssl'
|
5
|
-
require 'socket'
|
6
|
-
require 'zlib'
|
7
|
-
|
8
|
-
describe RC::HttpClient do
|
9
|
-
describe 'POST Payload' do
|
10
|
-
after do
|
11
|
-
WebMock.reset!
|
12
|
-
end
|
13
|
-
|
14
|
-
client = RC::Builder.client
|
15
|
-
path = 'http://example.com'
|
16
|
-
ok = 'OK'
|
17
|
-
c = client.new
|
18
|
-
|
19
|
-
post = lambda do |payload, body|
|
20
|
-
WebMock::API.stub_request(:post, path).
|
21
|
-
with(:body => body).to_return(:body => ok)
|
22
|
-
c.post(path, payload).should.eq ok
|
23
|
-
end
|
24
|
-
|
25
|
-
would 'post with string' do
|
26
|
-
post['string', 'string']
|
27
|
-
end
|
28
|
-
|
29
|
-
would 'post with file' do
|
30
|
-
File.open(__FILE__) do |f|
|
31
|
-
b = f.read
|
32
|
-
f.rewind
|
33
|
-
post[f, b]
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
would 'post with socket' do
|
38
|
-
rd, wr = IO.pipe
|
39
|
-
wr.write('socket')
|
40
|
-
wr.close
|
41
|
-
post[rd, 'socket']
|
42
|
-
end
|
43
|
-
|
44
|
-
would 'not kill the thread if error was coming from the task' do
|
45
|
-
mock(HTTPClient).new{ raise 'boom' }.with_any_args
|
46
|
-
c.request(RC::ASYNC => true).message.should.eq 'boom'
|
47
|
-
Muack.verify
|
48
|
-
end
|
49
|
-
|
50
|
-
def accept body
|
51
|
-
server = TCPServer.new(0)
|
52
|
-
t = Thread.new do
|
53
|
-
client = server.accept
|
54
|
-
client.write(<<-HTTP)
|
55
|
-
HTTP/1.0 200 OK\r
|
56
|
-
Connection: close\r
|
57
|
-
Content-Encoding: deflate\r
|
58
|
-
\r
|
59
|
-
#{body}\r
|
60
|
-
HTTP
|
61
|
-
client.close_write
|
62
|
-
end
|
63
|
-
|
64
|
-
yield("http://localhost:#{server.local_address.ip_port}")
|
65
|
-
|
66
|
-
t.join
|
67
|
-
end
|
68
|
-
|
69
|
-
would 'accept deflate' do
|
70
|
-
accept(Zlib::Deflate.deflate(ok)) do |site|
|
71
|
-
c.post(site, 'body').should.eq ok
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
config_engine = lambda do |engine|
|
76
|
-
engine.transparent_gzip_decompression = false
|
77
|
-
engine.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
78
|
-
end
|
79
|
-
|
80
|
-
define_method(:define_default_config_engine) do |d|
|
81
|
-
d.singleton_class.module_eval do
|
82
|
-
define_method(:default_config_engine) do
|
83
|
-
config_engine
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
would 'disable auto-deflate' do
|
89
|
-
accept(ok) do |site|
|
90
|
-
c.post(site, 'body', {}, :config_engine => config_engine).
|
91
|
-
chomp.should.eq ok
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
would 'disable auto-deflate with class default_config_engine' do
|
96
|
-
accept(ok) do |site|
|
97
|
-
d = RC::Builder.client
|
98
|
-
define_default_config_engine(d)
|
99
|
-
d.new.post(site, 'body').chomp.should.eq ok
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
would 'disable auto-deflate with instance default_config_engine' do
|
104
|
-
accept(ok) do |site|
|
105
|
-
d = RC::Builder.client.new
|
106
|
-
define_default_config_engine(d)
|
107
|
-
d.post(site, 'body').chomp.should.eq ok
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
would 'disable auto-deflate with setting config_engine' do
|
112
|
-
accept(ok) do |site|
|
113
|
-
d = RC::Builder.client.new(:config_engine => config_engine)
|
114
|
-
d.post(site, 'body').chomp.should.eq ok
|
115
|
-
end
|
116
|
-
end
|
117
|
-
end
|
118
|
-
end
|
data/test/test_payload.rb
DELETED
@@ -1,204 +0,0 @@
|
|
1
|
-
|
2
|
-
require 'rest-core/test'
|
3
|
-
|
4
|
-
describe RC::Payload do
|
5
|
-
describe 'A regular Payload' do
|
6
|
-
would 'use standard enctype as default content-type' do
|
7
|
-
RC::Payload::UrlEncoded.new({}).headers['Content-Type'].
|
8
|
-
should.eq 'application/x-www-form-urlencoded'
|
9
|
-
end
|
10
|
-
|
11
|
-
would 'form properly encoded params' do
|
12
|
-
RC::Payload::UrlEncoded.new(:foo => 'bar').read.
|
13
|
-
should.eq 'foo=bar'
|
14
|
-
RC::Payload::UrlEncoded.new(:foo => 'bar', :baz => 'qux').read.
|
15
|
-
should.eq 'baz=qux&foo=bar'
|
16
|
-
end
|
17
|
-
|
18
|
-
would 'escape parameters' do
|
19
|
-
RC::Payload::UrlEncoded.new('foo ' => 'bar').read.
|
20
|
-
should.eq 'foo%20=bar'
|
21
|
-
end
|
22
|
-
|
23
|
-
would 'properly handle arrays as repeated parameters' do
|
24
|
-
RC::Payload::UrlEncoded.new(:foo => ['bar']).read.
|
25
|
-
should.eq 'foo=bar'
|
26
|
-
RC::Payload::UrlEncoded.new(:foo => ['bar', 'baz']).read.
|
27
|
-
should.eq 'foo=bar&foo=baz'
|
28
|
-
end
|
29
|
-
|
30
|
-
would 'not close if stream already closed' do
|
31
|
-
p = RC::Payload::UrlEncoded.new('foo ' => 'bar')
|
32
|
-
p.close
|
33
|
-
2.times{ p.close.should.eq nil }
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
describe 'A multipart Payload' do
|
38
|
-
would 'use standard enctype as default content-type' do
|
39
|
-
p = RC::Payload::Multipart.new({})
|
40
|
-
stub(p).boundary{123}
|
41
|
-
p.headers['Content-Type'].should.eq 'multipart/form-data; boundary=123'
|
42
|
-
end
|
43
|
-
|
44
|
-
would 'not error on close if stream already closed' do
|
45
|
-
p = RC::Payload::Multipart.new(:file => File.open(__FILE__))
|
46
|
-
p.close
|
47
|
-
2.times{ p.close.should.eq nil }
|
48
|
-
end
|
49
|
-
|
50
|
-
would 'form properly separated multipart data' do
|
51
|
-
p = RC::Payload::Multipart.new(:bar => 'baz', :foo => 'bar')
|
52
|
-
p.read.should.eq <<-EOS
|
53
|
-
--#{p.boundary}\r
|
54
|
-
Content-Disposition: form-data; name="bar"\r
|
55
|
-
\r
|
56
|
-
baz\r
|
57
|
-
--#{p.boundary}\r
|
58
|
-
Content-Disposition: form-data; name="foo"\r
|
59
|
-
\r
|
60
|
-
bar\r
|
61
|
-
--#{p.boundary}--\r
|
62
|
-
EOS
|
63
|
-
end
|
64
|
-
|
65
|
-
would 'form multiple files with the same name' do
|
66
|
-
with_img do |f, n|
|
67
|
-
with_img do |ff, nn|
|
68
|
-
p = RC::Payload::Multipart.new(:foo => [f, ff])
|
69
|
-
p.read.should.eq <<-EOS
|
70
|
-
--#{p.boundary}\r
|
71
|
-
Content-Disposition: form-data; name="foo"; filename="#{n}"\r
|
72
|
-
Content-Type: image/jpeg\r
|
73
|
-
\r
|
74
|
-
#{'a'*10}\r
|
75
|
-
--#{p.boundary}\r
|
76
|
-
Content-Disposition: form-data; name="foo"; filename="#{nn}"\r
|
77
|
-
Content-Type: image/jpeg\r
|
78
|
-
\r
|
79
|
-
#{'a'*10}\r
|
80
|
-
--#{p.boundary}--\r
|
81
|
-
EOS
|
82
|
-
end
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
would 'not escape parameters names' do
|
87
|
-
p = RC::Payload::Multipart.new('bar ' => 'baz')
|
88
|
-
p.read.should.eq <<-EOS
|
89
|
-
--#{p.boundary}\r
|
90
|
-
Content-Disposition: form-data; name="bar "\r
|
91
|
-
\r
|
92
|
-
baz\r
|
93
|
-
--#{p.boundary}--\r
|
94
|
-
EOS
|
95
|
-
end
|
96
|
-
|
97
|
-
would 'form properly separated multipart data' do
|
98
|
-
with_img do |f, n|
|
99
|
-
p = RC::Payload::Multipart.new(:foo => f)
|
100
|
-
p.read.should.eq <<-EOS
|
101
|
-
--#{p.boundary}\r
|
102
|
-
Content-Disposition: form-data; name="foo"; filename="#{n}"\r
|
103
|
-
Content-Type: image/jpeg\r
|
104
|
-
\r
|
105
|
-
#{File.read(f.path)}\r
|
106
|
-
--#{p.boundary}--\r
|
107
|
-
EOS
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
would "ignore the name attribute when it's not set" do
|
112
|
-
with_img do |f, n|
|
113
|
-
p = RC::Payload::Multipart.new(nil => f)
|
114
|
-
p.read.should.eq <<-EOS
|
115
|
-
--#{p.boundary}\r
|
116
|
-
Content-Disposition: form-data; filename="#{n}"\r
|
117
|
-
Content-Type: image/jpeg\r
|
118
|
-
\r
|
119
|
-
#{File.read(f.path)}\r
|
120
|
-
--#{p.boundary}--\r
|
121
|
-
EOS
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
|
-
would 'detect optional (original) content type and filename' do
|
126
|
-
File.open(__FILE__) do |f|
|
127
|
-
def f.content_type ; 'image/jpeg'; end
|
128
|
-
def f.original_filename; 'foo.txt' ; end
|
129
|
-
p = RC::Payload::Multipart.new(:foo => f)
|
130
|
-
p.read.should.eq <<-EOS
|
131
|
-
--#{p.boundary}\r
|
132
|
-
Content-Disposition: form-data; name="foo"; filename="foo.txt"\r
|
133
|
-
Content-Type: image/jpeg\r
|
134
|
-
\r
|
135
|
-
#{File.read(f.path)}\r
|
136
|
-
--#{p.boundary}--\r
|
137
|
-
EOS
|
138
|
-
end
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
describe 'streamed payloads' do
|
143
|
-
would 'properly determine the size of file payloads' do
|
144
|
-
File.open(__FILE__) do |f|
|
145
|
-
p = RC::Payload.generate(f)
|
146
|
-
p.size.should.eq f.stat.size
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
|
-
would 'properly determine the size of other kinds of payloads' do
|
151
|
-
s = StringIO.new('foo')
|
152
|
-
p = RC::Payload.generate(s)
|
153
|
-
p.size.should.eq 3
|
154
|
-
|
155
|
-
begin
|
156
|
-
f = Tempfile.new('rest-core')
|
157
|
-
f.write('foo bar')
|
158
|
-
f.rewind
|
159
|
-
|
160
|
-
p = RC::Payload.generate(f)
|
161
|
-
p.size.should.eq 7
|
162
|
-
ensure
|
163
|
-
f.close!
|
164
|
-
end
|
165
|
-
end
|
166
|
-
end
|
167
|
-
|
168
|
-
describe 'Payload generation' do
|
169
|
-
would 'recognize standard urlencoded params' do
|
170
|
-
RC::Payload.generate('foo' => 'bar').should.
|
171
|
-
kind_of?(RC::Payload::UrlEncoded)
|
172
|
-
end
|
173
|
-
|
174
|
-
would 'recognize multipart params' do
|
175
|
-
File.open(__FILE__) do |f|
|
176
|
-
RC::Payload.generate('foo' => f).should.
|
177
|
-
kind_of?(RC::Payload::Multipart)
|
178
|
-
end
|
179
|
-
end
|
180
|
-
|
181
|
-
would 'return data if none of the above' do
|
182
|
-
RC::Payload.generate('data').should.
|
183
|
-
kind_of?(RC::Payload::StreamedString)
|
184
|
-
end
|
185
|
-
|
186
|
-
would 'recognize nested multipart payloads in arrays' do
|
187
|
-
File.open(__FILE__) do |f|
|
188
|
-
RC::Payload.generate('foo' => [f]).should.
|
189
|
-
kind_of?(RC::Payload::Multipart)
|
190
|
-
end
|
191
|
-
end
|
192
|
-
|
193
|
-
would 'recognize file payloads that can be streamed' do
|
194
|
-
File.open(__FILE__) do |f|
|
195
|
-
RC::Payload.generate(f).should.kind_of?(RC::Payload::Streamed)
|
196
|
-
end
|
197
|
-
end
|
198
|
-
|
199
|
-
would 'recognize other payloads that can be streamed' do
|
200
|
-
RC::Payload.generate(StringIO.new('foo')).should.
|
201
|
-
kind_of?(RC::Payload::Streamed)
|
202
|
-
end
|
203
|
-
end
|
204
|
-
end
|