restfulie 1.0.0.beta1 → 1.0.0.beta4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (80) hide show
  1. data/Gemfile +8 -10
  2. data/Gemfile.lock +59 -85
  3. data/README.textile +22 -57
  4. data/Rakefile +1 -3
  5. data/lib/restfulie/client/cache/basic.rb +7 -5
  6. data/lib/restfulie/client/cache/restrictions.rb +2 -0
  7. data/lib/restfulie/client/dsl.rb +7 -22
  8. data/lib/restfulie/client/entry_point.rb +1 -1
  9. data/lib/restfulie/client/ext/link_ext.rb +11 -0
  10. data/lib/restfulie/client/ext/open_search_ext.rb +26 -0
  11. data/lib/restfulie/client/ext.rb +3 -0
  12. data/lib/restfulie/client/feature/base_request.rb +2 -2
  13. data/lib/restfulie/client/feature/cache.rb +2 -2
  14. data/lib/restfulie/client/feature/conneg_when_unaccepted.rb +25 -0
  15. data/lib/restfulie/client/feature/enhance_response.rb +2 -2
  16. data/lib/restfulie/client/feature/follow_request.rb +2 -2
  17. data/lib/restfulie/client/feature/history_request.rb +2 -2
  18. data/lib/restfulie/client/feature/retry_when_unavailable.rb +25 -0
  19. data/lib/restfulie/client/feature/serialize_body.rb +7 -4
  20. data/lib/restfulie/client/feature/setup_header.rb +2 -2
  21. data/lib/restfulie/client/feature/throw_error.rb +2 -2
  22. data/lib/restfulie/client/http/link_header.rb +39 -0
  23. data/lib/restfulie/client/http/response_holder.rb +2 -2
  24. data/lib/restfulie/client/stack_navigator.rb +39 -0
  25. data/lib/restfulie/client.rb +3 -5
  26. data/lib/restfulie/common.rb +5 -6
  27. data/lib/restfulie/server/action_controller/base.rb +1 -1
  28. data/lib/restfulie/server/core_ext/array.rb +1 -27
  29. data/lib/restfulie/server/tokamak.rb +6 -0
  30. data/lib/restfulie/server.rb +11 -10
  31. data/lib/restfulie/version.rb +1 -1
  32. metadata +24 -95
  33. data/lib/restfulie/client/ext/atom_ext.rb +0 -14
  34. data/lib/restfulie/client/ext/json_ext.rb +0 -16
  35. data/lib/restfulie/common/converter/atom/base.rb +0 -91
  36. data/lib/restfulie/common/converter/atom/builder.rb +0 -111
  37. data/lib/restfulie/common/converter/atom/helpers.rb +0 -17
  38. data/lib/restfulie/common/converter/atom.rb +0 -12
  39. data/lib/restfulie/common/converter/form_url_encoded.rb +0 -16
  40. data/lib/restfulie/common/converter/json/base.rb +0 -87
  41. data/lib/restfulie/common/converter/json/builder.rb +0 -102
  42. data/lib/restfulie/common/converter/json/helpers.rb +0 -17
  43. data/lib/restfulie/common/converter/json.rb +0 -12
  44. data/lib/restfulie/common/converter/open_search/descriptor.rb +0 -32
  45. data/lib/restfulie/common/converter/open_search.rb +0 -16
  46. data/lib/restfulie/common/converter/values.rb +0 -33
  47. data/lib/restfulie/common/converter/xml/base.rb +0 -63
  48. data/lib/restfulie/common/converter/xml/builder.rb +0 -113
  49. data/lib/restfulie/common/converter/xml/helpers.rb +0 -17
  50. data/lib/restfulie/common/converter/xml/link.rb +0 -30
  51. data/lib/restfulie/common/converter/xml/links.rb +0 -21
  52. data/lib/restfulie/common/converter/xml.rb +0 -14
  53. data/lib/restfulie/common/converter.rb +0 -43
  54. data/lib/restfulie/common/core_ext/hash.rb +0 -18
  55. data/lib/restfulie/common/core_ext.rb +0 -1
  56. data/lib/restfulie/common/links.rb +0 -9
  57. data/lib/restfulie/common/representation/atom/atom.rng +0 -597
  58. data/lib/restfulie/common/representation/atom/base.rb +0 -142
  59. data/lib/restfulie/common/representation/atom/category.rb +0 -41
  60. data/lib/restfulie/common/representation/atom/entry.rb +0 -59
  61. data/lib/restfulie/common/representation/atom/factory.rb +0 -43
  62. data/lib/restfulie/common/representation/atom/feed.rb +0 -110
  63. data/lib/restfulie/common/representation/atom/link.rb +0 -68
  64. data/lib/restfulie/common/representation/atom/person.rb +0 -48
  65. data/lib/restfulie/common/representation/atom/source.rb +0 -59
  66. data/lib/restfulie/common/representation/atom/tag_collection.rb +0 -38
  67. data/lib/restfulie/common/representation/atom/xml.rb +0 -90
  68. data/lib/restfulie/common/representation/atom.rb +0 -20
  69. data/lib/restfulie/common/representation/generic.rb +0 -22
  70. data/lib/restfulie/common/representation/json/base.rb +0 -27
  71. data/lib/restfulie/common/representation/json/keys_as_methods.rb +0 -74
  72. data/lib/restfulie/common/representation/json/link.rb +0 -29
  73. data/lib/restfulie/common/representation/json/link_collection.rb +0 -23
  74. data/lib/restfulie/common/representation/json.rb +0 -13
  75. data/lib/restfulie/common/representation/links.rb +0 -11
  76. data/lib/restfulie/common/representation.rb +0 -3
  77. data/lib/restfulie/server/action_view/helpers.rb +0 -50
  78. data/lib/restfulie/server/action_view/template_handlers/tokamak.rb +0 -21
  79. data/lib/restfulie/server/action_view/template_handlers.rb +0 -30
  80. data/lib/restfulie/server/action_view.rb +0 -10
