restfulie 0.6.0 → 0.7.0
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.
- data/README.textile +83 -7
- data/Rakefile +98 -13
- data/lib/restfulie/client/base.rb +48 -53
- data/lib/restfulie/client/configuration.rb +69 -0
- data/lib/restfulie/client/http/adapter.rb +487 -0
- data/lib/restfulie/client/http/atom_ext.rb +87 -0
- data/lib/restfulie/client/http/cache.rb +28 -0
- data/lib/restfulie/client/http/error.rb +80 -0
- data/lib/restfulie/client/http/marshal.rb +147 -0
- data/lib/restfulie/client/http.rb +13 -0
- data/lib/restfulie/client.rb +8 -56
- data/lib/restfulie/common/builder/builder_base.rb +58 -0
- data/lib/restfulie/common/builder/helpers.rb +22 -0
- data/lib/restfulie/common/builder/marshalling/atom.rb +197 -0
- data/lib/restfulie/common/builder/marshalling/base.rb +12 -0
- data/lib/restfulie/common/builder/marshalling/json.rb +2 -0
- data/lib/restfulie/common/builder/marshalling.rb +16 -0
- data/lib/restfulie/common/builder/rules/collection_rule.rb +10 -0
- data/lib/restfulie/common/builder/rules/link.rb +20 -0
- data/lib/restfulie/common/builder/rules/links.rb +9 -0
- data/lib/restfulie/common/builder/rules/member_rule.rb +8 -0
- data/lib/restfulie/common/builder/rules/namespace.rb +25 -0
- data/lib/restfulie/common/builder/rules/rules_base.rb +76 -0
- data/lib/restfulie/common/builder.rb +16 -0
- data/lib/restfulie/common/errors.rb +9 -0
- data/lib/restfulie/{logger.rb → common/logger.rb} +3 -5
- data/lib/restfulie/common/representation/atom.rb +48 -0
- data/lib/restfulie/common/representation/generic.rb +33 -0
- data/lib/restfulie/common/representation/xml.rb +24 -0
- data/lib/restfulie/common/representation.rb +10 -0
- data/lib/restfulie/common.rb +23 -0
- data/lib/restfulie/server/action_controller/base.rb +31 -0
- data/lib/restfulie/server/action_controller/params_parser.rb +62 -0
- data/lib/restfulie/server/action_controller/restful_responder.rb +39 -0
- data/lib/restfulie/server/action_controller/routing/restful_route.rb +14 -0
- data/lib/restfulie/server/action_controller/routing.rb +12 -0
- data/lib/restfulie/server/action_controller.rb +15 -0
- data/lib/restfulie/server/action_view/helpers.rb +45 -0
- data/lib/restfulie/server/action_view/template_handlers/tokamak.rb +15 -0
- data/lib/restfulie/server/action_view/template_handlers.rb +13 -0
- data/lib/restfulie/server/action_view.rb +8 -0
- data/lib/restfulie/server/configuration.rb +21 -0
- data/lib/restfulie/server/core_ext/array.rb +45 -0
- data/lib/restfulie/server/core_ext.rb +1 -0
- data/lib/restfulie/server/restfulie_controller.rb +1 -17
- data/lib/restfulie/server.rb +15 -0
- data/lib/restfulie.rb +4 -72
- data/lib/vendor/atom/configuration.rb +24 -0
- data/lib/vendor/atom/pub.rb +250 -0
- data/lib/vendor/atom/xml/parser.rb +373 -0
- data/lib/vendor/atom.rb +771 -0
- metadata +94 -33
- data/lib/restfulie/client/atom_media_type.rb +0 -75
- data/lib/restfulie/client/cache.rb +0 -103
- data/lib/restfulie/client/entry_point.rb +0 -94
- data/lib/restfulie/client/extensions/http.rb +0 -116
- data/lib/restfulie/client/helper.rb +0 -28
- data/lib/restfulie/client/instance.rb +0 -158
- data/lib/restfulie/client/request_execution.rb +0 -321
- data/lib/restfulie/client/state.rb +0 -36
- data/lib/restfulie/media_type.rb +0 -143
- data/lib/restfulie/media_type_control.rb +0 -115
- data/lib/restfulie/media_type_defaults.rb +0 -51
- data/lib/restfulie/server/atom_media_type.rb +0 -115
- data/lib/restfulie/server/base.rb +0 -91
- data/lib/restfulie/server/controller.rb +0 -122
- data/lib/restfulie/server/instance.rb +0 -102
- data/lib/restfulie/server/marshalling.rb +0 -47
- data/lib/restfulie/server/opensearch/description.rb +0 -54
- data/lib/restfulie/server/opensearch.rb +0 -18
- data/lib/restfulie/server/transition.rb +0 -93
- data/lib/restfulie/unmarshalling.rb +0 -131
- data/lib/vendor/jeokkarak/hashi.rb +0 -65
- data/lib/vendor/jeokkarak/jeokkarak.rb +0 -81
@@ -1,158 +0,0 @@
|
|
1
|
-
#
|
2
|
-
# Copyright (c) 2009 Caelum - www.caelum.com.br/opensource
|
3
|
-
# All rights reserved.
|
4
|
-
#
|
5
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
-
# you may not use this file except in compliance with the License.
|
7
|
-
# You may obtain a copy of the License at
|
8
|
-
#
|
9
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
-
#
|
11
|
-
# Unless required by applicable law or agreed to in writing, software
|
12
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
-
# See the License for the specific language governing permissions and
|
15
|
-
# limitations under the License.
|
16
|
-
#
|
17
|
-
|
18
|
-
module Restfulie::Client::Instance
|
19
|
-
|
20
|
-
# list of possible states to access
|
21
|
-
def existing_relations
|
22
|
-
@existing_relations ||= {}
|
23
|
-
end
|
24
|
-
|
25
|
-
# which content-type generated this data
|
26
|
-
attr_reader :_came_from
|
27
|
-
|
28
|
-
# prepares a new request
|
29
|
-
def request
|
30
|
-
Restfulie::Client::RequestExecution.new(self.class, self)
|
31
|
-
end
|
32
|
-
|
33
|
-
# parse arguments from a transition invocation (or relation)
|
34
|
-
# it will receive either zero, one or two args, if there are two args, return them
|
35
|
-
# if there is one hash arg, its the options, add a data = nil
|
36
|
-
# if there is one arg (not a hash), its the data, add a options = {}
|
37
|
-
# if there are no args, data is nil and options = {}
|
38
|
-
def parse_args_from_transition(args)
|
39
|
-
data = nil
|
40
|
-
if args.nil? || args.size==0
|
41
|
-
options = {}
|
42
|
-
elsif args.size==1
|
43
|
-
if args[0].kind_of?(Hash)
|
44
|
-
options = args[0]
|
45
|
-
else
|
46
|
-
data = args[0]
|
47
|
-
options = {}
|
48
|
-
end
|
49
|
-
elsif args.size==2
|
50
|
-
data = args[0]
|
51
|
-
options = args[1] || {}
|
52
|
-
end
|
53
|
-
[data, options]
|
54
|
-
end
|
55
|
-
|
56
|
-
def invoke_remote_transition(name, args, block = nil)
|
57
|
-
|
58
|
-
data, options = parse_args_from_transition(args)
|
59
|
-
|
60
|
-
method = Restfulie::Client::Config.requisition_method_for options[:method], name
|
61
|
-
state = self.existing_relations[name]
|
62
|
-
|
63
|
-
request = Restfulie::Client::RequestExecution.new(self.class, self).at(state["href"] || state[:href]).with(options[:headers])
|
64
|
-
request.do method, name, data
|
65
|
-
|
66
|
-
end
|
67
|
-
|
68
|
-
# inserts all links from this object as can_xxx and xxx methods
|
69
|
-
def add_transitions(links)
|
70
|
-
links.each do |t|
|
71
|
-
self.existing_relations[t["rel"] || t[:rel]] = t
|
72
|
-
self.add_state(t)
|
73
|
-
end
|
74
|
-
self.extend Restfulie::Client::State
|
75
|
-
end
|
76
|
-
|
77
|
-
# adds the specific information for one state change or related resource
|
78
|
-
def add_state(transition)
|
79
|
-
name = transition["rel"] || transition[:rel]
|
80
|
-
|
81
|
-
# TODO: wrong, should be instance_eval
|
82
|
-
self.class.module_eval do
|
83
|
-
|
84
|
-
def temp_method(*args, &block)
|
85
|
-
self.invoke_remote_transition(Restfulie::Client::Helper.current_method, args, block)
|
86
|
-
end
|
87
|
-
|
88
|
-
alias_method name, :temp_method
|
89
|
-
undef :temp_method
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
# returns a list of extended fields for this instance.
|
94
|
-
# extended fields are those unknown to this model but kept in a hash
|
95
|
-
# to allow forward-compatibility.
|
96
|
-
def extended_fields
|
97
|
-
@extended_fields ||= {}
|
98
|
-
@extended_fields
|
99
|
-
end
|
100
|
-
|
101
|
-
def method_missing(name, *args)
|
102
|
-
name = name.to_s if name.kind_of? Symbol
|
103
|
-
|
104
|
-
if name[-1,1] == "="
|
105
|
-
extended_fields[name.chop] = args[0]
|
106
|
-
elsif name[-1,1] == "?"
|
107
|
-
found = extended_fields[name.chop]
|
108
|
-
return super(name,args) if found.nil?
|
109
|
-
parse(found)
|
110
|
-
else
|
111
|
-
found = extended_fields[name]
|
112
|
-
return super(name,args) if found.nil?
|
113
|
-
parse(transform(found))
|
114
|
-
end
|
115
|
-
|
116
|
-
end
|
117
|
-
|
118
|
-
def respond_to?(sym)
|
119
|
-
extended_fields[sym.to_s].nil? ? super(sym) : true
|
120
|
-
end
|
121
|
-
|
122
|
-
# redefines attribute definition allowing the invocation of method_missing
|
123
|
-
# when an attribute does not exist
|
124
|
-
def attributes=(values)
|
125
|
-
values.each do |key, value|
|
126
|
-
unless attributes.include? key
|
127
|
-
method_missing("#{key}=", value)
|
128
|
-
values.delete key
|
129
|
-
end
|
130
|
-
end
|
131
|
-
super(values)
|
132
|
-
end
|
133
|
-
|
134
|
-
|
135
|
-
# serializes the extended fields with the existing fields
|
136
|
-
def to_xml(options={})
|
137
|
-
super(options) do |xml|
|
138
|
-
extended_fields.each do |key,value|
|
139
|
-
xml.tag! key, value
|
140
|
-
end
|
141
|
-
end
|
142
|
-
end
|
143
|
-
|
144
|
-
private
|
145
|
-
|
146
|
-
# transforms a value in a custom hash
|
147
|
-
def transform(value)
|
148
|
-
return CustomHash.new(value) if value.kind_of?(Hash) || value.kind_of?(Array)
|
149
|
-
value
|
150
|
-
end
|
151
|
-
|
152
|
-
def parse(val)
|
153
|
-
raise "undefined method: '#{val}'" if val.nil?
|
154
|
-
val
|
155
|
-
end
|
156
|
-
|
157
|
-
|
158
|
-
end
|
@@ -1,321 +0,0 @@
|
|
1
|
-
#
|
2
|
-
# Copyright (c) 2009 Caelum - www.caelum.com.br/opensource
|
3
|
-
# All rights reserved.
|
4
|
-
#
|
5
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
-
# you may not use this file except in compliance with the License.
|
7
|
-
# You may obtain a copy of the License at
|
8
|
-
#
|
9
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
-
#
|
11
|
-
# Unless required by applicable law or agreed to in writing, software
|
12
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
-
# See the License for the specific language governing permissions and
|
15
|
-
# limitations under the License.
|
16
|
-
#
|
17
|
-
|
18
|
-
require 'restfulie/client/extensions/http'
|
19
|
-
|
20
|
-
module Restfulie
|
21
|
-
module Client
|
22
|
-
|
23
|
-
# extension to all answers that allows you to access the web response
|
24
|
-
module WebResponse
|
25
|
-
attr_accessor :web_response
|
26
|
-
end
|
27
|
-
|
28
|
-
# some error ocurred while processing the request
|
29
|
-
class ResponseError < Exception
|
30
|
-
end
|
31
|
-
|
32
|
-
# Handles response answered by servers by accessing the specific callback for a http response code.
|
33
|
-
module ResponseHandler
|
34
|
-
|
35
|
-
class << self
|
36
|
-
|
37
|
-
# registers a new callback for a specific range of response codes
|
38
|
-
#
|
39
|
-
# Restfulie::Client::ResponseHandler.register(400, 599) do |restfulie_response|
|
40
|
-
# # returns the original reponse object
|
41
|
-
# restfulie_response.response
|
42
|
-
# end
|
43
|
-
def register(min_code, max_code, &block)
|
44
|
-
(min_code..max_code).each do |code|
|
45
|
-
handlers[code] = block
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
# callback that returns the http response object
|
50
|
-
def pure_response_return(restfulie_response)
|
51
|
-
restfulie_response.response
|
52
|
-
end
|
53
|
-
|
54
|
-
# callback that raises a ResponseError
|
55
|
-
def raise_error(restfulie_response)
|
56
|
-
raise Restfulie::Client::ResponseError.new(restfulie_response.response)
|
57
|
-
end
|
58
|
-
|
59
|
-
# callback that parses the response media type and body,
|
60
|
-
# returning a deserialized representation of the resource.
|
61
|
-
# note that this will also set the _came_from instance variable with the content type
|
62
|
-
# this resource was represented, in order to allow further requests to prefer this content type.
|
63
|
-
def parse_entity(restfulie_response)
|
64
|
-
response = restfulie_response.response
|
65
|
-
content_type = response.content_type
|
66
|
-
type = Restfulie::MediaType.type_for(content_type)
|
67
|
-
if content_type[-3,3]=="xml"
|
68
|
-
result = type.from_xml response.body
|
69
|
-
elsif content_type[-4,4]=="json"
|
70
|
-
result = type.from_json response.body
|
71
|
-
else
|
72
|
-
result = generic_parse_entity restfulie_response
|
73
|
-
end
|
74
|
-
result.instance_variable_set :@_came_from, content_type
|
75
|
-
result
|
76
|
-
end
|
77
|
-
|
78
|
-
# callback taht executes a GET request to the response Location header.
|
79
|
-
# this is the typical callback for 200 response codes.
|
80
|
-
def retrieve_resource_from_location(restfulie_response)
|
81
|
-
restfulie_response.type.from_web restfulie_response.response["Location"]
|
82
|
-
end
|
83
|
-
|
84
|
-
# given a restfulie response, extracts the response code and invoke the registered callback.
|
85
|
-
def handle(restfulie_response)
|
86
|
-
handlers[restfulie_response.response.code.to_i].call(restfulie_response)
|
87
|
-
end
|
88
|
-
|
89
|
-
def generic_parse_entity(restfulie_response)
|
90
|
-
response = restfulie_response.response
|
91
|
-
content_type = response.content_type
|
92
|
-
type = Restfulie::MediaType.type_for(content_type)
|
93
|
-
method = "from_#{content_type}".to_sym
|
94
|
-
raise Restfulie::UnsupportedContentType.new("unsupported content type '#{content_type}' because '#{type}.#{method.to_s}' was not found") unless type.respond_to? method
|
95
|
-
type.send(method, response.body)
|
96
|
-
end
|
97
|
-
|
98
|
-
private
|
99
|
-
def handlers
|
100
|
-
@handlers ||= {}
|
101
|
-
end
|
102
|
-
|
103
|
-
def register_func(min, max, proc)
|
104
|
-
register(min, max) { |r| proc.call(r) }
|
105
|
-
end
|
106
|
-
|
107
|
-
end
|
108
|
-
|
109
|
-
register_func( 100, 599, Proc.new{ |r| pure_response_return r} )
|
110
|
-
register_func( 200, 200, Proc.new{ |r| parse_entity r} )
|
111
|
-
register_func( 301, 301, Proc.new{ |r| retrieve_resource_from_location r} )
|
112
|
-
|
113
|
-
end
|
114
|
-
|
115
|
-
|
116
|
-
# TODO there should be a response for each method type
|
117
|
-
class Response
|
118
|
-
|
119
|
-
attr_reader :type, :response
|
120
|
-
|
121
|
-
def initialize(type, response)
|
122
|
-
@type = type
|
123
|
-
@response = response
|
124
|
-
end
|
125
|
-
|
126
|
-
# TODO remote_post can probably be moved, does not need to be on the object's class itself
|
127
|
-
# the expected_content_type is used in case a redirection takes place
|
128
|
-
def parse_post(expected_content_type)
|
129
|
-
code = @response.code
|
130
|
-
if code=="301" && @type.follows.moved_permanently? == :all
|
131
|
-
result = @type.remote_post_to(@response["Location"], @response.body)
|
132
|
-
enhance(result)
|
133
|
-
elsif code=="201"
|
134
|
-
Restfulie.at(@response["Location"]).accepts(expected_content_type).get
|
135
|
-
else
|
136
|
-
final_parse
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
# gets a result object and enhances it with web response methods
|
141
|
-
# by extending WebResponse and defining the attribute web_response
|
142
|
-
def enhance(result)
|
143
|
-
@response.previous = result.web_response if result.respond_to? :web_response
|
144
|
-
result.extend Restfulie::Client::WebResponse
|
145
|
-
result.web_response = @response
|
146
|
-
result
|
147
|
-
end
|
148
|
-
|
149
|
-
# parses this response using the correct ResponseHandler and enhances it
|
150
|
-
def final_parse
|
151
|
-
enhance Restfulie::Client::ResponseHandler.handle(@response)
|
152
|
-
end
|
153
|
-
|
154
|
-
# detects which type of method invocation it was and act accordingly
|
155
|
-
# TODO this should be called by RequestExcution, not instance
|
156
|
-
def parse(method, invoking_object, content_type)
|
157
|
-
|
158
|
-
return enhance(invoking_object) if @response.code == "304"
|
159
|
-
|
160
|
-
# return block.call(@response) if block
|
161
|
-
|
162
|
-
return final_parse if method == Net::HTTP::Get
|
163
|
-
return parse_post(content_type) if method == Net::HTTP::Post
|
164
|
-
final_parse
|
165
|
-
|
166
|
-
end
|
167
|
-
|
168
|
-
end
|
169
|
-
|
170
|
-
class RequestExecution
|
171
|
-
|
172
|
-
def initialize(type)
|
173
|
-
initialize(type, nil)
|
174
|
-
end
|
175
|
-
|
176
|
-
def initialize(type, invoking_object)
|
177
|
-
@type = type
|
178
|
-
@content_type = "application/xml"
|
179
|
-
@accepts = "application/xml"
|
180
|
-
@invoking_object = invoking_object
|
181
|
-
end
|
182
|
-
|
183
|
-
def at(uri)
|
184
|
-
@uri = uri
|
185
|
-
self
|
186
|
-
end
|
187
|
-
|
188
|
-
# sets the Content-type AND Accept headers for this request
|
189
|
-
def as(content_type)
|
190
|
-
@content_type = content_type
|
191
|
-
@accepts = content_type
|
192
|
-
self
|
193
|
-
end
|
194
|
-
|
195
|
-
# sets the Accept header for this request
|
196
|
-
def accepts(content_type)
|
197
|
-
@accepts = content_type
|
198
|
-
self
|
199
|
-
end
|
200
|
-
|
201
|
-
def with(headers)
|
202
|
-
@headers = headers
|
203
|
-
self
|
204
|
-
end
|
205
|
-
|
206
|
-
# asks to create this content on the server (post it)
|
207
|
-
def create(content)
|
208
|
-
post(content)
|
209
|
-
end
|
210
|
-
|
211
|
-
# executes an http request using the specified verb
|
212
|
-
#
|
213
|
-
# example:
|
214
|
-
# do(Net::HTTP::Get, 'self', nil)
|
215
|
-
# do(Net::HTTP::Post, 'payment', '<payment/>')
|
216
|
-
def do(verb, relation_name, body = nil)
|
217
|
-
url, http_request = prepare_request(verb, relation_name, body)
|
218
|
-
response = execute_request(url, http_request)
|
219
|
-
Restfulie::Client::Response.new(@type, response).parse(verb, @invoking_object, "application/xml")
|
220
|
-
end
|
221
|
-
|
222
|
-
private
|
223
|
-
def execute_request(url, http_request)
|
224
|
-
cached = Restfulie.cache_provider.get(url, http_request)
|
225
|
-
return cached if cached
|
226
|
-
|
227
|
-
response = Net::HTTP.new(url.host, url.port).request(http_request)
|
228
|
-
Restfulie.cache_provider.put(url, http_request, response)
|
229
|
-
end
|
230
|
-
|
231
|
-
public
|
232
|
-
|
233
|
-
def prepare_request(verb, relation_name, body = nil)
|
234
|
-
url = URI.parse(@uri)
|
235
|
-
req = verb.new(url.path)
|
236
|
-
add_basic_request_headers(req, relation_name)
|
237
|
-
|
238
|
-
if body
|
239
|
-
req.body = body
|
240
|
-
req.add_field("Content-type", "application/xml") if req.get_fields("Content-type").nil?
|
241
|
-
end
|
242
|
-
[url, req]
|
243
|
-
end
|
244
|
-
|
245
|
-
# post this content to the server
|
246
|
-
def post(content)
|
247
|
-
remote_post_to(@uri, content)
|
248
|
-
end
|
249
|
-
|
250
|
-
# retrieves information from the server using a GET request
|
251
|
-
def get(options = {})
|
252
|
-
from_web(@uri, options)
|
253
|
-
end
|
254
|
-
|
255
|
-
def add_headers_to(hash)
|
256
|
-
hash[:headers] = {} unless hash[:headers]
|
257
|
-
hash[:headers]["Content-type"] = @content_type
|
258
|
-
hash[:headers]["Accept"] = @accepts
|
259
|
-
hash
|
260
|
-
end
|
261
|
-
|
262
|
-
def change_to_state(name, args)
|
263
|
-
if !args.empty? && args[args.size-1].kind_of?(Hash)
|
264
|
-
add_headers_to(args[args.size-1])
|
265
|
-
else
|
266
|
-
args << add_headers_to({})
|
267
|
-
end
|
268
|
-
@invoking_object.invoke_remote_transition name, args
|
269
|
-
end
|
270
|
-
|
271
|
-
# invokes an existing relation or delegates to the existing definition of method_missing
|
272
|
-
def method_missing(name, *args)
|
273
|
-
if @invoking_object && @invoking_object.existing_relations[name.to_s]
|
274
|
-
change_to_state(name.to_s, args)
|
275
|
-
else
|
276
|
-
super(name, args)
|
277
|
-
end
|
278
|
-
end
|
279
|
-
|
280
|
-
def add_basic_request_headers(req, name = nil)
|
281
|
-
|
282
|
-
req.add_field("Accept", @accepts) unless @accepts.nil?
|
283
|
-
|
284
|
-
@headers.each do |key, value|
|
285
|
-
req.add_field(key, value)
|
286
|
-
end if @headers
|
287
|
-
|
288
|
-
req.add_field("Accept", @invoking_object._came_from) if req.get_fields("Accept")==["*/*"]
|
289
|
-
|
290
|
-
if @type && name && @type.is_self_retrieval?(name) && @invoking_object.respond_to?(:web_response)
|
291
|
-
req.add_field("If-None-Match", @invoking_object.web_response.etag) if !@invoking_object.web_response.etag.nil?
|
292
|
-
req.add_field("If-Modified-Since", @invoking_object.web_response.last_modified) if !@invoking_object.web_response.last_modified.nil?
|
293
|
-
end
|
294
|
-
|
295
|
-
end
|
296
|
-
|
297
|
-
private
|
298
|
-
def remote_post_to(uri, content)
|
299
|
-
|
300
|
-
url = URI.parse(uri)
|
301
|
-
req = Net::HTTP::Post.new(url.path)
|
302
|
-
req.body = content
|
303
|
-
add_basic_request_headers(req)
|
304
|
-
req.add_field("Content-type", @content_type)
|
305
|
-
|
306
|
-
response = Net::HTTP.new(url.host, url.port).request(req)
|
307
|
-
Restfulie::Client::Response.new(@type, response).parse_post(@content_type)
|
308
|
-
end
|
309
|
-
|
310
|
-
def from_web(uri, options = {})
|
311
|
-
uri = URI.parse(uri)
|
312
|
-
req = Net::HTTP::Get.new(uri.path)
|
313
|
-
options.each { |key,value| req[key] = value }
|
314
|
-
add_basic_request_headers(req)
|
315
|
-
res = Net::HTTP.new(uri.host, uri.port).request(req)
|
316
|
-
Restfulie::Client::Response.new(@type, res).final_parse
|
317
|
-
end
|
318
|
-
|
319
|
-
end
|
320
|
-
end
|
321
|
-
end
|
@@ -1,36 +0,0 @@
|
|
1
|
-
#
|
2
|
-
# Copyright (c) 2009 Caelum - www.caelum.com.br/opensource
|
3
|
-
# All rights reserved.
|
4
|
-
#
|
5
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
-
# you may not use this file except in compliance with the License.
|
7
|
-
# You may obtain a copy of the License at
|
8
|
-
#
|
9
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
-
#
|
11
|
-
# Unless required by applicable law or agreed to in writing, software
|
12
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
-
# See the License for the specific language governing permissions and
|
15
|
-
# limitations under the License.
|
16
|
-
#
|
17
|
-
|
18
|
-
module Restfulie
|
19
|
-
|
20
|
-
module Client
|
21
|
-
|
22
|
-
# adds respond_to and has_state methods to resources
|
23
|
-
module State
|
24
|
-
|
25
|
-
# overrides the respond_to? method to check if this method is contained or was defined by a state
|
26
|
-
def respond_to?(sym)
|
27
|
-
has_state(sym.to_s) || super(sym)
|
28
|
-
end
|
29
|
-
|
30
|
-
# returns true if this resource has a state named name
|
31
|
-
def has_state(name)
|
32
|
-
!@existing_relations[name].nil?
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
data/lib/restfulie/media_type.rb
DELETED
@@ -1,143 +0,0 @@
|
|
1
|
-
#
|
2
|
-
# Copyright (c) 2009 Caelum - www.caelum.com.br/opensource
|
3
|
-
# All rights reserved.
|
4
|
-
#
|
5
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
-
# you may not use this file except in compliance with the License.
|
7
|
-
# You may obtain a copy of the License at
|
8
|
-
#
|
9
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
-
#
|
11
|
-
# Unless required by applicable law or agreed to in writing, software
|
12
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
-
# See the License for the specific language governing permissions and
|
15
|
-
# limitations under the License.
|
16
|
-
#
|
17
|
-
|
18
|
-
require 'restfulie/media_type_control'
|
19
|
-
|
20
|
-
module Restfulie
|
21
|
-
|
22
|
-
# represents an error when we are unable to support the desired content type
|
23
|
-
class UnsupportedContentType < Exception
|
24
|
-
|
25
|
-
attr_reader :msg
|
26
|
-
def initialize(msg)
|
27
|
-
@msg = msg
|
28
|
-
end
|
29
|
-
|
30
|
-
def to_s
|
31
|
-
@msg
|
32
|
-
end
|
33
|
-
|
34
|
-
end
|
35
|
-
|
36
|
-
module MediaType
|
37
|
-
|
38
|
-
# returns the decoder type for a specific content type
|
39
|
-
def self.type_for(content_type)
|
40
|
-
if Restfulie::MediaType.supports? content_type
|
41
|
-
Restfulie::MediaType.media_type(content_type)
|
42
|
-
else
|
43
|
-
Restfulie::MediaType::DefaultMediaTypeDecoder
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
# TODO removethis nasty method
|
48
|
-
def self.rendering_type(name, type)
|
49
|
-
Restfulie::MediaType.media_types[name] || Type.new(name,type)
|
50
|
-
end
|
51
|
-
|
52
|
-
# TODO remove this method
|
53
|
-
def self.custom_type(name, type, l)
|
54
|
-
Restfulie::MediaType.media_types[name] || CustomType.new(name, type, l)
|
55
|
-
end
|
56
|
-
|
57
|
-
class Type
|
58
|
-
attr_reader :name, :type
|
59
|
-
def initialize(name, type)
|
60
|
-
@name = name
|
61
|
-
@type = type
|
62
|
-
end
|
63
|
-
def short_name
|
64
|
-
name.gsub(/\//,'_').gsub(/\+/,'_').gsub(/\./,'_')
|
65
|
-
end
|
66
|
-
|
67
|
-
def format_name
|
68
|
-
name[/(.*[\+\/])?(.*)/,2]
|
69
|
-
end
|
70
|
-
def execute_for(controller, resource, options, render_options)
|
71
|
-
response = ["xml", "json"].include?(format_name) ? resource.send(:"to_#{format_name}", options) : resource
|
72
|
-
render(controller, response, render_options)
|
73
|
-
end
|
74
|
-
def render(controller, response, options)
|
75
|
-
options[:text] = response
|
76
|
-
options[:content_type] = name
|
77
|
-
controller.render options
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
class CustomType < Type
|
82
|
-
def initialize(name, type, l)
|
83
|
-
super(name, type)
|
84
|
-
@lambda = l
|
85
|
-
end
|
86
|
-
def execute_for(controller, resource, options, render_options)
|
87
|
-
@lambda.call
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
# from rails source code
|
92
|
-
def self.constantize(camel_cased_word)
|
93
|
-
unless /\A(?:::)?([A-Z]\w*(?:::[A-Z]\w*)*)\z/ =~ camel_cased_word
|
94
|
-
raise NameError, "#{camel_cased_word.inspect} is not a valid constant name!"
|
95
|
-
end
|
96
|
-
|
97
|
-
Object.module_eval("::#{$1}", __FILE__, __LINE__)
|
98
|
-
end
|
99
|
-
|
100
|
-
module DefaultMediaTypeDecoder
|
101
|
-
|
102
|
-
def self.from_xml(xml)
|
103
|
-
hash = Hash.from_xml xml
|
104
|
-
from_hash(hash)
|
105
|
-
end
|
106
|
-
|
107
|
-
def self.from_hash(hash)
|
108
|
-
|
109
|
-
type = Restfulie::MediaType.constantize(hash.keys.first.camelize) rescue Hashi
|
110
|
-
|
111
|
-
result = type.from_hash hash.values.first
|
112
|
-
return nil if result.nil?
|
113
|
-
result
|
114
|
-
|
115
|
-
end
|
116
|
-
|
117
|
-
def self.from_json(json)
|
118
|
-
hash = safe_json_decode(json)
|
119
|
-
type = hash.keys.first.camelize.constantize
|
120
|
-
type.from_hash(hash.values.first)
|
121
|
-
end
|
122
|
-
|
123
|
-
def self.from_html(body)
|
124
|
-
Hashi::CustomHash.new :body => body
|
125
|
-
end
|
126
|
-
|
127
|
-
def self.from_xhtml(body)
|
128
|
-
Hashi::CustomHash.new :body => body
|
129
|
-
end
|
130
|
-
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
|
-
end
|
135
|
-
|
136
|
-
def safe_json_decode(json)
|
137
|
-
return {} if !json
|
138
|
-
begin
|
139
|
-
ActiveSupport::JSON.decode json
|
140
|
-
rescue ; {} end
|
141
|
-
end
|
142
|
-
|
143
|
-
require 'restfulie/media_type_defaults'
|