restfulie 0.8.0 → 0.8.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.
Files changed (102) hide show
  1. data/Gemfile +10 -5
  2. data/Rakefile +5 -2
  3. data/lib/restfulie.rb +10 -5
  4. data/lib/restfulie/client.rb +13 -9
  5. data/lib/restfulie/client/base.rb +24 -65
  6. data/lib/restfulie/client/configuration.rb +62 -64
  7. data/lib/restfulie/client/entry_point.rb +36 -0
  8. data/lib/restfulie/client/ext/atom_ext.rb +12 -0
  9. data/lib/restfulie/client/ext/http_ext.rb +22 -0
  10. data/lib/restfulie/client/ext/json_ext.rb +12 -0
  11. data/lib/restfulie/client/ext/xml_ext.rb +4 -0
  12. data/lib/restfulie/client/http.rb +25 -13
  13. data/lib/restfulie/client/http/cache.rb +22 -22
  14. data/lib/restfulie/client/http/error.rb +70 -70
  15. data/lib/restfulie/client/http/link_request_builder.rb +15 -0
  16. data/lib/restfulie/client/http/request_adapter.rb +209 -0
  17. data/lib/restfulie/client/http/request_builder.rb +107 -0
  18. data/lib/restfulie/client/http/request_builder_executor.rb +24 -0
  19. data/lib/restfulie/client/http/request_executor.rb +17 -0
  20. data/lib/restfulie/client/http/request_follow.rb +42 -0
  21. data/lib/restfulie/client/http/request_follow_executor.rb +10 -0
  22. data/lib/restfulie/client/http/request_history.rb +69 -0
  23. data/lib/restfulie/client/http/request_history_executor.rb +10 -0
  24. data/lib/restfulie/client/http/request_marshaller.rb +127 -0
  25. data/lib/restfulie/client/http/request_marshaller_executor.rb +10 -0
  26. data/lib/restfulie/client/http/response.rb +23 -0
  27. data/lib/restfulie/client/http/response_handler.rb +67 -0
  28. data/lib/restfulie/client/http/response_holder.rb +9 -0
  29. data/lib/restfulie/client/mikyung.rb +17 -14
  30. data/lib/restfulie/client/mikyung/concatenator.rb +15 -12
  31. data/lib/restfulie/client/mikyung/core.rb +65 -39
  32. data/lib/restfulie/client/mikyung/languages.rb +8 -26
  33. data/lib/restfulie/client/mikyung/languages/german.rb +24 -0
  34. data/lib/restfulie/client/mikyung/languages/portuguese.rb +23 -0
  35. data/lib/restfulie/client/mikyung/rest_process_model.rb +184 -107
  36. data/lib/restfulie/client/mikyung/steady_state_walker.rb +34 -28
  37. data/lib/restfulie/client/mikyung/then_condition.rb +33 -27
  38. data/lib/restfulie/client/mikyung/when_condition.rb +53 -49
  39. data/lib/restfulie/common.rb +7 -12
  40. data/lib/restfulie/common/converter.rb +20 -9
  41. data/lib/restfulie/common/converter/atom.rb +8 -83
  42. data/lib/restfulie/common/converter/atom/base.rb +89 -0
  43. data/lib/restfulie/common/converter/atom/builder.rb +101 -99
  44. data/lib/restfulie/common/converter/atom/helpers.rb +16 -8
  45. data/lib/restfulie/common/converter/json.rb +12 -0
  46. data/lib/restfulie/common/converter/json/base.rb +84 -0
  47. data/lib/restfulie/common/converter/json/builder.rb +102 -0
  48. data/lib/restfulie/common/converter/json/helpers.rb +17 -0
  49. data/lib/restfulie/common/converter/values.rb +30 -26
  50. data/lib/restfulie/common/converter/xml.rb +14 -0
  51. data/lib/restfulie/common/converter/xml/base.rb +61 -0
  52. data/lib/restfulie/common/converter/xml/builder.rb +112 -0
  53. data/lib/restfulie/common/converter/xml/helpers.rb +17 -0
  54. data/lib/restfulie/common/converter/xml/link.rb +25 -0
  55. data/lib/restfulie/common/converter/xml/links.rb +25 -0
  56. data/lib/restfulie/common/core_ext.rb +1 -5
  57. data/lib/restfulie/common/core_ext/hash.rb +12 -0
  58. data/lib/restfulie/common/error.rb +19 -0
  59. data/lib/restfulie/common/logger.rb +17 -9
  60. data/lib/restfulie/common/representation.rb +9 -10
  61. data/lib/restfulie/common/representation/atom.rb +15 -47
  62. data/lib/restfulie/common/representation/atom/base.rb +122 -365
  63. data/lib/restfulie/common/representation/atom/category.rb +41 -0
  64. data/lib/restfulie/common/representation/atom/entry.rb +52 -100
  65. data/lib/restfulie/common/representation/atom/factory.rb +43 -0
  66. data/lib/restfulie/common/representation/atom/feed.rb +103 -99
  67. data/lib/restfulie/common/representation/atom/link.rb +68 -0
  68. data/lib/restfulie/common/representation/atom/person.rb +48 -0
  69. data/lib/restfulie/common/representation/atom/source.rb +59 -0
  70. data/lib/restfulie/common/representation/atom/tag_collection.rb +38 -0
  71. data/lib/restfulie/common/representation/atom/xml.rb +95 -0
  72. data/lib/restfulie/common/representation/generic.rb +30 -29
  73. data/lib/restfulie/common/representation/json.rb +10 -22
  74. data/lib/restfulie/common/representation/json/base.rb +27 -0
  75. data/lib/restfulie/common/representation/json/keys_as_methods.rb +72 -0
  76. data/lib/restfulie/common/representation/json/link.rb +29 -0
  77. data/lib/restfulie/common/representation/json/link_collection.rb +23 -0
  78. data/lib/restfulie/common/representation/xml.rb +18 -227
  79. data/lib/restfulie/server.rb +9 -10
  80. data/lib/restfulie/server/action_controller.rb +10 -12
  81. data/lib/restfulie/server/action_controller/base.rb +18 -15
  82. data/lib/restfulie/server/action_controller/{routing/patch.rb → patch.rb} +0 -0
  83. data/lib/restfulie/server/action_controller/restful_responder.rb +43 -35
  84. data/lib/restfulie/server/action_view.rb +8 -6
  85. data/lib/restfulie/server/action_view/helpers.rb +47 -41
  86. data/lib/restfulie/server/action_view/template_handlers.rb +24 -12
  87. data/lib/restfulie/server/action_view/template_handlers/tokamak.rb +17 -12
  88. data/lib/restfulie/server/configuration.rb +22 -19
  89. data/lib/restfulie/server/{restfulie_controller.rb → controller.rb} +1 -10
  90. data/lib/restfulie/server/core_ext.rb +1 -1
  91. data/lib/restfulie/version.rb +14 -0
  92. metadata +52 -16
  93. data/lib/restfulie/client/http/adapter.rb +0 -502
  94. data/lib/restfulie/client/http/atom_ext.rb +0 -4
  95. data/lib/restfulie/client/http/core_ext.rb +0 -6
  96. data/lib/restfulie/client/http/core_ext/http.rb +0 -19
  97. data/lib/restfulie/client/http/marshal.rb +0 -145
  98. data/lib/restfulie/client/http/xml_ext.rb +0 -7
  99. data/lib/restfulie/common/core_ext/proc.rb +0 -48
  100. data/lib/restfulie/common/errors.rb +0 -15
  101. data/lib/restfulie/server/action_controller/routing.rb +0 -12
  102. data/lib/restfulie/server/action_controller/routing/restful_route.rb +0 -14