data/Gemfile CHANGED
@@ -1,15 +1,10 @@
1
- # A sample Gemfile
2
1
  source :gemcutter
3
- #
4
- gem "rails", ">= 3.0.0"
5
- gem "libxml-ruby"
6
2
 
7
3
  gem "rack-conneg"
8
- gem "json_pure"
9
4
  gem "sqlite3-ruby"
10
- gem "yard"
11
-
12
- gem "respondie"
5
+ gem 'tokamak', ">= 1.0.0.beta4"
6
+ gem 'medie', ">= 1.0.0.beta4"
7
+ gem 'respondie', "~> 0.9.0"
13
8
 
14
9
  if RUBY_VERSION < "1.9"
15
10
  gem "ruby-debug"
@@ -17,9 +12,12 @@ else
17
12
  gem "ruby-debug19", :require => "ruby-debug"
18
13
  end
19
14
 
15
+ group :development do
16
+ gem "yard"
17
+ end
18
+
20
19
  group :test do
21
- gem "nokogiri"
22
- gem "rspec-rails", ">= 2.0.0.beta.19"
20
+ gem "rspec-rails", ">= 2.3.0"
23
21
  gem "rcov"
24
22
  gem "sinatra"
25
23
  gem "state_machine"
data/Gemfile.lock CHANGED
@@ -2,127 +2,101 @@ GEM
2
2
  remote: http://rubygems.org/
3
3
  specs:
4
4
  abstract (1.0.0)
5
- actionmailer (3.0.0)
6
- actionpack (= 3.0.0)
7
- mail (~> 2.2.5)
8
- actionpack (3.0.0)
9
- activemodel (= 3.0.0)
10
- activesupport (= 3.0.0)
5
+ actionpack (3.0.3)
6
+ activemodel (= 3.0.3)
7
+ activesupport (= 3.0.3)
11
8
  builder (~> 2.1.2)
12
9
  erubis (~> 2.6.6)
13
- i18n (~> 0.4.1)
10
+ i18n (~> 0.4)
14
11
  rack (~> 1.2.1)
