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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b126115b38499438877d2c55fe68b14c3d9989bd
4
- data.tar.gz: 6ba8f157a2025d94fe326767dc36823d11585854
3
+ metadata.gz: 5cc0c6118d2d5169988871b31d9b5544e2f28f60
4
+ data.tar.gz: c73e366ba7c4cdbdec4a5a76528ed5d8df21aed4
5
5
  SHA512:
6
- metadata.gz: 14b1c0022f58a2af1a26bb0126159937b0540ee462bb6fe96db3fa777e0ba7cd14183e6ff8e051e45acc65c02708a69f51b31ad3371d0792e4124c2811029720
7
- data.tar.gz: 4a3e037e2b30b77c57e7b030c05322389c1a585766ba414d137ce790c8c3e0b1c141c281a1dd664d07e47150a1f9f2a963059e42ffdad91d63549afd07ce095f
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.generate(env[REQUEST_PAYLOAD])
36
- tmpfile = payload2file(payload)
37
- args = if tmpfile.respond_to?(:path)
38
- {:file => tmpfile.path}
39
- else
40
- {:body => tmpfile}
41
- end
42
- client = ::EventMachine::HttpRequest.new(request_uri(env)).send(
43
- env[REQUEST_METHOD], args.merge(
44
- :head => payload.headers.merge(env[REQUEST_HEADERS])))
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
- close(client, tmpfile)
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
- close(client, tmpfile)
47
+ close_client(client)
48
+ close_tmpfile(tmpfile)
54
49
  future.on_error(client.error)}
55
50
 
56
51
  env[TIMER].on_timeout{
57
- close(client, tmpfile)
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
- t = future.wrap{ # we can implement thread pool in the future
14
- begin
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
- module RestCore::Payload
12
+ class RestCore::Payload
13
13
  include RestCore
14
- module_function
15
14
 
16
- def generate payload
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 Middleware.contain_binary?(payload)
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
- 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)
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
@@ -1,4 +1,4 @@
1
1
 
2
2
  module RestCore
3
- VERSION = '2.1.0'
3
+ VERSION = '2.1.1'
4
4
  end
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.0"
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-08"
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.0
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-08 00:00:00.000000000 Z
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