@@ -1,8 +1,10 @@
1
1
  if defined? ::ActionView and ::ActionController
2
-
3
- module Restfulie::Server::ActionView #:nodoc:
2
+ module Restfulie #:nodoc:
3
+ module Server #:nodoc:
4
+ module ActionView #:nodoc:
5
+ autoload :TemplateHandlers, 'restfulie/server/action_view/template_handlers'
6
+ autoload :Helpers, 'restfulie/server/action_view/helpers'
7
+ end
8
+ end
4
9
  end
5
-
6
- require 'restfulie/server/action_view/template_handlers'
7
- require 'restfulie/server/action_view/helpers'
8
- end
10
+ end
@@ -1,45 +1,51 @@
1
- module Restfulie::Server::ActionView::Helpers
2
- # Load a partial template to execute in describe
3
- #
4
- # For example:
5
- #
6
- # Passing the current context to partial in template:
7
- #
8
- # member(@album) do |member, album|
9
- # partial('member', binding)
10
- # end
11
- #
12
- # in partial:
13
- #
14
- # member.links << link(:rel => :artists, :href => album_artists_url(album))
15
- #
16
- # Or passing local variables assing
17
- #
18
- # collection(@albums) do |collection|
19
- # collection.members do |member, album|
20
- # partial("member", :locals => {:member => member, :album => album})
21
- # end
22
- # end
23
- #
24
- def partial(partial_path, caller_binding = nil)
25
- template = _pick_partial_template(partial_path)
26
-
27
- # Create a context to assing variables
28
- if caller_binding.kind_of?(Hash)
29
- Proc.new do
30
- extend @restfulie_type_helpers
31
- context = eval("(class << self; self; end)", binding)
32
-
33
- unless caller_binding[:locals].nil?
34
- caller_binding[:locals].each do |k, v|
35
- context.send(:define_method, k.to_sym) { v }
1
+ module Restfulie
2
+ module Server
3
+ module ActionView
4
+ module Helpers
5
+ # Load a partial template to execute in describe
6
+ #
7
+ # For example:
8
+ #
9
+ # Passing the current context to partial in template:
10
+ #
11
+ # member(@album) do |member, album|
12
+ # partial('member', binding)
13
+ # end
14
+ #
15
+ # in partial:
16
+ #
17
+ # member.links << link(:rel => :artists, :href => album_artists_url(album))
18
+ #
19
+ # Or passing local variables assing
20
+ #
21
+ # collection(@albums) do |collection|
22
+ # collection.members do |member, album|
23
+ # partial("member", :locals => {:member => member, :album => album})
24
+ # end
25
+ # end
26
+ #
27
+ def partial(partial_path, caller_binding = nil)
28
+ template = _pick_partial_template(partial_path)
29
+
30
+ # Create a context to assing variables
31
+ if caller_binding.kind_of?(Hash)
32
+ Proc.new do
33
+ extend @restfulie_type_helpers
34
+ context = eval("(class << self; self; end)", binding)
35
+
36
+ unless caller_binding[:locals].nil?
37
+ caller_binding[:locals].each do |k, v|
38
+ context.send(:define_method, k.to_sym) { v }
39
+ end
40
+ end
41
+
42
+ partial(partial_path, binding)
43
+ end.call
44
+ else
45
+ eval(template.source, caller_binding, template.path)
36
46
  end