15
- rack-mount (~> 0.6.12)
16
- rack-test (~> 0.5.4)
12
+ rack-mount (~> 0.6.13)
13
+ rack-test (~> 0.5.6)
17
14
  tzinfo (~> 0.3.23)
18
- activemodel (3.0.0)
19
- activesupport (= 3.0.0)
15
+ activemodel (3.0.3)
16
+ activesupport (= 3.0.3)
20
17
  builder (~> 2.1.2)
21
- i18n (~> 0.4.1)
22
- activerecord (3.0.0)
23
- activemodel (= 3.0.0)
24
- activesupport (= 3.0.0)
25
- arel (~> 1.0.0)
26
- tzinfo (~> 0.3.23)
27
- activeresource (3.0.0)
28
- activemodel (= 3.0.0)
29
- activesupport (= 3.0.0)
30
- activesupport (3.0.0)
31
- arel (1.0.1)
32
- activesupport (~> 3.0.0)
18
+ i18n (~> 0.4)
19
+ activesupport (3.0.3)
33
20
  builder (2.1.2)
34
- columnize (0.3.1)
21
+ columnize (0.3.2)
35
22
  diff-lcs (1.1.2)
36
23
  erubis (2.6.6)
37
24
  abstract (>= 1.0.0)
38
- fakeweb (1.2.8)
39
- hoe (2.6.1)
25
+ fakeweb (1.3.0)
26
+ hoe (2.8.0)
40
27
  rake (>= 0.8.7)
41
- rubyforge (>= 2.0.4)
42
- i18n (0.4.1)
28
+ i18n (0.5.0)
43
29
  json_pure (1.4.6)
44
- libxml-ruby (1.1.4)
45
30
  linecache (0.43)
46
- mail (2.2.5)
47
- activesupport (>= 2.3.6)
48
- mime-types
49
- treetop (>= 1.4.5)
50
- mime-types (1.16)
51
- nokogiri (1.4.3.1)
52
- polyglot (0.3.1)
31
+ medie (1.0.0.beta4)
32
+ actionpack (>= 3.0.0)
33
+ activesupport
34
+ json_pure
35
+ methodize
36
+ methodize (0.1)
37
+ nokogiri (1.4.4)
53
38
  rack (1.2.1)
54
39
  rack-conneg (0.1.4)
55
40
  rack (>= 1.0)
56
- rack-mount (0.6.12)
41
+ rack-mount (0.6.13)
57
42
  rack (>= 1.0.0)
58
- rack-test (0.5.4)
43
+ rack-test (0.5.7)
59
44
  rack (>= 1.0)
60
- rails (3.0.0)
61
- actionmailer (= 3.0.0)
62
- actionpack (= 3.0.0)
63
- activerecord (= 3.0.0)
64
- activeresource (= 3.0.0)
65
- activesupport (= 3.0.0)
66
- bundler (~> 1.0.0)
67
- railties (= 3.0.0)
68
- railties (3.0.0)
69
- actionpack (= 3.0.0)
70
- activesupport (= 3.0.0)
71
- rake (>= 0.8.4)
72
- thor (~> 0.14.0)
45
+ railties (3.0.3)
46
+ actionpack (= 3.0.3)
47
+ activesupport (= 3.0.3)
48
+ rake (>= 0.8.7)
49
+ thor (~> 0.14.4)
73
50
  rake (0.8.7)
74
- rcov (0.9.8)
51
+ rcov (0.9.9)
75
52
  respondie (0.9.0)
76
- rspec (2.0.0.beta.19)
77
- rspec-core (= 2.0.0.beta.19)
78
- rspec-expectations (= 2.0.0.beta.19)
79
- rspec-mocks (= 2.0.0.beta.19)
80
- rspec-core (2.0.0.beta.19)
81
- rspec-expectations (2.0.0.beta.19)
82
- diff-lcs (>= 1.1.2)
83
- rspec-mocks (2.0.0.beta.19)
84
- rspec-rails (2.0.0.beta.19)
85
- rspec (= 2.0.0.beta.19)
86
- webrat (>= 0.7.2.beta.1)
87
- ruby-debug (0.10.3)
53
+ rspec (2.3.0)
54
+ rspec-core (~> 2.3.0)
55
+ rspec-expectations (~> 2.3.0)
56
+ rspec-mocks (~> 2.3.0)
57
+ rspec-core (2.3.1)
58
+ rspec-expectations (2.3.0)
59
+ diff-lcs (~> 1.1.2)
60
+ rspec-mocks (2.3.0)
61
+ rspec-rails (2.3.1)
62
+ actionpack (~> 3.0)
63
+ activesupport (~> 3.0)
64
+ railties (~> 3.0)
65
+ rspec (~> 2.3.0)
66
+ ruby-debug (0.10.4)
88
67
  columnize (>= 0.1)
