wrest 0.0.9-java → 0.1.0-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (154) hide show
  1. data/CHANGELOG +34 -0
  2. data/README.rdoc +16 -10
  3. data/Rakefile +362 -124
  4. data/VERSION.yml +2 -2
  5. data/examples/delicious.rb +17 -7
  6. data/examples/facebook.rb +101 -0
  7. data/examples/keep_alive.rb +37 -0
  8. data/examples/twitter.rb +3 -3
  9. data/examples/twitter_public_timeline.rb +11 -4
  10. data/examples/wow_realm_status.rb +8 -2
  11. data/{spec/functional/sample_rails_app/public/favicon.ico → init.rb} +0 -0
  12. data/lib/wrest/components/{attributes_container → container}/alias_accessors.rb +4 -4
  13. data/lib/wrest/components/{attributes_container → container}/typecaster.rb +1 -1
  14. data/lib/wrest/components/{attributes_container.rb → container.rb} +46 -16
  15. data/lib/wrest/components/mutators.rb +4 -4
  16. data/lib/wrest/components/translators/json.rb +2 -2
  17. data/lib/wrest/components/translators/xml.rb +3 -2
  18. data/lib/wrest/components/translators.rb +3 -3
  19. data/lib/wrest/components.rb +3 -3
  20. data/lib/wrest/core_ext/hash.rb +1 -1
  21. data/lib/wrest/core_ext/string.rb +1 -1
  22. data/lib/wrest/curl/delete.rb +23 -0
  23. data/lib/wrest/curl/get.rb +23 -0
  24. data/lib/wrest/curl/options.rb +16 -0
  25. data/lib/wrest/curl/post.rb +23 -0
  26. data/lib/wrest/curl/put.rb +23 -0
  27. data/lib/wrest/curl/request.rb +95 -0
  28. data/lib/wrest/curl/response.rb +63 -0
  29. data/lib/wrest/curl/session.rb +57 -0
  30. data/lib/wrest/curl.rb +49 -0
  31. data/lib/wrest/exceptions.rb +16 -1
  32. data/lib/wrest/http_shared/headers.rb +350 -0
  33. data/lib/wrest/http_shared/standard_headers.rb +21 -0
  34. data/lib/wrest/http_shared/standard_tokens.rb +18 -0
  35. data/lib/wrest/http_shared.rb +24 -0
  36. data/lib/wrest/native/connection_factory.rb +23 -0
  37. data/lib/wrest/{http → native}/delete.rb +1 -1
  38. data/lib/wrest/{http → native}/get.rb +1 -1
  39. data/lib/wrest/{http → native}/options.rb +1 -1
  40. data/lib/wrest/{http → native}/post.rb +1 -1
  41. data/lib/wrest/{http → native}/put.rb +1 -1
  42. data/lib/wrest/{http → native}/redirection.rb +4 -1
  43. data/lib/wrest/{http → native}/request.rb +32 -20
  44. data/lib/wrest/{http → native}/response.rb +12 -4
  45. data/lib/wrest/native/session.rb +57 -0
  46. data/lib/wrest/native.rb +32 -0
  47. data/lib/wrest/resource/base.rb +1 -1
  48. data/lib/wrest/resource.rb +1 -1
  49. data/lib/wrest/test/request_patches.rb +5 -0
  50. data/lib/wrest/test.rb +1 -0
  51. data/lib/wrest/uri.rb +31 -3
  52. data/lib/wrest/version.rb +2 -2
  53. data/lib/wrest.rb +52 -16
  54. data/spec/unit/spec_helper.rb +12 -3
  55. data/spec/unit/wrest/components/attributes_container/alias_accessors_spec.rb +2 -2
  56. data/spec/unit/wrest/components/attributes_container/typecaster_spec.rb +6 -6
  57. data/spec/unit/wrest/components/attributes_container_spec.rb +44 -12
  58. data/spec/unit/wrest/components/translators/xml_spec.rb +7 -3
  59. data/spec/unit/wrest/curl/request_spec.rb +19 -0
  60. data/spec/unit/wrest/curl/response_spec.rb +16 -0
  61. data/spec/unit/wrest/http/response_spec.rb +17 -38
  62. data/spec/unit/wrest/{http → native}/redirection_spec.rb +5 -5
  63. data/spec/unit/wrest/{http → native}/request_spec.rb +15 -14
  64. data/spec/unit/wrest/native/response_spec.rb +72 -0
  65. data/spec/unit/wrest/native/session_spec.rb +74 -0
  66. data/spec/unit/wrest/resource/base_spec.rb +2 -2
  67. data/spec/unit/wrest/uri_spec.rb +51 -11
  68. data/wrest.gemspec +168 -0
  69. metadata +60 -164
  70. data/lib/wrest/http.rb +0 -25
  71. data/spec/functional/sample_rails_app/README +0 -3
  72. data/spec/functional/sample_rails_app/Rakefile +0 -10
  73. data/spec/functional/sample_rails_app/app/controllers/application_controller.rb +0 -10
  74. data/spec/functional/sample_rails_app/app/controllers/lead_bottles_controller.rb +0 -7
  75. data/spec/functional/sample_rails_app/app/helpers/application_helper.rb +0 -3
  76. data/spec/functional/sample_rails_app/app/models/bottle.rb +0 -3
  77. data/spec/functional/sample_rails_app/app/models/glass_bottle.rb +0 -3
  78. data/spec/functional/sample_rails_app/app/models/lead_bottle.rb +0 -3
  79. data/spec/functional/sample_rails_app/config/boot.rb +0 -110
  80. data/spec/functional/sample_rails_app/config/database.yml +0 -16
  81. data/spec/functional/sample_rails_app/config/environment.rb +0 -42
  82. data/spec/functional/sample_rails_app/config/environments/development.rb +0 -17
  83. data/spec/functional/sample_rails_app/config/environments/production.rb +0 -28
  84. data/spec/functional/sample_rails_app/config/environments/test.rb +0 -28
  85. data/spec/functional/sample_rails_app/config/initializers/backtrace_silencers.rb +0 -7
  86. data/spec/functional/sample_rails_app/config/initializers/inflections.rb +0 -10
  87. data/spec/functional/sample_rails_app/config/initializers/mime_types.rb +0 -5
  88. data/spec/functional/sample_rails_app/config/initializers/new_rails_defaults.rb +0 -19
  89. data/spec/functional/sample_rails_app/config/initializers/session_store.rb +0 -15
  90. data/spec/functional/sample_rails_app/config/locales/en.yml +0 -5
  91. data/spec/functional/sample_rails_app/config/routes.rb +0 -3
  92. data/spec/functional/sample_rails_app/db/development.sqlite3 +0 -0
  93. data/spec/functional/sample_rails_app/db/migrate/20090319115628_create_bottle.rb +0 -13
  94. data/spec/functional/sample_rails_app/db/schema.rb +0 -20
  95. data/spec/functional/sample_rails_app/db/test.sqlite3 +0 -0
  96. data/spec/functional/sample_rails_app/log/development.log +0 -1
  97. data/spec/functional/sample_rails_app/public/404.html +0 -30
  98. data/spec/functional/sample_rails_app/public/422.html +0 -30
  99. data/spec/functional/sample_rails_app/public/500.html +0 -30
  100. data/spec/functional/sample_rails_app/public/images/rails.png +0 -0
  101. data/spec/functional/sample_rails_app/public/index.html +0 -275
  102. data/spec/functional/sample_rails_app/public/robots.txt +0 -5
  103. data/spec/functional/sample_rails_app/script/about +0 -4
  104. data/spec/functional/sample_rails_app/script/autospec +0 -6
  105. data/spec/functional/sample_rails_app/script/console +0 -3
  106. data/spec/functional/sample_rails_app/script/dbconsole +0 -3
  107. data/spec/functional/sample_rails_app/script/destroy +0 -3
  108. data/spec/functional/sample_rails_app/script/generate +0 -3
  109. data/spec/functional/sample_rails_app/script/performance/benchmarker +0 -3
  110. data/spec/functional/sample_rails_app/script/performance/profiler +0 -3
  111. data/spec/functional/sample_rails_app/script/plugin +0 -3
  112. data/spec/functional/sample_rails_app/script/runner +0 -3
  113. data/spec/functional/sample_rails_app/script/server +0 -3
  114. data/spec/functional/sample_rails_app/script/spec +0 -10
  115. data/spec/functional/sample_rails_app/script/spec_server +0 -9
  116. data/spec/functional/sample_rails_app/test/performance/browsing_test.rb +0 -9
  117. data/spec/functional/sample_rails_app/test/test_helper.rb +0 -38
  118. data/spec/functional/sample_rails_app/tmtags +0 -2559
  119. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/MIT-LICENSE +0 -20
  120. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/README.rdoc +0 -100
  121. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/Rakefile +0 -18
  122. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/init.rb +0 -5
  123. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/install.rb +0 -1
  124. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/lib/resource_full/base.rb +0 -140
  125. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/lib/resource_full/controllers/resources.rb +0 -16
  126. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/lib/resource_full/controllers/resources_controller.rb +0 -26
  127. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/lib/resource_full/controllers/routes_controller.rb +0 -16
  128. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/lib/resource_full/core_extensions/api.rb +0 -26
  129. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/lib/resource_full/core_extensions/exception.rb +0 -23
  130. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/lib/resource_full/core_extensions/from_json.rb +0 -15
  131. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/lib/resource_full/dispatch.rb +0 -235
  132. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/lib/resource_full/models/resourced_route.rb +0 -84
  133. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/lib/resource_full/query.rb +0 -337
  134. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/lib/resource_full/render/html.rb +0 -50
  135. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/lib/resource_full/render/json.rb +0 -75
  136. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/lib/resource_full/render/xml.rb +0 -65
  137. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/lib/resource_full/render.rb +0 -63
  138. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/lib/resource_full/retrieve.rb +0 -74
  139. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/lib/resource_full/version.rb +0 -9
  140. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/lib/resource_full.rb +0 -14
  141. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/spec/resource_full/base_spec.rb +0 -88
  142. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/spec/resource_full/controllers/resources_spec.rb +0 -29
  143. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/spec/resource_full/dispatch_spec.rb +0 -262
  144. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/spec/resource_full/models/resourced_route_spec.rb +0 -62
  145. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/spec/resource_full/query/parameter_spec.rb +0 -57
  146. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/spec/resource_full/query_spec.rb +0 -462
  147. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/spec/resource_full/render/html_spec.rb +0 -4
  148. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/spec/resource_full/render/json_spec.rb +0 -107
  149. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/spec/resource_full/render/xml_spec.rb +0 -98
  150. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/spec/resource_full/render_spec.rb +0 -5
  151. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/spec/resource_full/retrieve_spec.rb +0 -173
  152. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/spec/spec_helper.rb +0 -98
  153. data/spec/functional/sample_rails_app/vendor/plugins/resource_full/uninstall.rb +0 -1
  154. 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::Http
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::Http
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::Http
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::Http
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::Http
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 Http #:nodoc:
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::Http
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. Defaults to 60.
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 = (@options[:timeout] ||= 60)
46
+ @timeout = @options[:timeout]
47
+ @connection = @options[:connection]
44
48
  end