37
47
  end
38
-
39
- partial(partial_path, binding)
40
- end.call
41
- else
42
- eval(template.source, caller_binding, template.path)
48
+ end
43
49
  end
44
50
  end
45
- end
51
+ end
@@ -1,13 +1,25 @@
1
- module Restfulie::Server::ActionView::TemplateHandlers #:nodoc:
1
+ module Restfulie
2
+ module Server
3
+ module ActionView
4
+ module TemplateHandlers #:nodoc:
5
+ autoload :Tokamak, 'restfulie/server/action_view/template_handlers/tokamak'
6
+
7
+ # It is needed to explicitly call 'activate!' to install the Tokamak
8
+ # template handler
9
+ def self.activate!
10
+ if defined? ::ActionView::Template and
11
+ ::ActionView::Template.respond_to?(:register_template_handler)
12
+ ::ActionView::Template
13
+ else
14
+ ::ActionView::Base
15
+ end.register_template_handler(:tokamak,
16
+ Restfulie::Server::ActionView::TemplateHandlers::Tokamak)
17
+
18
+ if defined? ::ActionController::Base
19
+ ::ActionController::Base.exempt_from_layout :tokamak
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
2
25
  end
3
-
4
- require 'restfulie/server/action_view/template_handlers/tokamak'
5
-
6
- if defined? ::ActionView::Template and ::ActionView::Template.respond_to? :register_template_handler
7
- ::ActionView::Template
8
- else
9
- ::ActionView::Base
10
- end.register_template_handler(:tokamak, Restfulie::Server::ActionView::TemplateHandlers::Tokamak)
11
-
12
- ::ActionController::Base.exempt_from_layout :tokamak if defined? ::ActionController::Base
13
-
@@ -1,15 +1,20 @@
1
- module Restfulie::Server::ActionView::TemplateHandlers
2
-
3
- class Tokamak < ActionView::TemplateHandler
4
- include ActionView::TemplateHandlers::Compilable
5
-
6
- def compile(template)
7
- "@restfulie_type_helpers = Restfulie::Client::HTTP::RequestMarshaller.content_type_for(self.response.content_type).helper; " +
8
- "extend @restfulie_type_helpers; " +
9
- "extend Restfulie::Server::ActionView::Helpers; " +
10
- "code_block = lambda { #{template.source} };" +
11
- "builder = code_block.call; " +
12
- "builder.to_s"
1
+ module Restfulie
2
+ module Server
3
+ module ActionView
4
+ module TemplateHandlers
5
+ class Tokamak < ::ActionView::TemplateHandler
6
+ include ::ActionView::TemplateHandlers::Compilable
7
+
8
+ def compile(template)
9
+ "@restfulie_type_helpers = Restfulie::Client::HTTP::RequestMarshaller.content_type_for(self.response.content_type).helper; " +
10
+ "extend @restfulie_type_helpers; " +
11
+ "extend Restfulie::Server::ActionView::Helpers; " +
12
+ "code_block = lambda { #{template.source} };" +
13
+ "builder = code_block.call; " +
14
+ "builder.to_s"
15
+ end
16
+ end
17
+ end
13
18
  end
14
19
  end
15
20
  end
@@ -1,21 +1,24 @@
1
- module Restfulie::Server::Configuration
2
- #Defines host to be passed to polymorphic_url.
3
- # You need to setup this to your own domain in order to generate meaningful links.
4
- mattr_accessor :host
5
- @@host = 'localhost'
6
-
7
- # Passes a symbol to polymorphic_url in order to use a namespaced named_route.
8
- # So, if config.named_route_prefix = :rest, it will search for rest_album_url,
9
- # rest_album_songs_url, and so on.
10
- mattr_accessor :named_route_prefix
11
- @@named_route_prefix = nil
12
-
13
- # This defines a Rails-like way to setup options. You can do, in a initializer:
14
- # Restfulie::Server.setup do |config|
15
- # config.host = 'mydomain.com'
16
- # end
17
- def self.setup
18
- yield self
1
+ module Restfulie
2
+ module Server
3
+ module Configuration
4
+ # Defines host to be passed to polymorphic_url.
5
+ # You need to setup this to your own domain in order to generate meaningful links.
6
+ mattr_accessor :host
7
+ @@host = 'localhost'
8
+
9
+ # Passes a symbol to polymorphic_url in order to use a namespaced named_route.
10
+ # So, if config.named_route_prefix = :rest, it will search for rest_album_url,
11
+ # rest_album_songs_url, and so on.
12
+ mattr_accessor :named_route_prefix
13
+ @@named_route_prefix = nil
14
+
15
+ # This defines a Rails-like way to setup options. You can do, in a initializer:
16
+ # Restfulie::Server.setup do |config|
17
+ # config.host = 'mydomain.com'
18
+ # end
19
+ def self.setup
20
+ yield self
21
+ end
22
+ end
19
23
  end