89
- ruby-debug-base (~> 0.10.3.0)
90
- ruby-debug-base (0.10.3)
68
+ ruby-debug-base (~> 0.10.4.0)
69
+ ruby-debug-base (0.10.4)
91
70
  linecache (>= 0.3)
92
- rubyforge (2.0.4)
93
- json_pure (>= 1.1.7)
94
- sinatra (1.0)
95
- rack (>= 1.0)
96
- sqlite3-ruby (1.3.1)
71
+ sinatra (1.1.2)
72
+ rack (~> 1.1)
73
+ tilt (~> 1.2)
74
+ sqlite3-ruby (1.3.2)
97
75
  state_machine (0.9.4)
98
76
  test-unit (1.2.3)
99
77
  hoe (>= 1.5.1)
100
- thor (0.14.0)
101
- treetop (1.4.8)
102
- polyglot (>= 0.3.1)
78
+ thor (0.14.6)
79
+ tilt (1.2.1)
80
+ tokamak (1.1.1)
81
+ json_pure
82
+ nokogiri
103
83
  tzinfo (0.3.23)
104
- webrat (0.7.2.beta.1)
105
- nokogiri (>= 1.2.0)
106
- rack (>= 1.0)
107
- rack-test (>= 0.5.3)
108
- yard (0.5.8)
84
+ yard (0.6.4)
109
85
 
110
86
  PLATFORMS
111
87
  ruby
112
88
 
113
89
  DEPENDENCIES
114
90
  fakeweb
115
- json_pure
116
- libxml-ruby
117
- nokogiri
91
+ medie (>= 1.0.0.beta4)
118
92
  rack-conneg
119
- rails (>= 3.0.0)
120
93
  rcov
121
- respondie
122
- rspec-rails (>= 2.0.0.beta.19)
94
+ respondie (~> 0.9.0)
95
+ rspec-rails (>= 2.3.0)
123
96
  ruby-debug
124
97
  sinatra
125
98
  sqlite3-ruby
126
99
  state_machine
127
100
  test-unit (= 1.2.3)
101
+ tokamak (>= 1.0.0.beta4)
128
102
  yard
data/README.textile CHANGED
@@ -1,85 +1,50 @@
1
1
  h1. Web site
2
2
 
3
- Restfulie's website can be found at "http://restfulie.caelumobjects.com":http://restfulie.caelumobjects.com
4
- From there you can see some videos and read the "Restfulie from Scratch guide":http://restfulie.caelumobjects.com/caelumobjects-restful-rails.pdf.
3
+ "http://restfulie.caelumobjects.com":"Restfulie's site" has a lot of information on Restfulie itself
5
4
 
6
5
  h1. Quit pretending
7
6
 
8
- CRUD through HTTP is a good step forward to using resources and becoming RESTful, another step further into it is to make use of hypermedia and semantic meaningful media types: this gem allows you to do it really fast.
7
+ CRUD through HTTP and web services (aka Rest) in Rails is a good step forward to using resources and becoming RESTful, another step further into it is to make use of hypermedia and semantic meaningful media types: this gem allows you to do it really fast. Go go go!
9
8
 
10
- You can read the "article on using the web for real":http://guilhermesilveira.wordpress.com/2009/11/03/quit-pretending-use-the-web-for-real-restfulie/ which gives an introduction to hypermedia/resources/services.
9
+ h2. Bite me!
11
10
 
