streamly 0.1.3 → 0.1.4
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.
- data/CHANGELOG.md +5 -0
- data/README.rdoc +3 -4
- data/VERSION.yml +3 -2
- data/benchmark/basic_request.rb +7 -6
- data/benchmark/streaming_json_request.rb +7 -6
- data/ext/extconf.rb +4 -1
- data/ext/streamly.c +356 -278
- data/ext/streamly.h +45 -22
- data/lib/streamly.rb +1 -1
- data/spec/requests/request_spec.rb +255 -65
- data/spec/{sinatra.rb → server.rb} +0 -0
- data/spec/spec_helper.rb +1 -0
- data/streamly.gemspec +6 -6
- metadata +19 -7
data/ext/streamly.h
CHANGED
@@ -8,25 +8,15 @@ VALUE sym_response_header_handler, sym_response_body_handler, sym_username, sym_
|
|
8
8
|
|
9
9
|
#define GetInstance(obj, sval) (sval = (struct curl_instance*)DATA_PTR(obj));
|
10
10
|
|
11
|
-
#ifdef HAVE_RBTRAP
|
12
|
-
#include <rubysig.h>
|
13
|
-
#else
|
14
|
-
void rb_enable_interrupt(void);
|
15
|
-
void rb_disable_interrupt(void);
|
16
|
-
|
17
|
-
#define TRAP_BEG rb_enable_interrupt();
|
18
|
-
#define TRAP_END do { rb_disable_interrupt(); rb_thread_check_ints(); } while(0);
|
19
|
-
#endif
|
20
|
-
|
21
11
|
struct curl_instance {
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
12
|
+
CURL* handle;
|
13
|
+
char error_buffer[CURL_ERROR_SIZE];
|
14
|
+
struct curl_slist* request_headers;
|
15
|
+
VALUE request_payload_handler;
|
16
|
+
VALUE response_header_handler;
|
17
|
+
VALUE response_body_handler;
|
18
|
+
VALUE request_method;
|
19
|
+
VALUE options;
|
30
20
|
};
|
31
21
|
|
32
22
|
// libcurl callbacks
|
@@ -36,8 +26,41 @@ static size_t data_handler(char * stream, size_t size, size_t nmemb, VALUE handl
|
|
36
26
|
//
|
37
27
|
static VALUE select_error(CURLcode code);
|
38
28
|
static VALUE each_http_header(VALUE header, VALUE header_array);
|
39
|
-
void streamly_instance_mark(struct curl_instance * instance);
|
40
|
-
void streamly_instance_free(struct curl_instance * instance);
|
29
|
+
static void streamly_instance_mark(struct curl_instance * instance);
|
30
|
+
static void streamly_instance_free(struct curl_instance * instance);
|
31
|
+
|
32
|
+
static VALUE rb_streamly_new(int argc, VALUE * argv, VALUE klass);
|
33
|
+
|
34
|
+
#if defined(__GNUC__) && (__GNUC__ >= 3)
|
35
|
+
#define RB_STREAMLY_UNUSED __attribute__ ((unused))
|
36
|
+
#else
|
37
|
+
#define RB_STREAMLY_UNUSED
|
38
|
+
#endif
|
39
|
+
|
40
|
+
/*
|
41
|
+
* partial emulation of the 1.9 rb_thread_blocking_region under 1.8,
|
42
|
+
* this is enough for dealing with blocking I/O functions in the
|
43
|
+
* presence of threads.
|
44
|
+
*/
|
45
|
+
#ifndef HAVE_RB_THREAD_BLOCKING_REGION
|
46
|
+
|
47
|
+
#include <rubysig.h>
|
48
|
+
#define RUBY_UBF_IO ((rb_unblock_function_t *)-1)
|
49
|
+
typedef void rb_unblock_function_t(void *);
|
50
|
+
typedef VALUE rb_blocking_function_t(void *);
|
51
|
+
static VALUE
|
52
|
+
rb_thread_blocking_region(
|
53
|
+
rb_blocking_function_t *func, void *data1,
|
54
|
+
RB_STREAMLY_UNUSED rb_unblock_function_t *ubf,
|
55
|
+
RB_STREAMLY_UNUSED void *data2)
|
56
|
+
{
|
57
|
+
VALUE rv;
|
58
|
+
|
59
|
+
TRAP_BEG;
|
60
|
+
rv = func(data1);
|
61
|
+
TRAP_END;
|
62
|
+
|
63
|
+
return rv;
|
64
|
+
}
|
41
65
|
|
42
|
-
|
43
|
-
VALUE rb_streamly_new(int argc, VALUE * argv, VALUE self);
|
66
|
+
#endif /* ! HAVE_RB_THREAD_BLOCKING_REGION */
|
data/lib/streamly.rb
CHANGED
@@ -2,92 +2,282 @@
|
|
2
2
|
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper.rb')
|
3
3
|
|
4
4
|
describe "Streamly's REST API" do
|
5
|
-
|
5
|
+
|
6
6
|
before(:all) do
|
7
7
|
@response = "Hello, brian".strip
|
8
8
|
end
|
9
|
-
|
9
|
+
|
10
10
|
context "HEAD" do
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
context "basic" do
|
12
|
+
it "should perform a basic request" do
|
13
|
+
resp = Streamly.head('localhost:4567')
|
14
|
+
resp.should_not be_empty
|
15
|
+
end
|
16
|
+
|
17
|
+
if RUBY_VERSION =~ /^1.9/
|
18
|
+
it "should default to utf-8 if Encoding.default_internal is nil" do
|
19
|
+
Encoding.default_internal = nil
|
20
|
+
Streamly.head('localhost:4567').encoding.should eql(Encoding.find('utf-8'))
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should use Encoding.default_internal" do
|
24
|
+
Encoding.default_internal = Encoding.find('utf-8')
|
25
|
+
Streamly.head('localhost:4567').encoding.should eql(Encoding.default_internal)
|
26
|
+
Encoding.default_internal = Encoding.find('us-ascii')
|
27
|
+
Streamly.head('localhost:4567').encoding.should eql(Encoding.default_internal)
|
28
|
+
end
|
29
|
+
end
|
14
30
|
end
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
31
|
+
|
32
|
+
context "streaming" do
|
33
|
+
it "should perform a basic request and stream header chunks to the caller" do
|
34
|
+
streamed_response = ''
|
35
|
+
resp = Streamly.head('localhost:4567') do |chunk|
|
36
|
+
chunk.should_not be_empty
|
37
|
+
streamed_response << chunk
|
38
|
+
end
|
39
|
+
resp.should be_nil
|
40
|
+
streamed_response.should_not be_nil
|
41
|
+
end
|
42
|
+
|
43
|
+
if RUBY_VERSION =~ /^1.9/
|
44
|
+
it "should default to utf-8 if Encoding.default_internal is nil" do
|
45
|
+
Encoding.default_internal = nil
|
46
|
+
Streamly.head('localhost:4567') do |chunk|
|
47
|
+
chunk.encoding.should eql(Encoding.find('utf-8'))
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should use Encoding.default_internal" do
|
52
|
+
Encoding.default_internal = Encoding.find('utf-8')
|
53
|
+
Streamly.head('localhost:4567') do |chunk|
|
54
|
+
chunk.encoding.should eql(Encoding.default_internal)
|
55
|
+
end
|
56
|
+
Encoding.default_internal = Encoding.find('us-ascii')
|
57
|
+
Streamly.head('localhost:4567') do |chunk|
|
58
|
+
chunk.encoding.should eql(Encoding.default_internal)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
24
62
|
end
|
25
63
|
end
|
26
|
-
|
64
|
+
|
27
65
|
context "GET" do
|
28
|
-
|
29
|
-
|
30
|
-
|
66
|
+
context "basic" do
|
67
|
+
it "should perform a basic request" do
|
68
|
+
resp = Streamly.get('localhost:4567/?name=brian')
|
69
|
+
resp.should eql(@response)
|
70
|
+
end
|
71
|
+
|
72
|
+
if RUBY_VERSION =~ /^1.9/
|
73
|
+
it "should default to utf-8 if Encoding.default_internal is nil" do
|
74
|
+
Encoding.default_internal = nil
|
75
|
+
Streamly.get('localhost:4567').encoding.should eql(Encoding.find('utf-8'))
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should use Encoding.default_internal" do
|
79
|
+
Encoding.default_internal = Encoding.find('utf-8')
|
80
|
+
Streamly.get('localhost:4567').encoding.should eql(Encoding.default_internal)
|
81
|
+
Encoding.default_internal = Encoding.find('us-ascii')
|
82
|
+
Streamly.get('localhost:4567').encoding.should eql(Encoding.default_internal)
|
83
|
+
end
|
84
|
+
end
|
31
85
|
end
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
86
|
+
|
87
|
+
context "streaming" do
|
88
|
+
it "should perform a basic request and stream the response to the caller" do
|
89
|
+
streamed_response = ''
|
90
|
+
resp = Streamly.get('localhost:4567/?name=brian') do |chunk|
|
91
|
+
chunk.should_not be_empty
|
92
|
+
streamed_response << chunk
|
93
|
+
end
|
94
|
+
resp.should be_nil
|
95
|
+
streamed_response.should eql(@response)
|
96
|
+
end
|
97
|
+
|
98
|
+
if RUBY_VERSION =~ /^1.9/
|
99
|
+
it "should default to utf-8 if Encoding.default_internal is nil" do
|
100
|
+
Encoding.default_internal = nil
|
101
|
+
Streamly.get('localhost:4567') do |chunk|
|
102
|
+
chunk.encoding.should eql(Encoding.find('utf-8'))
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
it "should use Encoding.default_internal" do
|
107
|
+
Encoding.default_internal = Encoding.find('utf-8')
|
108
|
+
Streamly.get('localhost:4567') do |chunk|
|
109
|
+
chunk.encoding.should eql(Encoding.default_internal)
|
110
|
+
end
|
111
|
+
Encoding.default_internal = Encoding.find('us-ascii')
|
112
|
+
Streamly.get('localhost:4567') do |chunk|
|
113
|
+
chunk.encoding.should eql(Encoding.default_internal)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
41
117
|
end
|
42
118
|
end
|
43
|
-
|
119
|
+
|
44
120
|
context "POST" do
|
45
|
-
|
46
|
-
|
47
|
-
|
121
|
+
context "basic" do
|
122
|
+
it "should perform a basic request" do
|
123
|
+
resp = Streamly.post('localhost:4567', 'name=brian')
|
124
|
+
resp.should eql(@response)
|
125
|
+
end
|
126
|
+
|
127
|
+
if RUBY_VERSION =~ /^1.9/
|
128
|
+
it "should default to utf-8 if Encoding.default_internal is nil" do
|
129
|
+
Encoding.default_internal = nil
|
130
|
+
Streamly.post('localhost:4567', 'name=brian').encoding.should eql(Encoding.find('utf-8'))
|
131
|
+
end
|
132
|
+
|
133
|
+
it "should use Encoding.default_internal" do
|
134
|
+
Encoding.default_internal = Encoding.find('utf-8')
|
135
|
+
Streamly.post('localhost:4567', 'name=brian').encoding.should eql(Encoding.default_internal)
|
136
|
+
Encoding.default_internal = Encoding.find('us-ascii')
|
137
|
+
Streamly.post('localhost:4567', 'name=brian').encoding.should eql(Encoding.default_internal)
|
138
|
+
end
|
139
|
+
end
|
48
140
|
end
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
141
|
+
|
142
|
+
context "streaming" do
|
143
|
+
it "should perform a basic request and stream the response to the caller" do
|
144
|
+
streamed_response = ''
|
145
|
+
resp = Streamly.post('localhost:4567', 'name=brian') do |chunk|
|
146
|
+
chunk.should_not be_empty
|
147
|
+
streamed_response << chunk
|
148
|
+
end
|
149
|
+
resp.should be_nil
|
150
|
+
streamed_response.should eql(@response)
|
151
|
+
end
|
152
|
+
|
153
|
+
if RUBY_VERSION =~ /^1.9/
|
154
|
+
it "should default to utf-8 if Encoding.default_internal is nil" do
|
155
|
+
Encoding.default_internal = nil
|
156
|
+
Streamly.post('localhost:4567', 'name=brian') do |chunk|
|
157
|
+
chunk.encoding.should eql(Encoding.find('utf-8'))
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
it "should use Encoding.default_internal" do
|
162
|
+
Encoding.default_internal = Encoding.find('utf-8')
|
163
|
+
Streamly.post('localhost:4567', 'name=brian') do |chunk|
|
164
|
+
chunk.encoding.should eql(Encoding.default_internal)
|
165
|
+
end
|
166
|
+
Encoding.default_internal = Encoding.find('us-ascii')
|
167
|
+
Streamly.post('localhost:4567', 'name=brian') do |chunk|
|
168
|
+
chunk.encoding.should eql(Encoding.default_internal)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
58
172
|
end
|
59
173
|
end
|
60
|
-
|
174
|
+
|
61
175
|
context "PUT" do
|
62
|
-
|
63
|
-
|
64
|
-
|
176
|
+
context "basic" do
|
177
|
+
it "should perform a basic request" do
|
178
|
+
resp = Streamly.put('localhost:4567', 'name=brian')
|
179
|
+
resp.should eql(@response)
|
180
|
+
end
|
181
|
+
|
182
|
+
if RUBY_VERSION =~ /^1.9/
|
183
|
+
it "should default to utf-8 if Encoding.default_internal is nil" do
|
184
|
+
Encoding.default_internal = nil
|
185
|
+
Streamly.put('localhost:4567', 'name=brian').encoding.should eql(Encoding.find('utf-8'))
|
186
|
+
end
|
187
|
+
|
188
|
+
it "should use Encoding.default_internal" do
|
189
|
+
Encoding.default_internal = Encoding.find('utf-8')
|
190
|
+
Streamly.put('localhost:4567', 'name=brian').encoding.should eql(Encoding.default_internal)
|
191
|
+
Encoding.default_internal = Encoding.find('us-ascii')
|
192
|
+
Streamly.put('localhost:4567', 'name=brian').encoding.should eql(Encoding.default_internal)
|
193
|
+
end
|
194
|
+
end
|
65
195
|
end
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
196
|
+
|
197
|
+
context "streaming" do
|
198
|
+
it "should perform a basic request and stream the response to the caller" do
|
199
|
+
streamed_response = ''
|
200
|
+
resp = Streamly.put('localhost:4567', 'name=brian') do |chunk|
|
201
|
+
chunk.should_not be_empty
|
202
|
+
streamed_response << chunk
|
203
|
+
end
|
204
|
+
resp.should be_nil
|
205
|
+
streamed_response.should eql(@response)
|
206
|
+
end
|
207
|
+
|
208
|
+
if RUBY_VERSION =~ /^1.9/
|
209
|
+
it "should default to utf-8 if Encoding.default_internal is nil" do
|
210
|
+
Encoding.default_internal = nil
|
211
|
+
Streamly.put('localhost:4567', 'name=brian') do |chunk|
|
212
|
+
chunk.encoding.should eql(Encoding.find('utf-8'))
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
it "should use Encoding.default_internal" do
|
217
|
+
Encoding.default_internal = Encoding.find('utf-8')
|
218
|
+
Streamly.put('localhost:4567', 'name=brian') do |chunk|
|
219
|
+
chunk.encoding.should eql(Encoding.default_internal)
|
220
|
+
end
|
221
|
+
Encoding.default_internal = Encoding.find('us-ascii')
|
222
|
+
Streamly.put('localhost:4567', 'name=brian') do |chunk|
|
223
|
+
chunk.encoding.should eql(Encoding.default_internal)
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
75
227
|
end
|
76
228
|
end
|
77
|
-
|
229
|
+
|
78
230
|
context "DELETE" do
|
79
|
-
|
80
|
-
|
231
|
+
context "basic" do
|
232
|
+
it "should perform a basic request" do
|
233
|
+
resp = Streamly.delete('localhost:4567/?name=brian').should eql(@response)
|
234
|
+
end
|
235
|
+
|
236
|
+
if RUBY_VERSION =~ /^1.9/
|
237
|
+
it "should default to utf-8 if Encoding.default_internal is nil" do
|
238
|
+
Encoding.default_internal = nil
|
239
|
+
Streamly.delete('localhost:4567/?name=brian').encoding.should eql(Encoding.find('utf-8'))
|
240
|
+
end
|
241
|
+
|
242
|
+
it "should use Encoding.default_internal" do
|
243
|
+
Encoding.default_internal = Encoding.find('utf-8')
|
244
|
+
Streamly.delete('localhost:4567/?name=brian').encoding.should eql(Encoding.default_internal)
|
245
|
+
Encoding.default_internal = Encoding.find('us-ascii')
|
246
|
+
Streamly.delete('localhost:4567/?name=brian').encoding.should eql(Encoding.default_internal)
|
247
|
+
end
|
248
|
+
end
|
81
249
|
end
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
250
|
+
|
251
|
+
context "streaming" do
|
252
|
+
it "should perform a basic request and stream the response to the caller" do
|
253
|
+
streamed_response = ''
|
254
|
+
resp = Streamly.delete('localhost:4567/?name=brian') do |chunk|
|
255
|
+
chunk.should_not be_empty
|
256
|
+
streamed_response << chunk
|
257
|
+
end
|
258
|
+
resp.should be_nil
|
259
|
+
streamed_response.should eql(@response)
|
260
|
+
end
|
261
|
+
|
262
|
+
if RUBY_VERSION =~ /^1.9/
|
263
|
+
it "should default to utf-8 if Encoding.default_internal is nil" do
|
264
|
+
Encoding.default_internal = nil
|
265
|
+
Streamly.delete('localhost:4567/?name=brian') do |chunk|
|
266
|
+
chunk.encoding.should eql(Encoding.find('utf-8'))
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
it "should use Encoding.default_internal" do
|
271
|
+
Encoding.default_internal = Encoding.find('utf-8')
|
272
|
+
Streamly.delete('localhost:4567/?name=brian') do |chunk|
|
273
|
+
chunk.encoding.should eql(Encoding.default_internal)
|
274
|
+
end
|
275
|
+
Encoding.default_internal = Encoding.find('us-ascii')
|
276
|
+
Streamly.delete('localhost:4567/?name=brian') do |chunk|
|
277
|
+
chunk.encoding.should eql(Encoding.default_internal)
|
278
|
+
end
|
279
|
+
end
|
280
|
+
end
|
91
281
|
end
|
92
282
|
end
|
93
283
|
end
|
File without changes
|
data/spec/spec_helper.rb
CHANGED
data/streamly.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{streamly}
|
8
|
-
s.version = "0.1.
|
8
|
+
s.version = "0.1.4"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Brian Lopez"]
|
12
|
-
s.date = %q{2010-02
|
12
|
+
s.date = %q{2010-09-02}
|
13
13
|
s.email = %q{seniorlopez@gmail.com}
|
14
14
|
s.extensions = ["ext/extconf.rb"]
|
15
15
|
s.extra_rdoc_files = [
|
@@ -40,7 +40,7 @@ Gem::Specification.new do |s|
|
|
40
40
|
"lib/streamly.rb",
|
41
41
|
"spec/rcov.opts",
|
42
42
|
"spec/requests/request_spec.rb",
|
43
|
-
"spec/
|
43
|
+
"spec/server.rb",
|
44
44
|
"spec/spec.opts",
|
45
45
|
"spec/spec_helper.rb",
|
46
46
|
"streamly.gemspec"
|
@@ -49,11 +49,11 @@ Gem::Specification.new do |s|
|
|
49
49
|
s.rdoc_options = ["--charset=UTF-8"]
|
50
50
|
s.require_paths = ["lib", "ext"]
|
51
51
|
s.rubyforge_project = %q{streamly}
|
52
|
-
s.rubygems_version = %q{1.3.
|
52
|
+
s.rubygems_version = %q{1.3.7}
|
53
53
|
s.summary = %q{A streaming REST client for Ruby, in C.}
|
54
54
|
s.test_files = [
|
55
55
|
"spec/requests/request_spec.rb",
|
56
|
-
"spec/
|
56
|
+
"spec/server.rb",
|
57
57
|
"spec/spec_helper.rb",
|
58
58
|
"examples/basic/delete.rb",
|
59
59
|
"examples/basic/get.rb",
|
@@ -71,7 +71,7 @@ Gem::Specification.new do |s|
|
|
71
71
|
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
72
72
|
s.specification_version = 3
|
73
73
|
|
74
|
-
if Gem::Version.new(Gem::
|
74
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
75
75
|
else
|
76
76
|
end
|
77
77
|
else
|