restfulie 0.8.0 → 0.8.1

Sign up to get free protection for your applications and to get access to all the features.
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