12
- h2. Why would I use restfulie?
13
-
14
- # Easy --> writing hypermedia and semantic meaningful media type aware clients
15
- # Small -> it's not a bloated solution with a huge list of APIs
16
- # HATEOAS --> clients you are unaware of will not bother if you change
17
- # HATEOAS --> consumed resources will not affect your software whenever they change their flow
18
- # Adaptability --> clients are able to adapt to your changes
19
-
20
- h2. Simple server example
21
-
22
- In the server side, all you need to do is notify inherited_resources which media types you are able to represent your resource:
11
+ One liners for your pleasure. First, how to let restfulie know which media types you can handle:
23
12
 
24
13
  <pre>
25
- class OrdersController < ApplicationController
26
- include Restfulie::Server::ActionController::Base
27
-
14
+ class ItemsController < ...
28
15
  respond_to :atom, :html, :xml, :commerce, :opensearch
29
-
30
- def index
31
- respond_with @orders = Order.all
32
- end
33
-
34
- def show
35
- respond_with @order = Order.find(params[:id])
36
- end
37
-
38
- end
16
+ end
39
17
  </pre>
40
18
 
41
- That's it. Restfulie will take care of rendering a valid representation according to content negotiation. You can configure the rendering process through a custom tokamak view:
19
+ Now let's handle them all:
42
20
 
43
21
  <pre>
44
- collection(@orders) do |collection|
45
- collection.values do |value|
46
- value.id = orders_url
22
+ def index
23
+ respond_with @orders = Order.all
47
24
  end
48
-
49
- collection.link("create", orders_url)
50
- collection.members
51
- end
52
25
  </pre>
53
26
 
54
- You can go through an entire application by "watching this video":http://guilhermesilveira.wordpress.com or "downloading an example application contained within the restfulie ":http://github.com/caelum/restfulie/tree/master/full-examples/rest_from_scratch/
55
-
56
- h2. Simple client example
57
-
58
- The following example is a partial REST client implementation that navigates through some relations:
27
+ And what is the *first* difference between simple web services with Rails and a REST architecture? Let's add hypermedia to the game:
59
28
 
60
29
  <pre>
61
- order = Restfulie.at('http://localhost:3000/orders/1').get!
62
- order.items.each { |item| puts items }
63
- receipt = order.payment.post! { :amount => 500 }
64
- puts receipt.id
30
+ memeber(@order) do |order|
31
+ order.link "payment", payment_url(order)
32
+ end
65
33
  </pre>
66
34
 
67
- In order to create a full REST client, "watch this video":http://guilhermesilveira.wordpress.com.
35
+ There you go, hypermedia, on the fly. You can also throw in link headers and much more fun for your life when maintaining your services. Lets grab it and navigate!
68
36
 
69
- h2. Full examples
70
-
71
- You can view an entire application running Restfulie under *spec/integration/order/server* and *spec/integration/order/client* in this git repository.
72
-
73
- "You can also download a full example of a REST based agent and server":http://github.com/caelum/restfulie/tree/master/full-examples/rest_from_scratch/ using Restfulie, according to the Rest Architecture Maturity Model.
37
+ <pre>
38
+ response = Restfulie.at('http://localhost:3030/orders').get
39
+ puts response.code
74
40
 
75
- h2. Documentation
41
+ orders = response.resource
42
+ response = orders.link(payment).follow.post {creditcard => 4444}
43
+ </pre>
76
44
 
77
- Appart from the simple server and client examples provided here, you can find the following links useful:
45
+ That was it for your first hypermedia introduction with Restfulie. Now its time for the real deal.
78
46
 
79
- * "RDocs":http://rdoc.info/projects/caelum/restfulie
80
- * "Official website":http://restfulie.caelumobjects.com
81
- * "How-tos":http://restfulie.caelumobjects.com/caelumobjects-restful-rails.pdf
82
- * "Buying through Rest: Rest to the enterprise (video)":http://guilhermesilveira.wordpress.com/2010/04/13/buying-through-rest-applying-rest-to-the-enterprise/
47
+ Download it, install it, use it, ask questions in the mailing list and read the documentation on Restfulie's website!
83
48
 
84
49
  h2. Installing
