rest-core 2.1.0 → 2.1.1
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 +13 -0
- data/Rakefile +1 -1
- data/lib/rest-core/engine/em-http-request.rb +34 -24
- data/lib/rest-core/engine/rest-client.rb +23 -23
- data/lib/rest-core/util/payload.rb +34 -27
- data/lib/rest-core/version.rb +1 -1
- data/rest-core.gemspec +3 -3
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5cc0c6118d2d5169988871b31d9b5544e2f28f60
|
4
|
+
data.tar.gz: c73e366ba7c4cdbdec4a5a76528ed5d8df21aed4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c175b2f84c14257fe189ae82bee8f1d3a2bd205ac4da36ab8b0b596ccfdf47253d05b8cb4940c4ebe47e770385ed282b6dfadf53db04a1fba67adc4975ae177e
|
7
|
+
data.tar.gz: 53cd1bed753213a3a27637ceb85acf9577504aaa48cf0b760c48c20a6cd35c87f96f8b8c2dc438b568adc8404d1b4c19066dbb5efc6c40871d5ea91e78cd43e5
|
data/CHANGES.md
CHANGED
@@ -1,5 +1,18 @@
|
|
1
1
|
# CHANGES
|
2
2
|
|
3
|
+
## rest-core 2.1.1 -- 2013-05-21
|
4
|
+
|
5
|
+
### Bugs fixes
|
6
|
+
|
7
|
+
* Fixed em-http-request support.
|
8
|
+
|
9
|
+
### Enhancement
|
10
|
+
|
11
|
+
* [`Payload`] Now it is a class rather than a module.
|
12
|
+
* [`Paylaod`] Introduced `Payload.generate_with_headers`.
|
13
|
+
* [`Paylaod`] Give a `nil` if payload passing to `Payload.generate` should
|
14
|
+
not have any payload at all.
|
15
|
+
|
3
16
|
## rest-core 2.1.0 -- 2013-05-08
|
4
17
|
|
5
18
|
### Incompatible changes
|
data/Rakefile
CHANGED
@@ -24,7 +24,7 @@ task 'gem:spec' do
|
|
24
24
|
s.email = ['dev (XD) cardinalblue.com']
|
25
25
|
|
26
26
|
s.post_install_message = <<-MARKDOWN
|
27
|
-
# [rest-core] Incompatible changes for POST requests:
|
27
|
+
# [rest-core] Since 2.1.0, Incompatible changes for POST requests:
|
28
28
|
|
29
29
|
* We no longer support Rails-like POST payload, like translating
|
30
30
|
`{:foo => [1, 2]}` to `'foo[]=1&foo[]=2'`. It would now be translated to
|
@@ -20,41 +20,37 @@ class RestCore::EmHttpRequest
|
|
20
20
|
FUTURE => future)
|
21
21
|
end
|
22
22
|
|
23
|
-
def close client, tmpfile
|
24
|
-
(client.instance_variable_get(:@callbacks)||[]).clear
|
25
|
-
(client.instance_variable_get(:@errbacks )||[]).clear
|
26
|
-
client.close
|
27
|
-
if tmpfile.respond_to?(:close!) # tempfile
|
28
|
-
tmpfile.close!
|
29
|
-
elsif tmpfile.respond_to?(:close) # regular IO
|
30
|
-
tmpfile.close
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
23
|
def request future, env
|
35
|
-
payload = Payload.
|
36
|
-
|
37
|
-
args
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
24
|
+
payload, headers = Payload.generate_with_headers(env[REQUEST_PAYLOAD],
|
25
|
+
env[REQUEST_HEADERS])
|
26
|
+
args = if payload.nil?
|
27
|
+
{}
|
28
|
+
else
|
29
|
+
tmpfile = payload2file(payload)
|
30
|
+
if tmpfile.respond_to?(:path)
|
31
|
+
{:file => tmpfile.path}
|
32
|
+
else
|
33
|
+
{:body => tmpfile}
|
34
|
+
end
|
35
|
+
end.merge(:head => headers)
|
36
|
+
|
37
|
+
client = ::EventMachine::HttpRequest.new(request_uri(env)).
|
38
|
+
send(env[REQUEST_METHOD], args)
|
45
39
|
|
46
40
|
client.callback{
|
47
|
-
|
41
|
+
close_tmpfile(tmpfile)
|
48
42
|
future.on_load(client.response,
|
49
43
|
client.response_header.status,
|
50
44
|
client.response_header)}
|
51
45
|
|
52
46
|
client.errback{
|
53
|
-
|
47
|
+
close_client(client)
|
48
|
+
close_tmpfile(tmpfile)
|
54
49
|
future.on_error(client.error)}
|
55
50
|
|
56
51
|
env[TIMER].on_timeout{
|
57
|
-
|
52
|
+
close_client(client)
|
53
|
+
close_tmpfile(tmpfile)
|
58
54
|
future.on_error(env[TIMER].error)
|
59
55
|
} if env[TIMER]
|
60
56
|
end
|
@@ -77,4 +73,18 @@ class RestCore::EmHttpRequest
|
|
77
73
|
IO.copy_stream(io, tempfile)
|
78
74
|
tempfile
|
79
75
|
end
|
76
|
+
|
77
|
+
def close_client client
|
78
|
+
(client.instance_variable_get(:@callbacks)||[]).clear
|
79
|
+
(client.instance_variable_get(:@errbacks )||[]).clear
|
80
|
+
client.close
|
81
|
+
end
|
82
|
+
|
83
|
+
def close_tmpfile tmpfile
|
84
|
+
if tmpfile.respond_to?(:close!) # tempfile
|
85
|
+
tmpfile.close!
|
86
|
+
elsif tmpfile.respond_to?(:close) # regular IO
|
87
|
+
tmpfile.close
|
88
|
+
end
|
89
|
+
end
|
80
90
|
end
|
@@ -10,29 +10,8 @@ class RestCore::RestClient
|
|
10
10
|
def call env, &k
|
11
11
|
future = Future::FutureThread.new(env, k, env[ASYNC])
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
payload = Payload.generate(env[REQUEST_PAYLOAD])
|
16
|
-
headers = env[REQUEST_HEADERS].merge(payload.headers)
|
17
|
-
res = ::RestClient::Request.execute(:method => env[REQUEST_METHOD],
|
18
|
-
:url => request_uri(env) ,
|
19
|
-
:payload => payload ,
|
20
|
-
:headers => headers ,
|
21
|
-
:max_redirects => 0)
|
22
|
-
future.on_load(res.body, res.code, normalize_headers(res.raw_headers))
|
23
|
-
|
24
|
-
rescue ::RestClient::Exception => e
|
25
|
-
if res = e.response
|
26
|
-
# we don't want to raise an exception for 404 requests
|
27
|
-
future.on_load(res.body, res.code,
|
28
|
-
normalize_headers(res.raw_headers))
|
29
|
-
else
|
30
|
-
future.on_error(e)
|
31
|
-
end
|
32
|
-
rescue Exception => e
|
33
|
-
future.on_error(e)
|
34
|
-
end
|
35
|
-
}
|
13
|
+
# we can implement thread pool in the future
|
14
|
+
t = future.wrap{ request(future, env) }
|
36
15
|
|
37
16
|
env[TIMER].on_timeout{
|
38
17
|
t.kill
|
@@ -45,6 +24,27 @@ class RestCore::RestClient
|
|
45
24
|
FUTURE => future)
|
46
25
|
end
|
47
26
|
|
27
|
+
def request future, env
|
28
|
+
payload, headers = Payload.generate_with_headers(env[REQUEST_PAYLOAD],
|
29
|
+
env[REQUEST_HEADERS])
|
30
|
+
res = ::RestClient::Request.execute(:method => env[REQUEST_METHOD],
|
31
|
+
:url => request_uri(env) ,
|
32
|
+
:payload => payload ,
|
33
|
+
:headers => headers ,
|
34
|
+
:max_redirects => 0)
|
35
|
+
future.on_load(res.body, res.code, normalize_headers(res.raw_headers))
|
36
|
+
|
37
|
+
rescue ::RestClient::Exception => e
|
38
|
+
if res = e.response
|
39
|
+
# we don't want to raise an exception for 404 requests
|
40
|
+
future.on_load(res.body, res.code, normalize_headers(res.raw_headers))
|
41
|
+
else
|
42
|
+
future.on_error(e)
|
43
|
+
end
|
44
|
+
rescue Exception => e
|
45
|
+
future.on_error(e)
|
46
|
+
end
|
47
|
+
|
48
48
|
def normalize_headers raw_headers
|
49
49
|
raw_headers.inject({}){ |r, (k, v)|
|
50
50
|
r[k.to_s.upcase.tr('-', '_')] = if v.kind_of?(Array) && v.size == 1
|
@@ -9,11 +9,19 @@ require 'stringio'
|
|
9
9
|
require 'tempfile'
|
10
10
|
|
11
11
|
module RestCore; end
|
12
|
-
|
12
|
+
class RestCore::Payload
|
13
13
|
include RestCore
|
14
|
-
module_function
|
15
14
|
|
16
|
-
def
|
15
|
+
def self.generate_with_headers payload, headers
|
16
|
+
h = if p = generate(payload)
|
17
|
+
p.headers.merge(headers)
|
18
|
+
else
|
19
|
+
headers
|
20
|
+
end
|
21
|
+
[p, h]
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.generate payload
|
17
25
|
if payload.respond_to?(:read)
|
18
26
|
Streamed.new(payload)
|
19
27
|
|
@@ -21,7 +29,10 @@ module RestCore::Payload
|
|
21
29
|
StreamedString.new(payload)
|
22
30
|
|
23
31
|
elsif payload.kind_of?(Hash)
|
24
|
-
if
|
32
|
+
if payload.empty?
|
33
|
+
nil
|
34
|
+
|
35
|
+
elsif Middleware.contain_binary?(payload)
|
25
36
|
Multipart.new(payload)
|
26
37
|
|
27
38
|
else
|
@@ -34,34 +45,30 @@ module RestCore::Payload
|
|
34
45
|
end
|
35
46
|
end
|
36
47
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
48
|
+
# Payload API
|
49
|
+
attr_reader :io
|
50
|
+
alias_method :to_io, :io
|
51
|
+
|
52
|
+
def initialize payload; @io = payload ; end
|
53
|
+
def read bytes=nil; io.read(bytes) ; end
|
54
|
+
def close ; io.close unless closed?; end
|
55
|
+
def closed? ; io.closed? ; end
|
56
|
+
def headers ; {} ; end
|
57
|
+
|
58
|
+
def size
|
59
|
+
if io.respond_to?(:size)
|
60
|
+
io.size
|
61
|
+
elsif io.respond_to?(:stat)
|
62
|
+
io.stat.size
|
63
|
+
else
|
64
|
+
0
|
47
65
|
end
|
66
|
+
end
|
48
67
|
|
68
|
+
class Streamed < Payload
|
49
69
|
def headers
|
50
70
|
{'Content-Length' => size.to_s}
|
51
71
|
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
72
|
end
|
66
73
|
|
67
74
|
class StreamedString < Streamed
|
data/lib/rest-core/version.rb
CHANGED
data/rest-core.gemspec
CHANGED
@@ -2,13 +2,13 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = "rest-core"
|
5
|
-
s.version = "2.1.
|
5
|
+
s.version = "2.1.1"
|
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-05-
|
11
|
+
s.date = "2013-05-21"
|
12
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 = [
|
@@ -97,7 +97,7 @@ Gem::Specification.new do |s|
|
|
97
97
|
"test/test_wrapper.rb"]
|
98
98
|
s.homepage = "https://github.com/cardinalblue/rest-core"
|
99
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"
|
100
|
+
s.post_install_message = "# [rest-core] Since 2.1.0, 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"
|
101
101
|
s.require_paths = ["lib"]
|
102
102
|
s.rubygems_version = "2.0.3"
|
103
103
|
s.summary = "Modular Ruby clients interface for REST APIs."
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rest-core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.1.
|
4
|
+
version: 2.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Cardinal Blue
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-05-
|
12
|
+
date: 2013-05-21 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rest-client
|
@@ -130,7 +130,7 @@ licenses:
|
|
130
130
|
- Apache License 2.0
|
131
131
|
metadata: {}
|
132
132
|
post_install_message: |
|
133
|
-
# [rest-core] Incompatible changes for POST requests:
|
133
|
+
# [rest-core] Since 2.1.0, Incompatible changes for POST requests:
|
134
134
|
|
135
135
|
* We no longer support Rails-like POST payload, like translating
|
136
136
|
`{:foo => [1, 2]}` to `'foo[]=1&foo[]=2'`. It would now be translated to
|