wrest 0.0.9 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +34 -0
- data/README.rdoc +16 -10
- data/Rakefile +361 -123
- data/VERSION.yml +2 -2
- data/examples/delicious.rb +17 -7
- data/examples/facebook.rb +101 -0
- data/examples/keep_alive.rb +37 -0
- data/examples/twitter.rb +3 -3
- data/examples/twitter_public_timeline.rb +11 -4
- data/examples/wow_realm_status.rb +8 -2
- data/{spec/functional/sample_rails_app/public/favicon.ico → init.rb} +0 -0
- data/lib/wrest/components/{attributes_container → container}/alias_accessors.rb +4 -4
- data/lib/wrest/components/{attributes_container → container}/typecaster.rb +1 -1
- data/lib/wrest/components/{attributes_container.rb → container.rb} +46 -16
- data/lib/wrest/components/mutators.rb +4 -4
- data/lib/wrest/components/translators/json.rb +2 -2
- data/lib/wrest/components/translators/xml.rb +3 -2
- data/lib/wrest/components/translators.rb +3 -3
- data/lib/wrest/components.rb +3 -3
- data/lib/wrest/core_ext/hash.rb +1 -1
- data/lib/wrest/core_ext/string.rb +1 -1
- data/lib/wrest/curl/delete.rb +23 -0
- data/lib/wrest/curl/get.rb +23 -0
- data/lib/wrest/curl/options.rb +16 -0
- data/lib/wrest/curl/post.rb +23 -0
- data/lib/wrest/curl/put.rb +23 -0
- data/lib/wrest/curl/request.rb +95 -0
- data/lib/wrest/curl/response.rb +63 -0
- data/lib/wrest/curl/session.rb +57 -0
- data/lib/wrest/curl.rb +49 -0
- data/lib/wrest/exceptions.rb +16 -1
- data/lib/wrest/http_shared/headers.rb +350 -0
- data/lib/wrest/http_shared/standard_headers.rb +21 -0
- data/lib/wrest/http_shared/standard_tokens.rb +18 -0
- data/lib/wrest/http_shared.rb +24 -0
- data/lib/wrest/native/connection_factory.rb +23 -0
- data/lib/wrest/{http → native}/delete.rb +1 -1
- data/lib/wrest/{http → native}/get.rb +1 -1
- data/lib/wrest/{http → native}/options.rb +1 -1
- data/lib/wrest/{http → native}/post.rb +1 -1
- data/lib/wrest/{http → native}/put.rb +1 -1
- data/lib/wrest/{http → native}/redirection.rb +4 -1
- data/lib/wrest/{http → native}/request.rb +32 -20
- data/lib/wrest/{http → native}/response.rb +12 -4
- data/lib/wrest/native/session.rb +57 -0
- data/lib/wrest/native.rb +32 -0
- data/lib/wrest/resource/base.rb +1 -1
- data/lib/wrest/resource.rb +1 -1
- data/lib/wrest/test/request_patches.rb +5 -0
- data/lib/wrest/test.rb +1 -0
- data/lib/wrest/uri.rb +31 -3
- data/lib/wrest/version.rb +2 -2
- data/lib/wrest.rb +52 -16
- data/spec/unit/spec_helper.rb +12 -3
- data/spec/unit/wrest/components/attributes_container/alias_accessors_spec.rb +2 -2
- data/spec/unit/wrest/components/attributes_container/typecaster_spec.rb +6 -6
- data/spec/unit/wrest/components/attributes_container_spec.rb +44 -12
- data/spec/unit/wrest/components/translators/xml_spec.rb +7 -3
- data/spec/unit/wrest/curl/request_spec.rb +19 -0
- data/spec/unit/wrest/curl/response_spec.rb +16 -0
- data/spec/unit/wrest/http/response_spec.rb +17 -38
- data/spec/unit/wrest/{http → native}/redirection_spec.rb +5 -5
- data/spec/unit/wrest/{http → native}/request_spec.rb +15 -14
- data/spec/unit/wrest/native/response_spec.rb +72 -0
- data/spec/unit/wrest/native/session_spec.rb +74 -0
- data/spec/unit/wrest/resource/base_spec.rb +2 -2
- data/spec/unit/wrest/uri_spec.rb +51 -11
- data/wrest.gemspec +164 -0
- metadata +51 -165
- data/lib/wrest/http.rb +0 -25
- data/spec/functional/sample_rails_app/README +0 -3
- data/spec/functional/sample_rails_app/Rakefile +0 -10
- data/spec/functional/sample_rails_app/app/controllers/application_controller.rb +0 -10
- data/spec/functional/sample_rails_app/app/controllers/lead_bottles_controller.rb +0 -7
- data/spec/functional/sample_rails_app/app/helpers/application_helper.rb +0 -3
- data/spec/functional/sample_rails_app/app/models/bottle.rb +0 -3
- data/spec/functional/sample_rails_app/app/models/glass_bottle.rb +0 -3
- data/spec/functional/sample_rails_app/app/models/lead_bottle.rb +0 -3
- data/spec/functional/sample_rails_app/config/boot.rb +0 -110
- data/spec/functional/sample_rails_app/config/database.yml +0 -16
- data/spec/functional/sample_rails_app/config/environment.rb +0 -42
- data/spec/functional/sample_rails_app/config/environments/development.rb +0 -17
- data/spec/functional/sample_rails_app/config/environments/production.rb +0 -28
- data/spec/functional/sample_rails_app/config/environments/test.rb +0 -28
- data/spec/functional/sample_rails_app/config/initializers/backtrace_silencers.rb +0 -7
- data/spec/functional/sample_rails_app/config/initializers/inflections.rb +0 -10
- data/spec/functional/sample_rails_app/config/initializers/mime_types.rb +0 -5
- data/spec/functional/sample_rails_app/config/initializers/new_rails_defaults.rb +0 -19
- data/spec/functional/sample_rails_app/config/initializers/session_store.rb +0 -15
- data/spec/functional/sample_rails_app/config/locales/en.yml +0 -5
- data/spec/functional/sample_rails_app/config/routes.rb +0 -3
- data/spec/functional/sample_rails_app/db/development.sqlite3 +0 -0
- data/spec/functional/sample_rails_app/db/migrate/20090319115628_create_bottle.rb +0 -13
- data/spec/functional/sample_rails_app/db/schema.rb +0 -20
- data/spec/functional/sample_rails_app/db/test.sqlite3 +0 -0
- data/spec/functional/sample_rails_app/log/development.log +0 -1
- data/spec/functional/sample_rails_app/public/404.html +0 -30
- data/spec/functional/sample_rails_app/public/422.html +0 -30
- data/spec/functional/sample_rails_app/public/500.html +0 -30
- data/spec/functional/sample_rails_app/public/images/rails.png +0 -0
- data/spec/functional/sample_rails_app/public/index.html +0 -275
- data/spec/functional/sample_rails_app/public/robots.txt +0 -5
- data/spec/functional/sample_rails_app/script/about +0 -4
- data/spec/functional/sample_rails_app/script/autospec +0 -6
- data/spec/functional/sample_rails_app/script/console +0 -3
- data/spec/functional/sample_rails_app/script/dbconsole +0 -3
- data/spec/functional/sample_rails_app/script/destroy +0 -3
- data/spec/functional/sample_rails_app/script/generate +0 -3
- data/spec/functional/sample_rails_app/script/performance/benchmarker +0 -3
- data/spec/functional/sample_rails_app/script/performance/profiler +0 -3
- data/spec/functional/sample_rails_app/script/plugin +0 -3
- data/spec/functional/sample_rails_app/script/runner +0 -3
- data/spec/functional/sample_rails_app/script/server +0 -3
- data/spec/functional/sample_rails_app/script/spec +0 -10
- data/spec/functional/sample_rails_app/script/spec_server +0 -9
- data/spec/functional/sample_rails_app/test/performance/browsing_test.rb +0 -9
- data/spec/functional/sample_rails_app/test/test_helper.rb +0 -38
- data/spec/functional/sample_rails_app/tmtags +0 -2559
- data/spec/functional/sample_rails_app/vendor/plugins/resource_full/MIT-LICENSE +0 -20
- data/spec/functional/sample_rails_app/vendor/plugins/resource_full/README.rdoc +0 -100
- data/spec/functional/sample_rails_app/vendor/plugins/resource_full/Rakefile +0 -18
- data/spec/functional/sample_rails_app/vendor/plugins/resource_full/init.rb +0 -5
- data/spec/functional/sample_rails_app/vendor/plugins/resource_full/install.rb +0 -1
- data/spec/functional/sample_rails_app/vendor/plugins/resource_full/lib/resource_full/base.rb +0 -140
- data/spec/functional/sample_rails_app/vendor/plugins/resource_full/lib/resource_full/controllers/resources.rb +0 -16
- data/spec/functional/sample_rails_app/vendor/plugins/resource_full/lib/resource_full/controllers/resources_controller.rb +0 -26
- data/spec/functional/sample_rails_app/vendor/plugins/resource_full/lib/resource_full/controllers/routes_controller.rb +0 -16
- data/spec/functional/sample_rails_app/vendor/plugins/resource_full/lib/resource_full/core_extensions/api.rb +0 -26
- data/spec/functional/sample_rails_app/vendor/plugins/resource_full/lib/resource_full/core_extensions/exception.rb +0 -23
- data/spec/functional/sample_rails_app/vendor/plugins/resource_full/lib/resource_full/core_extensions/from_json.rb +0 -15
- data/spec/functional/sample_rails_app/vendor/plugins/resource_full/lib/resource_full/dispatch.rb +0 -235
- data/spec/functional/sample_rails_app/vendor/plugins/resource_full/lib/resource_full/models/resourced_route.rb +0 -84
- data/spec/functional/sample_rails_app/vendor/plugins/resource_full/lib/resource_full/query.rb +0 -337
- data/spec/functional/sample_rails_app/vendor/plugins/resource_full/lib/resource_full/render/html.rb +0 -50
- data/spec/functional/sample_rails_app/vendor/plugins/resource_full/lib/resource_full/render/json.rb +0 -75
- data/spec/functional/sample_rails_app/vendor/plugins/resource_full/lib/resource_full/render/xml.rb +0 -65
- data/spec/functional/sample_rails_app/vendor/plugins/resource_full/lib/resource_full/render.rb +0 -63
- data/spec/functional/sample_rails_app/vendor/plugins/resource_full/lib/resource_full/retrieve.rb +0 -74
- data/spec/functional/sample_rails_app/vendor/plugins/resource_full/lib/resource_full/version.rb +0 -9
- data/spec/functional/sample_rails_app/vendor/plugins/resource_full/lib/resource_full.rb +0 -14
- data/spec/functional/sample_rails_app/vendor/plugins/resource_full/spec/resource_full/base_spec.rb +0 -88
- data/spec/functional/sample_rails_app/vendor/plugins/resource_full/spec/resource_full/controllers/resources_spec.rb +0 -29
- data/spec/functional/sample_rails_app/vendor/plugins/resource_full/spec/resource_full/dispatch_spec.rb +0 -262
- data/spec/functional/sample_rails_app/vendor/plugins/resource_full/spec/resource_full/models/resourced_route_spec.rb +0 -62
- data/spec/functional/sample_rails_app/vendor/plugins/resource_full/spec/resource_full/query/parameter_spec.rb +0 -57
- data/spec/functional/sample_rails_app/vendor/plugins/resource_full/spec/resource_full/query_spec.rb +0 -462
- data/spec/functional/sample_rails_app/vendor/plugins/resource_full/spec/resource_full/render/html_spec.rb +0 -4
- data/spec/functional/sample_rails_app/vendor/plugins/resource_full/spec/resource_full/render/json_spec.rb +0 -107
- data/spec/functional/sample_rails_app/vendor/plugins/resource_full/spec/resource_full/render/xml_spec.rb +0 -98
- data/spec/functional/sample_rails_app/vendor/plugins/resource_full/spec/resource_full/render_spec.rb +0 -5
- data/spec/functional/sample_rails_app/vendor/plugins/resource_full/spec/resource_full/retrieve_spec.rb +0 -173
- data/spec/functional/sample_rails_app/vendor/plugins/resource_full/spec/spec_helper.rb +0 -98
- data/spec/functional/sample_rails_app/vendor/plugins/resource_full/uninstall.rb +0 -1
- data/spec/functional/spec_helper.rb +0 -0
@@ -0,0 +1,24 @@
|
|
1
|
+
# Copyright 2009 Sidu Ponnappa
|
2
|
+
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at native://www.apache.org/licenses/LICENSE-2.0
|
6
|
+
# Unless required by applicable law or agreed to in writing, software distributed under the License
|
7
|
+
# is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
8
|
+
# See the License for the specific language governing permissions and limitations under the License.
|
9
|
+
|
10
|
+
module Wrest #:nodoc:
|
11
|
+
|
12
|
+
# Contains functionality the is independent of
|
13
|
+
# the underlying HTTP libs
|
14
|
+
module HttpShared
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
require "#{Wrest::Root}/wrest/http_shared/headers"
|
19
|
+
require "#{Wrest::Root}/wrest/http_shared/standard_headers"
|
20
|
+
require "#{Wrest::Root}/wrest/http_shared/standard_tokens"
|
21
|
+
|
22
|
+
# Set up a shorter convenience API for constants
|
23
|
+
Wrest::H = Wrest::HttpShared::StandardHeaders
|
24
|
+
Wrest::T = Wrest::HttpShared::StandardTokens
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# Copyright 2009 Sidu Ponnappa
|
2
|
+
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
6
|
+
# Unless required by applicable law or agreed to in writing, software distributed under the License
|
7
|
+
# is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
8
|
+
# See the License for the specific language governing permissions and limitations under the License.
|
9
|
+
|
10
|
+
module Wrest::Native
|
11
|
+
module ConnectionFactory
|
12
|
+
def create_connection(timeout = 60)
|
13
|
+
timeout ||= 60
|
14
|
+
connection = Net::HTTP.new(self.host, self.port)
|
15
|
+
connection.read_timeout = timeout
|
16
|
+
if self.https?
|
17
|
+
connection.use_ssl = true
|
18
|
+
connection.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
19
|
+
end
|
20
|
+
connection
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -7,7 +7,7 @@
|
|
7
7
|
# is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
8
8
|
# See the License for the specific language governing permissions and limitations under the License.
|
9
9
|
|
10
|
-
module Wrest::
|
10
|
+
module Wrest::Native
|
11
11
|
class Delete < Request
|
12
12
|
def initialize(wrest_uri, parameters = {}, headers = {}, options = {})
|
13
13
|
super(
|
@@ -7,7 +7,7 @@
|
|
7
7
|
# is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
8
8
|
# See the License for the specific language governing permissions and limitations under the License.
|
9
9
|
|
10
|
-
module Wrest::
|
10
|
+
module Wrest::Native
|
11
11
|
class Get < Request
|
12
12
|
def initialize(wrest_uri, parameters = {}, headers = {}, options = {})
|
13
13
|
follow_redirects = options[:follow_redirects]
|
@@ -7,7 +7,7 @@
|
|
7
7
|
# is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
8
8
|
# See the License for the specific language governing permissions and limitations under the License.
|
9
9
|
|
10
|
-
module Wrest::
|
10
|
+
module Wrest::Native
|
11
11
|
class Options < Request
|
12
12
|
def initialize(wrest_uri, options = {})
|
13
13
|
super(
|
@@ -7,7 +7,7 @@
|
|
7
7
|
# is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
8
8
|
# See the License for the specific language governing permissions and limitations under the License.
|
9
9
|
|
10
|
-
module Wrest::
|
10
|
+
module Wrest::Native
|
11
11
|
class Post < Request
|
12
12
|
def initialize(wrest_uri, body = '', headers = {}, parameters = {}, options = {})
|
13
13
|
super(
|
@@ -7,7 +7,7 @@
|
|
7
7
|
# is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
8
8
|
# See the License for the specific language governing permissions and limitations under the License.
|
9
9
|
|
10
|
-
module Wrest::
|
10
|
+
module Wrest::Native
|
11
11
|
class Put < Request
|
12
12
|
def initialize(wrest_uri, body = '', headers = {}, parameters = {}, options = {})
|
13
13
|
super(
|
@@ -8,9 +8,12 @@
|
|
8
8
|
# See the License for the specific language governing permissions and limitations under the License.
|
9
9
|
|
10
10
|
module Wrest #:nodoc:
|
11
|
-
module
|
11
|
+
module Native #:nodoc:
|
12
12
|
# Constructed by Wrest::Response.new if the HTTP response code is 3xx
|
13
13
|
# (http://en.wikipedia.org/wiki/300_Multiple_Choices#3xx_Redirection)
|
14
|
+
#
|
15
|
+
# This class is necessary because Net::HTTP doesn't seem to support
|
16
|
+
# redirection natively.
|
14
17
|
class Redirection < Response
|
15
18
|
|
16
19
|
# A get is invoked on the url stored in the response headers
|
@@ -7,13 +7,13 @@
|
|
7
7
|
# is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
8
8
|
# See the License for the specific language governing permissions and limitations under the License.
|
9
9
|
|
10
|
-
module Wrest::
|
10
|
+
module Wrest::Native
|
11
11
|
# This represents a HTTP request. Typically you will never need to instantiate
|
12
12
|
# one of these yourself - you can use one of the more conveient APIs via Wrest::Uri
|
13
13
|
# or Wrest::Http::Get etc. instead.
|
14
14
|
class Request
|
15
|
-
attr_reader :http_request, :uri, :body, :headers, :username, :password, :follow_redirects,
|
16
|
-
:follow_redirects_limit, :follow_redirects_count, :timeout
|
15
|
+
attr_reader :http_request, :uri, :body, :headers, :username, :password, :follow_redirects,
|
16
|
+
:follow_redirects_limit, :follow_redirects_count, :timeout, :connection, :parameters
|
17
17
|
# Valid tuples for the options are:
|
18
18
|
# :username => String, defaults to nil
|
19
19
|
# :password => String, defaults to nil
|
@@ -28,10 +28,13 @@ module Wrest::Http
|
|
28
28
|
# until the follow_redirects_limit is hit. You should never set
|
29
29
|
# this option yourself.
|
30
30
|
# :timeout => The period, in seconds, after which a Timeout::Error is raised
|
31
|
-
# in the event of a connection failing to open.
|
31
|
+
# in the event of a connection failing to open. Defaulted to 60 by Uri#create_connection.
|
32
|
+
# :connection => The HTTP Connection object to use. This is how a keep-alive connection can be
|
33
|
+
# used for multiple requests.
|
32
34
|
def initialize(wrest_uri, http_request_klass, parameters = {}, body = nil, headers = {}, options = {})
|
33
35
|
@uri = wrest_uri
|
34
36
|
@headers = headers.stringify_keys
|
37
|
+
@parameters = parameters
|
35
38
|
@http_request = http_request_klass.new(parameters.empty? ? wrest_uri.full_path : "#{wrest_uri.full_path}?#{parameters.to_query}", @headers)
|
36
39
|
@body = body
|
37
40
|
@options = options.clone
|
@@ -40,33 +43,42 @@ module Wrest::Http
|
|
40
43
|
@follow_redirects = (@options[:follow_redirects] ||= false)
|
41
44
|
@follow_redirects_count = (@options[:follow_redirects_count] ||= 0)
|
42
45
|
@follow_redirects_limit = (@options[:follow_redirects_limit] ||= 5)
|
43
|
-
@timeout =
|
46
|
+
@timeout = @options[:timeout]
|
47
|
+
@connection = @options[:connection]
|
44
48
|
end
|
45
49
|
|
46
|
-
# Makes a request and returns a Wrest::
|
50
|
+
# Makes a request and returns a Wrest::Native::Response.
|
47
51
|
# Data about the request is and logged to Wrest.logger
|
52
|
+
# The log entry contains the following information:
|
53
|
+
#
|
54
|
+
# --> indicates a request
|
55
|
+
# <-- indicates a response
|
56
|
+
#
|
57
|
+
# The type of request is mentioned in caps, followed by a hash
|
58
|
+
# uniquely uniquely identifying a particular request/response pair.
|
59
|
+
# In a multi-process or multi-threaded scenario, this can be used
|
60
|
+
# to identify request-response pairs.
|
61
|
+
#
|
62
|
+
# The request hash is followed by a connection hash; requests using the
|
63
|
+
# same connection (effectively a keep-alive connection) will have the
|
64
|
+
# same connection hash.
|
65
|
+
#
|
66
|
+
# This is followed by the response code, the payload size and the time taken.
|
48
67
|
def invoke
|
49
68
|
response = nil
|
50
|
-
|
51
|
-
|
52
|
-
http_connection = create_connection(timeout)
|
69
|
+
|
70
|
+
@connection ||= @uri.create_connection(timeout)
|
53
71
|
http_request.basic_auth username, password
|
54
72
|
|
73
|
+
prefix = "#{http_request.method} #{http_request.hash} #{@connection.hash}"
|
74
|
+
|
55
75
|
Wrest.logger.debug "--> (#{prefix}) #{@uri.protocol}://#{@uri.host}:#{@uri.port}#{@http_request.path}"
|
56
|
-
time = Benchmark.realtime { response = Wrest::
|
76
|
+
time = Benchmark.realtime { response = Wrest::Native::Response.new( @connection.request(@http_request, @body) ) }
|
57
77
|
Wrest.logger.debug "<-- (#{prefix}) %d %s (%d bytes %.2fs)" % [response.code, response.message, response.body ? response.body.length : 0, time]
|
58
78
|
|
59
79
|
@follow_redirects ? response.follow(@options) : response
|
60
|
-
|
61
|
-
|
62
|
-
def create_connection(timeout)
|
63
|
-
connection = Net::HTTP.new(@uri.host, @uri.port)
|
64
|
-
connection.read_timeout = timeout
|
65
|
-
if @uri.https?
|
66
|
-
connection.use_ssl = true
|
67
|
-
connection.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
68
|
-
end
|
69
|
-
connection
|
80
|
+
rescue Timeout::Error => e
|
81
|
+
raise Wrest::Exceptions::Timeout.new(e)
|
70
82
|
end
|
71
83
|
end
|
72
84
|
end
|
@@ -8,10 +8,10 @@
|
|
8
8
|
# See the License for the specific language governing permissions and limitations under the License.
|
9
9
|
|
10
10
|
module Wrest #:nodoc:
|
11
|
-
module
|
11
|
+
module Native #:nodoc:
|
12
12
|
# Decorates a response providing support for deserialisation.
|
13
13
|
#
|
14
|
-
# The following methods are also available (unlisted by rdoc because they're forwarded):
|
14
|
+
# The following methods are also available (unlisted by rdoc because they're forwarded to Net::HTTP::Response):
|
15
15
|
#
|
16
16
|
# <tt>:@Http_response, :code, :message, :body, :Http_version,
|
17
17
|
# :[], :content_length, :content_type, :each_header, :each_name, :each_value, :fetch,
|
@@ -19,15 +19,19 @@ module Wrest #:nodoc:
|
|
19
19
|
#
|
20
20
|
# They behave exactly like their Net::HttpResponse equivalents.
|
21
21
|
class Response
|
22
|
+
attr_reader :http_response
|
23
|
+
|
22
24
|
extend Forwardable
|
23
25
|
def_delegators :@http_response, :code, :message, :body, :Http_version,
|
24
26
|
:[], :content_length, :content_type, :each_header, :each_name, :each_value, :fetch,
|
25
27
|
:get_fields, :key?, :type_params
|
26
28
|
|
27
29
|
# We're overriding :new to act as a factory so
|
28
|
-
# we can build the appropriate Response instance
|
30
|
+
# we can build the appropriate Response instance based
|
31
|
+
# on th response code.
|
29
32
|
def self.new(http_response)
|
30
|
-
|
33
|
+
code = http_response.code.to_i
|
34
|
+
instance = ((300..303).include?(code) || (305..399).include?(code) ? Wrest::Native::Redirection : self).allocate
|
31
35
|
instance.send :initialize, http_response
|
32
36
|
instance
|
33
37
|
end
|
@@ -56,6 +60,10 @@ module Wrest #:nodoc:
|
|
56
60
|
def follow(redirect_request_options = {})
|
57
61
|
self
|
58
62
|
end
|
63
|
+
|
64
|
+
def connection_closed?
|
65
|
+
self[Native::StandardHeaders::Connection].downcase == Native::StandardTokens::Close.downcase
|
66
|
+
end
|
59
67
|
end
|
60
68
|
end
|
61
69
|
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# Copyright 2009 Sidu Ponnappa
|
2
|
+
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
6
|
+
# Unless required by applicable law or agreed to in writing, software distributed under the License
|
7
|
+
# is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
8
|
+
# See the License for the specific language governing permissions and limitations under the License.
|
9
|
+
|
10
|
+
module Wrest::Native
|
11
|
+
# This class is a wrapper for a keep-alive HTTP connection. It simply passes the
|
12
|
+
# same connection instance as an option to all Wrest::Http::Request instances created using it.
|
13
|
+
#
|
14
|
+
# If at any point the server closes an existing connection during a Session by returning a
|
15
|
+
# Connection: Close header the current connection is destroyed and a fresh one created for the next
|
16
|
+
# request.
|
17
|
+
#
|
18
|
+
# The Session constructor can accept either a String URI or a Wrest::Uri as a parameter. If you
|
19
|
+
# need HTTP authentication, you should use a Wrest::Uri.
|
20
|
+
class Session
|
21
|
+
attr_reader :uri
|
22
|
+
def initialize(uri)
|
23
|
+
@uri = uri.is_a?(String) ? uri.to_uri : uri
|
24
|
+
@default_headers = { Wrest::Native::StandardHeaders::Connection => Wrest::Native::StandardTokens::KeepAlive }
|
25
|
+
|
26
|
+
yield(self) if block_given?
|
27
|
+
end
|
28
|
+
|
29
|
+
def connection
|
30
|
+
@connection ||= @uri.create_connection
|
31
|
+
end
|
32
|
+
|
33
|
+
def get(path = '', parameters = {}, headers = {})
|
34
|
+
maybe_destroy_connection @uri[path, {:connection => self.connection}].get(parameters, headers.merge(@default_headers))
|
35
|
+
end
|
36
|
+
|
37
|
+
def post(path = '', body = '', headers = {}, params = {})
|
38
|
+
maybe_destroy_connection @uri[path, {:connection => self.connection}].post(body, headers.merge(@default_headers), params)
|
39
|
+
end
|
40
|
+
|
41
|
+
def put(path = '', body = '', headers = {}, params = {})
|
42
|
+
maybe_destroy_connection @uri[path, {:connection => self.connection}].put(body, headers.merge(@default_headers), params)
|
43
|
+
end
|
44
|
+
|
45
|
+
def delete(path = '', parameters = {}, headers = {})
|
46
|
+
maybe_destroy_connection @uri[path, {:connection => self.connection}].delete(parameters, headers.merge(@default_headers))
|
47
|
+
end
|
48
|
+
|
49
|
+
def maybe_destroy_connection(response)
|
50
|
+
if response.connection_closed?
|
51
|
+
Wrest.logger.warn "Connection #{@connection.hash} has been closed by the server"
|
52
|
+
@connection = nil
|
53
|
+
end
|
54
|
+
response
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
data/lib/wrest/native.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# Copyright 2009 Sidu Ponnappa
|
2
|
+
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at native://www.apache.org/licenses/LICENSE-2.0
|
6
|
+
# Unless required by applicable law or agreed to in writing, software distributed under the License
|
7
|
+
# is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
8
|
+
# See the License for the specific language governing permissions and limitations under the License.
|
9
|
+
|
10
|
+
module Wrest #:nodoc:
|
11
|
+
|
12
|
+
# Contains all native protocol related classes such as
|
13
|
+
# Get, Post, Request, Response etc. and uses the native
|
14
|
+
# Ruby Net::native libraries.
|
15
|
+
module Native
|
16
|
+
include Wrest::HttpShared
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
require "#{Wrest::Root}/wrest/native/connection_factory"
|
21
|
+
require "#{Wrest::Root}/wrest/native/response"
|
22
|
+
require "#{Wrest::Root}/wrest/native/redirection"
|
23
|
+
require "#{Wrest::Root}/wrest/native/request"
|
24
|
+
require "#{Wrest::Root}/wrest/native/get"
|
25
|
+
require "#{Wrest::Root}/wrest/native/put"
|
26
|
+
require "#{Wrest::Root}/wrest/native/post"
|
27
|
+
require "#{Wrest::Root}/wrest/native/delete"
|
28
|
+
require "#{Wrest::Root}/wrest/native/options"
|
29
|
+
require "#{Wrest::Root}/wrest/native/session"
|
30
|
+
|
31
|
+
# default to using Native libs
|
32
|
+
Wrest::Http = Wrest::Native
|
data/lib/wrest/resource/base.rb
CHANGED
@@ -11,7 +11,7 @@ module Wrest::Resource #:nodoc:
|
|
11
11
|
# Resource::Base is the equivalent of ActiveResource::Base.
|
12
12
|
# It is a REST client targetted at Rails REST apps.
|
13
13
|
class Base
|
14
|
-
include Wrest::Components::
|
14
|
+
include Wrest::Components::Container
|
15
15
|
|
16
16
|
always_has :id
|
17
17
|
typecast :id => as_integer
|
data/lib/wrest/resource.rb
CHANGED
data/lib/wrest/test.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "#{Wrest::Root}/wrest/test/request_patches"
|
data/lib/wrest/uri.rb
CHANGED
@@ -22,14 +22,13 @@ module Wrest #:nodoc:
|
|
22
22
|
#
|
23
23
|
# You can find examples that use real APIs (like delicious) under the wrest/examples directory.
|
24
24
|
class Uri
|
25
|
-
attr_reader :uri, :username, :password
|
26
|
-
|
25
|
+
attr_reader :uri, :username, :password, :uri_string
|
26
|
+
|
27
27
|
# See Wrest::Http::Request for the available options and their default values.
|
28
28
|
def initialize(uri_string, options = {})
|
29
29
|
@options = options
|
30
30
|
@uri_string = uri_string.clone
|
31
31
|
@uri = URI.parse(uri_string)
|
32
|
-
@options = options
|
33
32
|
@username = (@options[:username] ||= @uri.user)
|
34
33
|
@password = (@options[:password] ||= @uri.password)
|
35
34
|
end
|
@@ -53,6 +52,12 @@ module Wrest #:nodoc:
|
|
53
52
|
Uri.new(@uri_string+path, options || @options)
|
54
53
|
end
|
55
54
|
|
55
|
+
# Clones a Uri, building a new instance with exactly the same uri string.
|
56
|
+
# You can however change the Uri options or add new ones.
|
57
|
+
def clone(opts = {})
|
58
|
+
Uri.new(@uri_string, @options.merge(opts))
|
59
|
+
end
|
60
|
+
|
56
61
|
def eql?(other)
|
57
62
|
self == other
|
58
63
|
end
|
@@ -66,6 +71,13 @@ module Wrest #:nodoc:
|
|
66
71
|
@uri.hash + @username.hash + @password.hash + 20090423
|
67
72
|
end
|
68
73
|
|
74
|
+
# This produces exactly the same string as the Wrest::Uri was constructed with.
|
75
|
+
# If the orignial URI contained a HTTP username and password, that too will
|
76
|
+
# show up, so be careful if using this for logging.
|
77
|
+
def to_s
|
78
|
+
uri_string
|
79
|
+
end
|
80
|
+
|
69
81
|
# Make a GET request to this URI. This is a convenience API
|
70
82
|
# that creates a Wrest::Http::Get, executes it and returns a Wrest::Http::Response.
|
71
83
|
#
|
@@ -84,11 +96,25 @@ module Wrest #:nodoc:
|
|
84
96
|
|
85
97
|
# Makes a POST request to this URI. This is a convenience API
|
86
98
|
# that creates a Wrest::Http::Post, executes it and returns a Wrest::Http::Response.
|
99
|
+
# Note that sending an empty body will blow up if you're using libcurl.
|
87
100
|
#
|
88
101
|
# Remember to escape all parameter strings if necessary, using URI.escape
|
89
102
|
def post(body = '', headers = {}, parameters = {})
|
90
103
|
Http::Post.new(self, body.to_s, headers, parameters, @options).invoke
|
91
104
|
end
|
105
|
+
|
106
|
+
# Makes a POST request to this URI. This is a convenience API
|
107
|
+
# that mimics a form being posted; some allegly RESTful APIs like FCBK
|
108
|
+
# require this to be used.
|
109
|
+
#
|
110
|
+
# Form encoding involves munging the parameters into a string and placing them
|
111
|
+
# in the body, as well as setting the Content-Type header to
|
112
|
+
# application/x-www-form-urlencoded
|
113
|
+
def post_form(parameters = {}, headers = {})
|
114
|
+
headers = headers.merge(Wrest::H::ContentType => Wrest::T::FormEncoded)
|
115
|
+
body = parameters.to_query
|
116
|
+
Http::Post.new(self, body, headers, {}, @options).invoke
|
117
|
+
end
|
92
118
|
|
93
119
|
# Makes a DELETE request to this URI. This is a convenience API
|
94
120
|
# that creates a Wrest::Http::Delete, executes it and returns a Wrest::Http::Response.
|
@@ -128,5 +154,7 @@ module Wrest #:nodoc:
|
|
128
154
|
def port
|
129
155
|
uri.port
|
130
156
|
end
|
157
|
+
|
158
|
+
include Http::ConnectionFactory
|
131
159
|
end
|
132
160
|
end
|
data/lib/wrest/version.rb
CHANGED
data/lib/wrest.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
# Copyright 2009 Sidu Ponnappa
|
2
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
3
|
-
# you may not use this file except in compliance with the License.
|
4
|
-
# You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
5
|
-
# Unless required by applicable law or agreed to in writing, software distributed under the License
|
6
|
-
# is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
7
|
-
# See the License for the specific language governing permissions and limitations under the License.
|
2
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
3
|
+
# you may not use this file except in compliance with the License.
|
4
|
+
# You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
5
|
+
# Unless required by applicable law or agreed to in writing, software distributed under the License
|
6
|
+
# is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
7
|
+
# See the License for the specific language governing permissions and limitations under the License.
|
8
8
|
|
9
9
|
require 'rubygems'
|
10
|
-
gem 'activesupport', '>= 2.3.
|
10
|
+
gem 'activesupport', '>= 2.3.5'
|
11
11
|
|
12
12
|
require 'net/http'
|
13
13
|
require 'net/https'
|
@@ -19,16 +19,25 @@ require 'logger'
|
|
19
19
|
require 'benchmark'
|
20
20
|
require 'active_support'
|
21
21
|
|
22
|
-
WREST_ROOT = File.dirname(__FILE__)
|
23
22
|
|
24
23
|
module Wrest #:nodoc:
|
24
|
+
Root = File.dirname(__FILE__)
|
25
25
|
def self.logger=(logger)
|
26
26
|
@logger = logger
|
27
27
|
end
|
28
|
-
|
28
|
+
|
29
29
|
def self.logger
|
30
30
|
@logger
|
31
31
|
end
|
32
|
+
|
33
|
+
def self.use_native
|
34
|
+
silence_warnings{ Wrest.const_set('Http', Wrest::Native) }
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.use_curl
|
38
|
+
require "#{Wrest::Root}/wrest/curl"
|
39
|
+
silence_warnings{ Wrest.const_set('Http', Wrest::Curl) }
|
40
|
+
end
|
32
41
|
end
|
33
42
|
|
34
43
|
Wrest.logger = ActiveSupport::BufferedLogger.new(STDOUT)
|
@@ -38,13 +47,40 @@ begin
|
|
38
47
|
gem 'libxml-ruby', '>= 1.1.3'
|
39
48
|
ActiveSupport::XmlMini.backend='LibXML'
|
40
49
|
rescue Gem::LoadError
|
41
|
-
Wrest.logger.
|
50
|
+
Wrest.logger.debug "Warning: LibXML >= 1.1.3 not found, attempting to use Nokogiri. To install LibXML run `(sudo) gem install libxml-ruby` (libxml-ruby is not available on JRuby)"
|
51
|
+
begin
|
52
|
+
gem 'nokogiri', '>= 1.3.3'
|
53
|
+
ActiveSupport::XmlMini.backend='Nokogiri'
|
54
|
+
rescue Gem::LoadError
|
55
|
+
Wrest.logger.debug "Warning: Nokogiri >= 1.3.3 not found, falling back to #{ActiveSupport::XmlMini.backend} (which is probably significantly slower). To install Nokogiri run `(sudo) (jruby -S) gem install nokogiri`"
|
56
|
+
if RUBY_PLATFORM =~ /java/
|
57
|
+
begin
|
58
|
+
gem 'jrexml', '>= 0.5.3'
|
59
|
+
require 'jrexml'
|
60
|
+
Wrest.logger.debug "Detected JRuby, JREXML loaded."
|
61
|
+
rescue Gem::LoadError
|
62
|
+
Wrest.logger.debug "Warning: Detected JRuby, but failed to load JREXML. JREXML offers *some* performance improvement when using REXML on JRuby. To install JREXML run `(sudo) jruby -S gem install jrexml`"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
42
66
|
end
|
43
67
|
|
44
|
-
|
68
|
+
Dir["#{File.expand_path(File.dirname(__FILE__))}/wrest/core_ext/*.rb"].each { |file| require file }
|
69
|
+
|
70
|
+
# Load Wrest Core
|
71
|
+
require "#{Wrest::Root}/wrest/http_shared"
|
72
|
+
require "#{Wrest::Root}/wrest/native"
|
73
|
+
|
74
|
+
# Load Wrest Wrappers
|
75
|
+
require "#{Wrest::Root}/wrest/uri"
|
76
|
+
require "#{Wrest::Root}/wrest/uri_template"
|
77
|
+
require "#{Wrest::Root}/wrest/version"
|
78
|
+
require "#{Wrest::Root}/wrest/exceptions"
|
79
|
+
require "#{Wrest::Root}/wrest/components"
|
80
|
+
|
81
|
+
# Load Wrest::Resource
|
82
|
+
require "#{Wrest::Root}/wrest/resource"
|
45
83
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
}
|
50
|
-
}
|
84
|
+
# if (ENV['RAILS_ENV'] == 'test' || (Kernel.const_defined?(:RAILS_ENV) && (RAILS_ENV == 'test')))
|
85
|
+
# require "#{Wrest::Root}/wrest/test"
|
86
|
+
# end
|
data/spec/unit/spec_helper.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + "/../../lib/wrest")
|
2
|
+
require "#{Wrest::Root}/wrest/curl" unless RUBY_PLATFORM =~ /java/
|
2
3
|
require 'spec'
|
3
4
|
|
4
5
|
['/../custom_matchers/**/*.rb'].each{|directory|
|
@@ -7,7 +8,7 @@ require 'spec'
|
|
7
8
|
}
|
8
9
|
}
|
9
10
|
|
10
|
-
Wrest.logger = Logger.new(File.open("#{
|
11
|
+
Wrest.logger = Logger.new(File.open("#{Wrest::Root}/../log/test.log", 'a'))
|
11
12
|
|
12
13
|
def p(*args)
|
13
14
|
# super *(args << caller[0])
|
@@ -17,10 +18,18 @@ end
|
|
17
18
|
|
18
19
|
def puts(*args)
|
19
20
|
# super *(args << caller[0])
|
20
|
-
super *(args
|
21
|
+
super *(['<pre>'] + args + ['</pre>'])
|
21
22
|
# super *args
|
22
23
|
end
|
23
24
|
|
24
25
|
Spec::Runner.configure do |config|
|
25
26
|
config.include(CustomMatchers)
|
26
|
-
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def build_ok_response(body = '')
|
30
|
+
returning mock(Net::HTTPOK) do |response|
|
31
|
+
response.stub!(:code).and_return('200')
|
32
|
+
response.stub!(:message).and_return('OK')
|
33
|
+
response.stub!(:body).and_return(body)
|
34
|
+
end
|
35
|
+
end
|
@@ -1,11 +1,11 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/../../../spec_helper'
|
2
2
|
|
3
3
|
module Wrest::Components
|
4
|
-
describe
|
4
|
+
describe Container::AliasAccessors do
|
5
5
|
before :each do
|
6
6
|
@Demon = Class.new
|
7
7
|
@Demon.class_eval do
|
8
|
-
include Wrest::Components::
|
8
|
+
include Wrest::Components::Container
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
@@ -1,12 +1,12 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/../../../spec_helper'
|
2
2
|
|
3
3
|
module Wrest::Components
|
4
|
-
describe
|
4
|
+
describe Container::Typecaster do
|
5
5
|
before :each do
|
6
6
|
@Demon = Class.new
|
7
7
|
@Demon.class_eval do
|
8
|
-
include Wrest::Components::
|
9
|
-
include Wrest::Components::
|
8
|
+
include Wrest::Components::Container
|
9
|
+
include Wrest::Components::Container::Typecaster
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
@@ -25,7 +25,7 @@ module Wrest::Components
|
|
25
25
|
|
26
26
|
it "hash should not typecast" do
|
27
27
|
class TestUser
|
28
|
-
include Wrest::Components::
|
28
|
+
include Wrest::Components::Container
|
29
29
|
end
|
30
30
|
|
31
31
|
@Demon.class_eval{ typecast :user => lambda{|user| TestUser.new(user)}}
|
@@ -58,8 +58,8 @@ module Wrest::Components
|
|
58
58
|
before :each do
|
59
59
|
@Sidhe = Class.new
|
60
60
|
@Sidhe.class_eval do
|
61
|
-
include Wrest::Components::
|
62
|
-
include Wrest::Components::
|
61
|
+
include Wrest::Components::Container
|
62
|
+
include Wrest::Components::Container::Typecaster
|
63
63
|
|
64
64
|
typecast :age => as_integer
|
65
65
|
end
|