85
50
 
data/Rakefile CHANGED
@@ -11,7 +11,7 @@ require File.expand_path('lib/restfulie')
11
11
  GEM = "restfulie"
12
12
  GEM_VERSION = Restfulie::VERSION
13
13
  SUMMARY = "Hypermedia aware resource based library in ruby (client side) and ruby on rails (server side)."
14
- AUTHOR = "Guilherme Silveira, Caue Guerra, Luis Cipriani, Everton Ribeiro, George Guimaraes, Paulo Ahagon, Several contributors"
14
+ AUTHOR = "Guilherme Silveira, Caue Guerra, Luis Cipriani, Everton Ribeiro, George Guimaraes, Paulo Ahagon, and many more!"
15
15
  EMAIL = "guilherme.silveira@caelum.com.br"
16
16
  HOMEPAGE = "http://restfulie.caelumobjects.com"
17
17
 
@@ -23,8 +23,6 @@ spec = Gem::Specification.new do |s|
23
23
  s.require_paths = ['lib']
24
24
  s.files = FileList['lib/**/*.rb', '[A-Z]*', 'lib/**/*.rng'].to_a
25
25
  s.add_dependency("nokogiri", [">= 1.4.2"])
26
- s.add_dependency("actionpack", [">= 2.3.2"])
27
- s.add_dependency("activesupport", [">= 2.3.2"])
28
26
  s.add_dependency("json_pure", [">= 1.2.4"])
29
27
 
30
28
  s.author = AUTHOR
@@ -16,7 +16,6 @@ module Restfulie::Client::Cache
16
16
 
17
17
  def get(key, request)
18
18
 
19
- # debugger
20
19
  response = cache_get(key, request)
21
20
  return nil if response.nil?
22
21
 
@@ -34,6 +33,13 @@ module Restfulie::Client::Cache
34
33
  cache.clear
35
34
  end
36
35
 
36
+ protected
37
+
38
+ # allows you to redefine the cache store
39
+ def cache
40
+ Restfulie::Client.cache_store
41
+ end
42
+
37
43
  private
38
44
 
39
45
  # allows response enhancement when the cache was hit with it
@@ -68,9 +74,5 @@ module Restfulie::Client::Cache
68
74
  nil
69
75
  end
70
76
 
71
- def cache
72
- Restfulie::Client.cache_store
73
- end
74
-
75
77
  end
76
78
  end
@@ -1,4 +1,6 @@
1
1
  module Restfulie::Client::Cache
2
+
3
+ # Cache restrictions that allow you to cache this response or not
2
4
  module Restrictions
3
5
  class << self
4
6
 
@@ -13,9 +13,9 @@ module Restfulie::Client
13
13
  request :follow_request
14
14
  end
15
15
 
16
- def request(what)
16
+ def request(what, *args)
17
17
  req = "Restfulie::Client::Feature::#{what.to_s.classify}".constantize
18
- @requests << req
18
+ @requests << {:type => req, :args => args}
19
19
  self
20
20
  end
21
21
 
@@ -32,7 +32,7 @@ module Restfulie::Client
32
32
  end
33
33
  if Restfulie::Client::Feature.const_defined? "#{sym.to_s.classify}Request"
34
34
  loaded = true
35
- request "#{sym.to_s}Request"
35
+ request "#{sym.to_s}Request", *args
36
36
  end
37
37
  if loaded
38
38
  self
@@ -42,25 +42,10 @@ module Restfulie::Client
42
42
  end
43
43
 
44
44
  def request_flow(env = {})
45
- Parser.new(@requests).continue(self, nil, env)
45
+ Restfulie::Common::Logger.logger.debug "ready to execute request using stack #{@requests}"
46
+ StackNavigator.new(@requests).continue(self, env)
46
47
  end
47
48
 
48
- end
49
-
50
- class Parser
51
-
52
- def initialize(stack)
53
- @stack = stack.dup
54
- end
55
-
56
- def continue(request, response, env)
57
- current = @stack.pop
58
- if current.nil?
59
- return response
60
- end
61
- filter = current.new
62
- filter.execute(self, request, response, env)
63
- end
64
-
65
- end
49
+ end
50
+
66
51
  end