20
24
  end
21
-
@@ -1,15 +1,10 @@
1
1
  module Restfulie
2
-
3
2
  module Server
4
-
5
3
  # Controller which adds default CRUD + search + other operations.
6
4
  # TODO: move these actions to controller/base.rb (maybe using InheritedResources, maybe not)
7
5
  module Controller
8
-
9
6
  # creates a model based on the request media-type extracted from its content-type
10
- #
11
7
  def create
12
-
13
8
  type = model_type
14
9
  return head 415 unless fits_content(type, request.headers['CONTENT_TYPE'])
15
10
 
@@ -19,7 +14,6 @@ module Restfulie
19
14
  else
20
15
  render :xml => @model.errors, :status => :unprocessable_entity
21
16
  end
22
-
23
17
  end
24
18
 
25
19
  # renders this resource
@@ -75,9 +69,6 @@ module Restfulie
75
69
  type.media_type_representations.include?(content_type) :
76
70
  Restfulie::MediaType.default_representations.include?(content_type))
77
71
  end
78
-
79
72
  end
80
-
81
73
  end
82
-
83
- end
74
+ end
@@ -1 +1 @@
1
- require 'restfulie/server/core_ext/array'
1
+ require 'restfulie/server/core_ext/array'
@@ -0,0 +1,14 @@
1
+ module Restfulie
2
+ module VERSION #:nodoc:
3
+ MAJOR = 0
4
+ MINOR = 8
5
+ TINY = 1
6
+
7
+ STRING = [MAJOR, MINOR, TINY].join('.')
8
+
9
+ # Restfulie's version
10
+ def self.to_s
11
+ STRING
12
+ end
13
+ end
14
+ end
metadata CHANGED
@@ -5,16 +5,16 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 8
8
- - 0
9
- version: 0.8.0
8
+ - 1
9
+ version: 0.8.1
10
10
  platform: ruby
11
11
  authors:
12
- - "Guilherme Silveira, Caue Guerra, Luis Cipriani, \xC3\x89verton Ribeiro, George Guimar\xC3\xA3es, Paulo Ahagon"
12
+ - Guilherme Silveira, Caue Guerra, Luis Cipriani, Everton Ribeiro, George Guimaraes, Paulo Ahagon
13
13
  autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-05-27 00:00:00 -03:00
17
+ date: 2010-06-03 00:00:00 -03:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -98,17 +98,32 @@ extra_rdoc_files: []
98
98
  files:
99
99
  - lib/restfulie/client/base.rb
100
100
  - lib/restfulie/client/configuration.rb
101
- - lib/restfulie/client/http/adapter.rb
102
- - lib/restfulie/client/http/atom_ext.rb
101
+ - lib/restfulie/client/entry_point.rb
102
+ - lib/restfulie/client/ext/atom_ext.rb
103
+ - lib/restfulie/client/ext/http_ext.rb
104
+ - lib/restfulie/client/ext/json_ext.rb
105
+ - lib/restfulie/client/ext/xml_ext.rb
103
106
  - lib/restfulie/client/http/cache.rb
104
- - lib/restfulie/client/http/core_ext/http.rb
105
- - lib/restfulie/client/http/core_ext.rb
106
107
  - lib/restfulie/client/http/error.rb
107
- - lib/restfulie/client/http/marshal.rb
108
- - lib/restfulie/client/http/xml_ext.rb
108
+ - lib/restfulie/client/http/link_request_builder.rb
109
+ - lib/restfulie/client/http/request_adapter.rb
110
+ - lib/restfulie/client/http/request_builder.rb
111
+ - lib/restfulie/client/http/request_builder_executor.rb
112
+ - lib/restfulie/client/http/request_executor.rb
113
+ - lib/restfulie/client/http/request_follow.rb
114
+ - lib/restfulie/client/http/request_follow_executor.rb
115
+ - lib/restfulie/client/http/request_history.rb
116
+ - lib/restfulie/client/http/request_history_executor.rb
117
+ - lib/restfulie/client/http/request_marshaller.rb
118
+ - lib/restfulie/client/http/request_marshaller_executor.rb
119
+ - lib/restfulie/client/http/response.rb
120
+ - lib/restfulie/client/http/response_handler.rb
121
+ - lib/restfulie/client/http/response_holder.rb
109
122
  - lib/restfulie/client/http.rb
110
123
  - lib/restfulie/client/mikyung/concatenator.rb
111
124
  - lib/restfulie/client/mikyung/core.rb
125
+ - lib/restfulie/client/mikyung/languages/german.rb
126
+ - lib/restfulie/client/mikyung/languages/portuguese.rb
112
127
  - lib/restfulie/client/mikyung/languages.rb
113
128
  - lib/restfulie/client/mikyung/rest_process_model.rb
114
129
  - lib/restfulie/client/mikyung/steady_state_walker.rb
@@ -116,40 +131,61 @@ files:
116
131
  - lib/restfulie/client/mikyung/when_condition.rb
117
132
  - lib/restfulie/client/mikyung.rb
118
133
  - lib/restfulie/client.rb
134
+ - lib/restfulie/common/converter/atom/base.rb
119
135
  - lib/restfulie/common/converter/atom/builder.rb
120
136
  - lib/restfulie/common/converter/atom/helpers.rb