45
49
 
46
- # Makes a request and returns a Wrest::Http::Response.
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
- prefix = "#{http_request.method} #{http_request.hash}"
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::Http::Response.new( http_connection.request(@http_request, @body) ) }
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
- end
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 Http #:nodoc:
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
- instance = ((300..399).include?(http_response.code.to_i) ? Wrest::Http::Redirection : self).allocate
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
@@ -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
@@ -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::AttributesContainer
14
+ include Wrest::Components::Container
15
15
 
16
16
  always_has :id
17
17
  typecast :id => as_integer
@@ -15,4 +15,4 @@ module Wrest
15
15
  end
16
16
  end
17
17
 
18
- require "#{WREST_ROOT}/wrest/resource/base"
18
+ require "#{Wrest::Root}/wrest/resource/base"
@@ -0,0 +1,5 @@
1
+ class Wrest::Native::Request
2
+ def invoke
3
+ raise Wrest::Exceptions::RealRequestMadeInTestEnvironmet, 'A real HTTP request was made while running tests. Please avoid using live HTTP connections while testing and replace them with mocks.'
4
+ end
5
+ end
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
@@ -11,8 +11,8 @@ module Wrest
11
11
  module VERSION
12
12
  unless defined? MAJOR
13
13
  MAJOR = 0