@@ -5,7 +5,7 @@ module Restfulie
5
5
  module HTTP::RecipeModule
6
6
  def recipe(converter_sym, options={}, &block)
7
7
  raise 'Undefined block' unless block_given?
8
- converter = "Restfulie::Common::Converter::#{converter_sym.to_s.camelize}".constantize
8
+ converter = "Tokamak::#{converter_sym.to_s.camelize}".constantize
9
9
  converter.describe_recipe(options[:name], &block)
10
10
  end
11
11
 
@@ -0,0 +1,11 @@
1
+ module Medie
2
+ class Link
3
+
4
+ # allows you to follow links by using restfulie
5
+ def follow
6
+ r = Restfulie.at(href)
7
+ r = r.as(content_type) if content_type
8
+ r
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,26 @@
1
+ module Medie
2
+ module OpenSearch
3
+ class Descriptor
4
+
5
+ def use(content_type)
6
+ uri = urls.find do |url|
7
+ url["type"]==content_type
8
+ end
9
+ return nil if uri.nil?
10
+
11
+ base_uri, params_pattern = extract_uri(uri)
12
+ Restfulie.at(base_uri).accepts(content_type).open_search.with_pattern(params_pattern)
13
+ end
14
+
15
+ private
16
+ def extract_uri(uri)
17
+ uri = uri["template"]
18
+ interrogation = uri.index("?")
19
+ params = uri[interrogation+1..uri.size]
20
+ base_uri = uri[0..interrogation-1]
21
+ [base_uri, params]
22
+ end
23
+
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,3 @@
1
+ require 'restfulie/client/ext/link_ext'
2
+ require 'restfulie/client/ext/http_ext'
3
+ require 'restfulie/client/ext/open_search_ext'
@@ -1,6 +1,6 @@
1
1
  class Restfulie::Client::Feature::BaseRequest
2
2
 
3
- def execute(flow, request, response, env)
3
+ def execute(flow, request, env)
4
4
  request!(request.verb, request.host, request.path, request, flow, env)
5
5
  end
6
6
 
@@ -24,7 +24,7 @@ class Restfulie::Client::Feature::BaseRequest
24
24
  response = e
25
25
  end
26
26
 
27
- flow.continue(request, response, env)
27
+ response
28
28
 
29
29
  end
30
30
 
@@ -1,10 +1,10 @@
1
1
  class Restfulie::Client::Feature::Cache
2
2
 
3
- def execute(flow, request, response, env)
3
+ def execute(flow, request, env)
4
4
  found = Restfulie::Client.cache_provider.get([request.host, request.path], request)
5
5
  return found if found
6
6
 
7
- resp = flow.continue(request, response, env)
7
+ resp = flow.continue(request, env)
8
8
  if resp.kind_of?(Exception)
9
9
  resp
10
10
  else
@@ -0,0 +1,25 @@
1
+ # Retries marshalling to an acceptable media type if
2
+ # the server returns with 406: content negotiation. This means looking for
3
+ # another media type that both server and client
4
+ # understands, picking its converter and using it
5
+ # to marshal the original payload again.
6
+ #
7
+ # To use it, load it in your dsl:
8
+ # Restfulie.at("http://localhost:3000/product/2").conneg_when_unaccepted.get
9
+ module Restfulie::Client::Feature
10
+ class ConnegWhenUnaccepted
11
+
12
+ def execute(chain, request, env)
13
+ resp = chain.continue(request, env)
14
+ return resp if resp.code.to_i!=406
15
+
16
+ accept = Medie.registry.for(resp.headers["Accept"])
17
+ return resp if accept.nil?
18
+
19
+ request.with("Content-type", accept)
20
+ env = env.dup.merge(:body => env[:payload])
21
+ Restfulie::Client::Feature::SerializeBody.new.execute(chain, request, env)
22
+ end
23
+
24
+ end
25
+ end
@@ -1,7 +1,7 @@
1
1
  module Restfulie::Client::Feature
2
2
  class EnhanceResponse