121
137
  - lib/restfulie/common/converter/atom.rb
138
+ - lib/restfulie/common/converter/json/base.rb
139
+ - lib/restfulie/common/converter/json/builder.rb
140
+ - lib/restfulie/common/converter/json/helpers.rb
141
+ - lib/restfulie/common/converter/json.rb
122
142
  - lib/restfulie/common/converter/values.rb
143
+ - lib/restfulie/common/converter/xml/base.rb
144
+ - lib/restfulie/common/converter/xml/builder.rb
145
+ - lib/restfulie/common/converter/xml/helpers.rb
146
+ - lib/restfulie/common/converter/xml/link.rb
147
+ - lib/restfulie/common/converter/xml/links.rb
148
+ - lib/restfulie/common/converter/xml.rb
123
149
  - lib/restfulie/common/converter.rb
124
- - lib/restfulie/common/core_ext/proc.rb
150
+ - lib/restfulie/common/core_ext/hash.rb
125
151
  - lib/restfulie/common/core_ext.rb
126
- - lib/restfulie/common/errors.rb
152
+ - lib/restfulie/common/error.rb
127
153
  - lib/restfulie/common/logger.rb
128
154
  - lib/restfulie/common/representation/atom/base.rb
155
+ - lib/restfulie/common/representation/atom/category.rb
129
156
  - lib/restfulie/common/representation/atom/entry.rb
157
+ - lib/restfulie/common/representation/atom/factory.rb
130
158
  - lib/restfulie/common/representation/atom/feed.rb
159
+ - lib/restfulie/common/representation/atom/link.rb
160
+ - lib/restfulie/common/representation/atom/person.rb
161
+ - lib/restfulie/common/representation/atom/source.rb
162
+ - lib/restfulie/common/representation/atom/tag_collection.rb
163
+ - lib/restfulie/common/representation/atom/xml.rb
131
164
  - lib/restfulie/common/representation/atom.rb
132
165
  - lib/restfulie/common/representation/generic.rb
166
+ - lib/restfulie/common/representation/json/base.rb
167
+ - lib/restfulie/common/representation/json/keys_as_methods.rb
168
+ - lib/restfulie/common/representation/json/link.rb
169
+ - lib/restfulie/common/representation/json/link_collection.rb
133
170
  - lib/restfulie/common/representation/json.rb
134
171
  - lib/restfulie/common/representation/xml.rb
135
172
  - lib/restfulie/common/representation.rb
136
173
  - lib/restfulie/common.rb
137
174
  - lib/restfulie/server/action_controller/base.rb
138
175
  - lib/restfulie/server/action_controller/params_parser.rb
176
+ - lib/restfulie/server/action_controller/patch.rb
139
177
  - lib/restfulie/server/action_controller/restful_responder.rb
140
- - lib/restfulie/server/action_controller/routing/patch.rb
141
- - lib/restfulie/server/action_controller/routing/restful_route.rb
142
- - lib/restfulie/server/action_controller/routing.rb
143
178
  - lib/restfulie/server/action_controller.rb
144
179
  - lib/restfulie/server/action_view/helpers.rb
145
180
  - lib/restfulie/server/action_view/template_handlers/tokamak.rb
146
181
  - lib/restfulie/server/action_view/template_handlers.rb
147
182
  - lib/restfulie/server/action_view.rb
148
183
  - lib/restfulie/server/configuration.rb
184
+ - lib/restfulie/server/controller.rb
149
185
  - lib/restfulie/server/core_ext/array.rb
150
186
  - lib/restfulie/server/core_ext.rb
151
- - lib/restfulie/server/restfulie_controller.rb
152
187
  - lib/restfulie/server.rb
188
+ - lib/restfulie/version.rb
153
189
  - lib/restfulie.rb
154
190
  - Gemfile
155
191
  - LICENSE