14
- MINOR = 0
15
- TINY = 9
14
+ MINOR = 1
15
+ TINY = 0
16
16
 
17
17
  STRING = [MAJOR, MINOR, TINY].join('.')
18
18
 
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.2'
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.warn "LibXML >= 1.1.3 not found, falling back to #{ActiveSupport::XmlMini.backend}. To install LibXML run `sudo gem install ruby-libxml`"
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
- source_dirs = ["/wrest/core_ext/*.rb", "/wrest/*.rb"]
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
- source_dirs.each{|directory|
47
- Dir["#{File.expand_path(File.dirname(__FILE__) + directory)}"].each { |file|
48
- require file
49
- }
50
- }
84
+ # if (ENV['RAILS_ENV'] == 'test' || (Kernel.const_defined?(:RAILS_ENV) && (RAILS_ENV == 'test')))
85
+ # require "#{Wrest::Root}/wrest/test"
86
+ # end
@@ -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("#{WREST_ROOT}/../log/test.log", 'a'))
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 << '<br/>')
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 AttributesContainer::AliasAccessors do
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::AttributesContainer
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 AttributesContainer::Typecaster do
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::AttributesContainer
9
- include Wrest::Components::AttributesContainer::Typecaster
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::AttributesContainer
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::AttributesContainer
62
- include Wrest::Components::AttributesContainer::Typecaster
61
+ include Wrest::Components::Container
62
+ include Wrest::Components::Container::Typecaster
63
63
 
64
64
  typecast :age => as_integer
65
65
  end