3
- def execute(flow, request, response, env)
4
- resp = flow.continue(request, response, env)
3
+ def execute(flow, request, env)
4
+ resp = flow.continue(request, env)
5
5
  unless resp.kind_of? ::Restfulie::Client::HTTP::ResponseHolder
6
6
  resp.extend(::Restfulie::Client::HTTP::ResponseHolder)
7
7
  resp.results_from request, resp
@@ -12,8 +12,8 @@ class Restfulie::Client::Feature::FollowRequest
12
12
  self
13
13
  end
14
14
 
15
- def execute(flow, request, response, env)
16
- resp = flow.continue(request, response, env)
15
+ def execute(flow, request, env)
16
+ resp = flow.continue(request, env)
17
17
  if !resp.respond_to?(:code)
18
18
  return resp
19
19
  end
@@ -10,8 +10,8 @@
10
10
  #
11
11
  class Restfulie::Client::Feature::HistoryRequest
12
12
 
13
- def execute(flow, request, response, env)
14
- resp = flow.continue(request, response, env)
13
+ def execute(flow, request, env)
14
+ resp = flow.continue(request, env)
15
15
  request.make_snapshot(request)
16
16
  resp
17
17
  end
@@ -0,0 +1,25 @@
1
+ # Adds support to retrying a request if the result is 503.
2
+ #
3
+ # To use it, load it in your dsl:
4
+ # Restfulie.at("http://localhost:3000/product/2").retry_when_unavailable.get
5
+ module Restfulie::Client::Feature
6
+ class RetryWhenUnavailable
7
+
8
+ def execute(chain, request, env)
9
+ resp = chain.continue(request, env)
10
+ if should_retry?(resp, env)
11
+ resp = chain.continue(request, env)
12
+ end
13
+ resp
14
+ end
15
+
16
+ protected
17
+ # extension point that allows you to redefine
18
+ # when a request should be retried
19
+ def should_retry?(response, env)
20
+ response.code.to_i == 503
21
+ end
22
+
23
+ end
24
+ end
25
+
@@ -1,15 +1,18 @@
1
+ # Feature responsible for marshalling the entity into the request body.
2
+ # It will use the request content type header to select the proper marshaller using Medie.
1
3
  class Restfulie::Client::Feature::SerializeBody
2
4
 
3
- def execute(flow, request, response, env)
5
+ def execute(flow, request, env = {})
4
6
 
5
7
  if should_have_payload?(request.verb)
6
8
 
7
- payload = env[:body]
9
+ env = env.dup
10
+ payload = env[:payload] = env[:body]
8
11
  if payload && !(payload.kind_of?(String) && payload.empty?)
9
12
  type = request.headers['Content-Type']
10
13
  raise Restfulie::Common::Error::RestfulieError, "Missing content type related to the data to be submitted" unless type
11
14
 
12
- marshaller = Restfulie::Common::Converter.content_type_for(type)
15
+ marshaller = Medie.registry.for(type)
13
16
  raise Restfulie::Common::Error::RestfulieError, "Missing content type for #{type} related to the data to be submitted" unless marshaller
14
17
 
15
18
  rel = request.respond_to?(:rel) ? request.rel : ""
@@ -18,7 +21,7 @@ class Restfulie::Client::Feature::SerializeBody
18
21
 
19
22
  end
20
23
 
21
- flow.continue(request, response, env)
24
+ flow.continue(request, env)
22
25
  end
23
26
 
24
27
  protected
@@ -2,7 +2,7 @@ module Restfulie::Client::Feature
2
2
 
3
3
  class SetupHeader
4
4
 
5
- def execute(flow, request, response, env)
5
+ def execute(flow, request, env)
6
6
  headers = request.default_headers.dup.merge(request.headers)
7
7
  host = request.host
8
8
  if host.user || host.password
@@ -14,7 +14,7 @@ module Restfulie::Client::Feature
14
14
  # gs: this should not be overriden, do it in some other way
15
15
  request.headers = headers
16
16
 
17
- flow.continue(request, response, env)
17
+ flow.continue(request, env)
18
18
  end
19
19
 
20
20
  end