@@ -1,502 +0,0 @@
1
- module Restfulie::Client::HTTP #:nodoc:
2
-
3
- #=Response
4
- # Default response class
5
- class Response
6
-
7
- attr_reader :method
8
- attr_reader :path
9
- attr_reader :code
10
- attr_reader :body
11
- attr_reader :headers
12
-
13
- def initialize(method, path, code, body, headers)
14
- @method = method
15
- @path = path
16
- @code = code
17
- @body = body
18
- @headers = headers
19
- end
20
-
21
- end
22
-
23
- #=ResponseHandler
24
- # You can change instance registering a class according to the code.
25
- #
26
- #==Example
27
- #
28
- # class RequestExecutor
29
- # include RequestAdapter
30
- # def initialize(host)
31
- # self.host=host
32
- # end
33
- # end
34
- #
35
- # class FakeResponse < Restfulie::Client::HTTP::Response
36
- # end
37
- #
38
- # Restfulie::Client::HTTP::ResponseHandler.register(201,FakeResponse)
39
- # @re = Restfulie::Client::HTTP::RequestExecutor.new('http://restfulie.com')
40
- # puts @re.as('application/atom+xml').get!('/posts').class.to_i #=> FakeResponse
41
- #
42
- module ResponseHandler
43
-
44
- @@response_handlers = {}
45
- ##
46
- # :singleton-method:
47
- # Response handlers attribute reader
48
- # * code: HTTP status code
49
- def self.handlers(code)
50
- @@response_handlers[code]
51
- end
52
-
53
- ##
54
- # :singleton-method:
55
- # Use to register response handlers
56
- #
57
- # * <tt>code: HTTP status code</tt>
58
- # * <tt>response_class: Response class</tt>
59
- #
60
- #==Example:
61
- # class FakeResponse < ::Restfulie::Client::HTTP::Response
62
- # end
63
- #
64
- # Restfulie::Client::HTTP::ResponseHandler.register(200,FakeResponse)
65
- #
66
- def self.register(code,response_class)
67
- @@response_handlers[code] = response_class
68
- end
69
-
70
- ##
71
- # :singleton-method:
72
- # Request Adapter uses this method to choose response instance
73
- #
74
- # *<tt>method: :get,:post,:delete,:head,:put</tt>
75
- # *<tt>path: '/posts'</tt>
76
- # *<tt>http_response</tt>
77
- #
78
- def self.handle(method, path, http_response)
79
- response_class = @@response_handlers[http_response.code.to_i] || Response
80
- headers = {}
81
- http_response.header.each { |k, v| headers[k] = v }
82
- response_class.new( method, path, http_response.code.to_i, http_response.body, headers)
83
- end
84
-
85
- end
86
-
87
- #
88
- # Request Adapter provides a minimal interface to exchange information between server over HTTP protocol through simple adapters.
89
- #
90
- # All the concrete adapters follow the interface laid down in this module.
91
- # Default connection provider is net/http
92
- #
93
- #==Example
94
- #
95
- # @re = ::Restfulie::Client::HTTP::RequestExecutor.new('http://restfulie.com') #this class includes RequestAdapter module.
96
- # puts @re.as('application/atom+xml').get!('/posts').title #=> 'Hello World!'
97
- #
98
- module RequestAdapter
99
-
100
- attr_reader :host
101
- attr_accessor :cookies
102
- attr_writer :default_headers
103
-
104
- def host=(host)
105
- if host.is_a?(::URI)
106
- @host = host
107
- else
108
- @host = ::URI.parse(host)
109
- end
110
- end
111
-
112
- def default_headers
113
- @default_headers ||= {}
114
- end
115
-
116
- #GET HTTP verb without {Error}
117
- # * <tt>path: '/posts'</tt>
118
- # * <tt>headers: {'Accept' => '*/*', 'Content-Type' => 'application/atom+xml'}</tt>
119
- def get(path, *args)
120
- request(:get, path, *args)
121
- end
122
-
123
- #HEAD HTTP verb without {Error}
124
- # * <tt>path: '/posts'</tt>
125
- # * <tt>headers: {'Accept' => '*/*', 'Content-Type' => 'application/atom+xml'}</tt>
126
- def head(path, *args)
127
- request(:head, path, *args)
128
- end
129
-
130
- #POST HTTP verb without {Error}
131
- # * <tt>path: '/posts'</tt>
132
- # * <tt>payload: 'some text'</tt>
133
- # * <tt>headers: {'Accept' => '*/*', 'Content-Type' => 'application/atom+xml'}</tt>
134
- def post(path, payload, *args)
135
- request(:post, path, payload, *args)
136
- end
137
-
138
- #PATCH HTTP verb without {Error}
139
- # * <tt>path: '/posts'</tt>
140
- # * <tt>payload: 'some text'</tt>
141
- # * <tt>headers: {'Accept' => '*/*', 'Content-Type' => 'application/atom+xml'}</tt>
142
- def patch(path, payload, *args)
143
- request(:patch, path, payload, *args)
144
- end
145
-
146
- #PUT HTTP verb without {Error}
147
- # * <tt>path: '/posts'</tt>
148
- # * <tt>payload: 'some text'</tt>
149
- # * <tt>headers: {'Accept' => '*/*', 'Content-Type' => 'application/atom+xml'}</tt>
150
- def put(path, payload, *args)
151
- request(:put, path, payload, *args)
152
- end
153
-
154
- #DELETE HTTP verb without {Error}
155
- # * <tt>path: '/posts'</tt>
156
- # * <tt>headers: {'Accept' => '*/*', 'Content-Type' => 'application/atom+xml'}</tt>
157
- def delete(path, *args)
158
- request(:delete, path, *args)
159
- end
160
-
161
- #GET HTTP verb {Error}
162
- # * <tt>path: '/posts'</tt>
163
- # * <tt>headers: {'Accept' => '*/*', 'Content-Type' => 'application/atom+xml'}</tt>
164
- def get!(path, *args)
165
- request!(:get, path, *args)
166
- end
167
-
168
- #HEAD HTTP verb {Error}
169
- # * <tt>path: '/posts'</tt>
170
- # * <tt>headers: {'Accept' => '*/*', 'Content-Type' => 'application/atom+xml'}</tt>
171
- def head!(path, *args)
172
- request!(:head, path, *args)
173
- end
174
-
175
- #POST HTTP verb {Error}
176
- # * <tt>path: '/posts'</tt>
177
- # * <tt>payload: 'some text'</tt>
178
- # * <tt>headers: {'Accept' => '*/*', 'Content-Type' => 'application/atom+xml'}</tt>
179
- def post!(path, payload, *args)
180
- request!(:post, path, payload, *args)
181
- end
182
-
183
- #PATCH HTTP verb {Error}
184
- # * <tt>path: '/posts'</tt>
185
- # * <tt>payload: 'some text'</tt>
186
- # * <tt>headers: {'Accept' => '*/*', 'Content-Type' => 'application/atom+xml'}</tt>
187
- def patch!(path, payload, *args)
188
- request!(:patch, path, payload, *args)
189
- end
190
-
191
- #PUT HTTP verb {Error}
192
- # * <tt>path: '/posts'</tt>
193
- # * <tt>payload: 'some text'</tt>
194
- # * <tt>headers: {'Accept' => '*/*', 'Content-Type' => 'application/atom+xml'}</tt>
195
- def put!(path, payload, *args)
196
- request!(:put, path, payload, *args)
197
- end
198
-
199
- #DELETE HTTP verb {Error}
200
- # * <tt>path: '/posts'</tt>
201
- # * <tt>headers: {'Accept' => '*/*', 'Content-Type' => 'application/atom+xml'}</tt>
202
- def delete!(path, *args)
203
- request!(:delete, path, *args)
204
- end
205
-
206
- #Executes a request against your server and return a response instance without {Error}
207
- # * <tt>method: :get,:post,:delete,:head,:put</tt>
208
- # * <tt>path: '/posts'</tt>
209
- # * <tt>args: payload: 'some text' and/or headers: {'Accept' => '*/*', 'Content-Type' => 'application/atom+xml'}</tt>
210
- def request(method, path, *args)
211
- request!(method, path, *args)
212
- rescue Error::RESTError => se
213
- se.response
214
- end
215
-
216
- #Executes a request against your server and return a response instance.
217
- # * <tt>method: :get,:post,:delete,:head,:put</tt>
218
- # * <tt>path: '/posts'</tt>
219
- # * <tt>args: payload: 'some text' and/or headers: {'Accept' => '*/*', 'Content-Type' => 'application/atom+xml'}</tt>
220
- def request!(method, path, *args)
221
- headers = default_headers.merge(args.extract_options!)
222
- unless @host.user.blank? && @host.password.blank?
223
- headers["Authorization"] = "Basic " + ["#{@host.user}:#{@host.password}"].pack("m").delete("\r\n")
224
- end
225
- headers['cookie'] = @cookies if @cookies
226
- args << headers
227
-
228
- ::Restfulie::Common::Logger.logger.info(request_to_s(method, path, *args)) if ::Restfulie::Common::Logger.logger
229
- begin
230
- response = ResponseHandler.handle(method, path, get_connection_provider.send(method, path, *args))
231
- rescue Exception => e
232
- raise Error::ServerNotAvailableError.new(self, Response.new(method, path, 503, nil, {}), e )
233
- end
234
-
235
- case response.code
236
- when 100..299
237
- response
238
- when 300..399
239
- raise Error::Redirection.new(self, response)
240
- when 400
241
- raise Error::BadRequest.new(self, response)
242
- when 401
243
- raise Error::Unauthorized.new(self, response)
244
- when 403
245
- raise Error::Forbidden.new(self, response)
246
- when 404
247
- raise Error::NotFound.new(self, response)
248
- when 405
249
- raise Error::MethodNotAllowed.new(self, response)
250
- when 407
251
- raise Error::ProxyAuthenticationRequired.new(self, response)
252
- when 409
253
- raise Error::Conflict.new(self, response)
254
- when 410
255
- raise Error::Gone.new(self, response)
256
- when 412
257
- raise Error::PreconditionFailed.new(self, response)
258
- when 402, 406, 408, 411, 413..499
259
- raise Error::ClientError.new(self, response)
260
- when 501
261
- raise Error::NotImplemented.new(self, response)
262
- when 500, 502..599
263
- raise Error::ServerError.new(self, response)
264
- else
265
- raise Error::UnknownError.new(self, response)
266
- end
267
- end
268
-
269
- private
270
-
271
- def get_connection_provider
272
- @connection ||= ::Net::HTTP.new(@host.host, @host.port)
273
- end
274
-
275
- protected
276
-
277
- def request_to_s(method, path, *args)
278
- result = ["#{method.to_s.upcase} #{path}"]
279
-
280
- arguments = args.dup
281
- headers = arguments.extract_options!
282
-
283
- if [:post, :put].include?(method)
284
- body = arguments.shift
285
- end
286
-
287
- result << headers.collect { |key, value| "#{key}: #{value}" }.join("\n")
288
-
289
- (result + [body ? (body.inspect + "\n") : nil]).compact.join("\n") << "\n"
290
- end
291
-
292
- end
293
-
294
- #=RequestBuilder
295
- # Uses RequestAdapater to create a HTTP Request DSL
296
- #
297
- #==Example:
298
- #
299
- # @builder = ::Restfulie::Client::HTTP::RequestBuilderExecutor.new("http://restfulie.com") #this class includes RequestBuilder module.
300
- # @builder.at('/posts').as('application/xml').accepts('application/atom+xml').with('Accept-Language' => 'en').get.code #=> 200
301
- #
302
- module RequestBuilder
303
- include RequestAdapter
304
-
305
- #Set host
306
- def at(url)
307
- self.host = url
308
- self
309
- end
310
-
311
- #Set Content-Type and Accept headers
312
- def as(content_type)
313
- headers['Content-Type'] = content_type
314
- accepts(content_type)
315
- end
316
-
317
- #Set Accept headers
318
- def accepts(content_type)
319
- headers['Accept'] = content_type
320
- self
321
- end
322
-
323
- #
324
- #Merge internal header
325
- #
326
- # * <tt>headers (e.g. {'Cache-control' => 'no-cache'})</tt>
327
- #
328
- def with(headers)
329
- self.headers.merge!(headers)
330
- self
331
- end
332
-
333
- def headers
334
- @headers || @headers = {}
335
- end
336
-
337
- #Path (e.g. http://restfulie.com/posts => /posts)
338
- def path
339
- host.path
340
- end
341
-
342
- def get
343
- request(:get, path, headers)
344
- end
345
-
346
- def head
347
- request(:head, path, headers)
348
- end
349
-
350
- def post(payload)
351
- request(:post, path, payload, headers)
352
- end
353
-
354
- def patch(payload)
355
- request(:patch, path, payload, headers)
356
- end
357
-
358
- def put(payload)
359
- request(:put, path, payload, headers)
360
- end
361
-
362
- def delete
363
- request(:delete, path, headers)
364
- end
365
-
366
- def get!
367
- request!(:get, path, headers)
368
- end
369
-
370
- def head!
371
- request!(:head, path, headers)
372
- end
373
-
374
- def post!(payload)
375
- request!(:post, path, payload, headers)
376
- end
377
-
378
- def patch!(payload)
379
- request!(:patch, path, payload, headers)
380
- end
381
-
382
- def put!(payload)
383
- request!(:put, path, payload, headers)
384
- end
385
-
386
- def delete!
387
- request!(:delete, path, headers)
388
- end
389
-
390
- protected
391
-
392
- def headers=(h)
393
- @headers = h
394
- end
395
-
396
- end
397
-
398
-
399
- #=RequestHistory
400
- # Uses RequestBuilder and remind previous requests
401
- #
402
- #==Example:
403
- #
404
- # @executor = ::Restfulie::Client::HTTP::RequestHistoryExecutor.new("http://restfulie.com") #this class includes RequestHistory module.
405
- # @executor.at('/posts').as('application/xml').accepts('application/atom+xml').with('Accept-Language' => 'en').get.code #=> 200 #first request
406
- # @executor.at('/blogs').as('application/xml').accepts('application/atom+xml').with('Accept-Language' => 'en').get.code #=> 200 #second request
407
- # @executor.request_history!(0) #doing first request
408
- #
409
- module RequestHistory
410
- include RequestBuilder
411
-
412
- attr_accessor_with_default :max_to_remind, 10
413
-
414
- def snapshots
415
- @snapshots || @snapshots = []
416
- end
417
-
418
- def request!(method=nil, path=nil, *args)#:nodoc:
419
- if method == nil || path == nil
420
- raise 'History not selected' unless @snapshot
421
- super( @snapshot[:method], @snapshot[:path], *@snapshot[:args] )
422
- else
423
- @snapshot = make_snapshot(method, path, *args)
424
- unless snapshots.include?(@snapshot)
425
- snapshots.shift if snapshots.size >= max_to_remind
426
- snapshots << @snapshot
427
- end
428
- super
429
- end
430
- end
431
-
432
- def request(method=nil, path=nil, *args)#:nodoc:
433
- request!(method, path, *args)
434
- rescue Error::RESTError => se
435
- se.response
436
- end
437
-
438
- def history(number)
439
- @snapshot = snapshots[number]
440
- raise "Undefined snapshot for #{number}" unless @snapshot
441
- self.host = @snapshot[:host]
442
- self.cookies = @snapshot[:cookies]
443
- self.headers = @snapshot[:headers]
444
- self.default_headers = @snapshot[:default_headers]
445
- at(@snapshot[:path])
446
- end
447
-
448
- private
449
-
450
- def make_snapshot(method, path, *args)
451
- arguments = args.dup
452
- cutom_headers = arguments.extract_options!
453
- { :host => self.host.dup,
454
- :default_headers => self.default_headers.dup,
455
- :headers => self.headers.dup,
456
- :cookies => self.cookies,
457
- :method => method,
458
- :path => path,
459
- :args => arguments << self.headers.merge(cutom_headers) }
460
- end
461
-
462
- end
463
-
464
- #=This class includes RequestAdapter module.
465
- class RequestExecutor
466
- include RequestAdapter
467
-
468
- # * <tt> host (e.g. 'http://restfulie.com') </tt>
469
- # * <tt> default_headers (e.g. {'Cache-control' => 'no-cache'} ) </tt>
470
- def initialize(host, default_headers = {})
471
- self.host=host
472
- self.default_headers=default_headers
473
- end
474
-
475
- end
476
-
477
- #=This class includes RequestBuilder module.
478
- class RequestBuilderExecutor < RequestExecutor
479
- include RequestBuilder
480
-
481
- def host=(host)
482
- super
483
- at(self.host.path)
484
- end
485
-
486
- def at(path)
487
- @path = path
488
- self
489
- end
490
-
491
- def path
492
- @path
493
- end
494
-
495
- end
496
-
497
- #=This class inherits RequestFollowExecutor and include RequestHistory module.
498
- class RequestHistoryExecutor < RequestBuilderExecutor
499
- include RequestHistory
500
- end
501
-
502
- end