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,95 @@
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::Curl
11
+ # This represents a HTTP request. Typically you will never need to instantiate
12
+ # one of these yourself - you can use one of the more conveient APIs via Wrest::Uri
13
+ # or Wrest::Http::Get etc. instead.
14
+ class Request
15
+ attr_reader :http_request, :uri, :body, :headers, :username, :password, :follow_redirects,
16
+ :follow_redirects_limit, :timeout, :connection, :parameters, :auth_type
17
+ # Valid tuples for the options are:
18
+ # :username => String, defaults to nil
19
+ # :password => String, defaults to nil
20
+ # :follow_redirects => Boolean, defaults to true for Get, false for anything else
21
+ # :follow_redirects_limit => Integer, defaults to 5. This is the number of redirects
22
+ # that Wrest will automatically follow before raising an
23
+ # Wrest::Exceptions::AutoRedirectLimitExceeded exception.
24
+ # For example, if you set this to 1, the very first redirect
25
+ # will raise the exception.
26
+ # :timeout => The period, in seconds, after which a Timeout::Error is raised
27
+ # in the event of a connection failing to open. Defaulted to 60 by Uri#create_connection.
28
+ # :connection => The HTTP Connection object to use. This is how a keep-alive connection can be
29
+ # used for multiple requests. Not yet fully implemented for Curl.
30
+ #
31
+ # Curl specific options:
32
+ # :auth_type => This is a curl specific option and can be one of :basic, :digest, or :any. The default is :basic.
33
+ def initialize(wrest_uri, http_verb, parameters = {}, body = nil, headers = {}, options = {})
34
+ @uri = wrest_uri
35
+ @headers = headers.stringify_keys
36
+ @parameters = parameters
37
+ @body = body
38
+
39
+ @options = options.clone
40
+ @auth_type = @options[:auth_type] || :basic
41
+ @username = @options[:username]
42
+ @password = @options[:password]
43
+ @follow_redirects = (@options[:follow_redirects] ||= false)
44
+
45
+ @follow_redirects_limit = (@options[:follow_redirects_limit] ||= 5)
46
+ @timeout = @options[:timeout] || 60
47
+ @connection = @options[:connection]
48
+
49
+ @http_request = Patron::Request.new
50
+ @http_request.action = http_verb
51
+ @http_request.upload_data = body
52
+ @http_request.headers = headers
53
+ @http_request.username = username
54
+ @http_request.password = password
55
+ @http_request.auth_type = auth_type
56
+ @http_request.url = parameters.empty? ? uri.to_s : "#{uri.to_s}?#{parameters.to_query}"
57
+ @http_request.max_redirects = follow_redirects_limit if follow_redirects
58
+ @http_request.timeout = @timeout
59
+ end
60
+
61
+ # Makes a request and returns a Wrest::Http::Response.
62
+ # Data about the request is and logged to Wrest.logger
63
+ # The log entry contains the following information:
64
+ #
65
+ # --> indicates a request
66
+ # <-- indicates a response
67
+ #
68
+ # The type of request is mentioned in caps, followed by a hash
69
+ # uniquely uniquely identifying a particular request/response pair.
70
+ # In a multi-process or multi-threaded scenario, this can be used
71
+ # to identify request-response pairs.
72
+ #
73
+ # The request hash is followed by a connection hash; requests using the
74
+ # same connection (effectively a keep-alive connection) will have the
75
+ # same connection hash.
76
+ #
77
+ # This is followed by the response code, the payload size and the time taken.
78
+ def invoke
79
+ response = nil
80
+
81
+ @connection ||= Patron::Session.new
82
+ raise ArgumentError, "Empty URL" if http_request.url.empty?
83
+
84
+ prefix = "#{http_request.action.to_s.upcase} #{http_request.hash} #{connection.hash}"
85
+
86
+ Wrest.logger.debug "--> (#{prefix}) #{http_request.url}"
87
+ time = Benchmark.realtime { response = Wrest::Curl::Response.new(connection.handle_request(http_request))}
88
+ Wrest.logger.debug "<-- (#{prefix}) %s (%d bytes %.2fs)" % [response.message, response.body ? response.body.length : 0, time]
89
+
90
+ response
91
+ rescue Patron::TimeoutError => e
92
+ raise Wrest::Exceptions::Timeout.new(e)
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,63 @@
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 #:nodoc:
11
+ module Curl #:nodoc:
12
+ # Decorates a response providing support for deserialisation.
13
+ class Response
14
+ attr_reader :http_response
15
+ include HttpShared::Headers
16
+
17
+ extend Forwardable
18
+ def_delegators :@http_response, :body, :headers
19
+
20
+ def initialize(http_response)
21
+ @http_response = http_response
22
+ initialize_http_header
23
+ end
24
+
25
+ def deserialise
26
+ deserialise_using(Wrest::Components::Translators.lookup(content_type))
27
+ end
28
+
29
+ def deserialise_using(translator)
30
+ translator.deserialise(@http_response)
31
+ end
32
+
33
+ def code
34
+ @http_response.status
35
+ end
36
+
37
+ def message
38
+ @http_response.status_line
39
+ end
40
+
41
+ def content_length
42
+ self[H::ContentLength].try(:to_i)
43
+ end
44
+
45
+ def content_type
46
+ self[H::ContentType].split(';').first
47
+ end
48
+
49
+ # A null object implementation - invoking this method on
50
+ # a response simply returns the same response unless
51
+ # the response is a Redirection (code 3xx), in which case a
52
+ # get is invoked on the url stored in the response headers
53
+ # under the key 'location' and the new Response is returned.
54
+ def follow(redirect_request_options = {})
55
+ self
56
+ end
57
+
58
+ def connection_closed?
59
+ self[StandardHeaders::Connection].downcase == StandardTokens::Close.downcase
60
+ end
61
+ end
62
+ end
63
+ 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 = { StandardHeaders::Connection => 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/curl.rb ADDED
@@ -0,0 +1,49 @@
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
+ begin
11
+ gem 'patron', '>=0.4.4'
12
+ rescue Gem::LoadError => e
13
+ Wrest.logger.debug "Patron >= 0.4.4 not found. Patron is necessary to use libcurl. To install Patron run `sudo gem install patron` (patron is not available on JRuby, but you shouldn't need it anyway)."
14
+ raise e
15
+ end
16
+ require 'patron'
17
+
18
+ module Wrest #:nodoc:
19
+
20
+ # Contains all HTTP protocol related classes such as
21
+ # Get, Post, Request, Response etc. and uses Curl for
22
+ # better performance, but works only on CRuby and only on a *nix OS.
23
+ #
24
+ # This functionality is under development and the Wrest API
25
+ # may not cover using it fully.
26
+ #
27
+ # Note:
28
+ # * The Curl based APIs do *not* support the HTTP 'options' verb.
29
+ # * Since auto-redirect is natively supported by Curl, auto-redirect may
30
+ # behave differently from the native implementation for now.
31
+ module Curl
32
+ include Wrest::HttpShared
33
+ end
34
+ end
35
+
36
+ module Patron
37
+ class Session
38
+ public :handle_request
39
+ end
40
+ end
41
+
42
+ require "#{Wrest::Root}/wrest/curl/response"
43
+ require "#{Wrest::Root}/wrest/curl/request"
44
+ require "#{Wrest::Root}/wrest/curl/get"
45
+ require "#{Wrest::Root}/wrest/curl/put"
46
+ require "#{Wrest::Root}/wrest/curl/post"
47
+ require "#{Wrest::Root}/wrest/curl/delete"
48
+ require "#{Wrest::Root}/wrest/curl/options"
49
+ # require "#{Wrest::Root}/wrest/curl/session"
@@ -9,10 +9,25 @@ module Wrest
9
9
  # is requested. See Translators.
10
10
  class UnsupportedContentType < StandardError
11
11
  end
12
-
12
+
13
13
  # Raised when a request auto redirects more times than are allowed
14
14
  # by its follow_redirects_limit. See Wrest::Http::Redirection.
15
15
  class AutoRedirectLimitExceeded < StandardError
16
16
  end
17
+
18
+ # Raised when a request is made when either RAILS_ENV or
19
+ # ENV['RAILS_ENV'] is set to 'test', which is the case when
20
+ # running tests/specs in a Rails application.
21
+ #
22
+ # See wrest/test/request_patches.
23
+ class RealRequestMadeInTestEnvironmet < StandardError
24
+ end
25
+
26
+ # Raised when a request times out
27
+ class Timeout < StandardError
28
+ end
29
+
30
+ class UnsupportedHttpVerb < StandardError
31
+ end
17
32
  end
18
33
  end
@@ -0,0 +1,350 @@
1
+ #
2
+ # Header module.
3
+ #
4
+ # Provides access to headers in the mixed-into class as a hash-like
5
+ # object, except with case-insensitive keys. Also provides
6
+ # methods for accessing commonly-used header values in a more
7
+ # convenient format.
8
+ #
9
+ # Sourced from Net::HTTP and then modified to be generic
10
+ module Wrest
11
+ module HttpShared
12
+ module Headers
13
+
14
+ def initialize_http_header
15
+ headers.each do |key, value|
16
+ headers[key.downcase] = value.strip
17
+ end
18
+ end
19
+
20
+ # Returns the header field corresponding to the case-insensitive key.
21
+ # For example, a key of "Content-Type" might return "text/html"
22
+ def [](key)
23
+ headers[key] || headers[key.downcase]
24
+ end
25
+
26
+ # # Sets the header field corresponding to the case-insensitive key.
27
+ # def []=(key, val)
28
+ # unless val
29
+ # headers.delete key.downcase
30
+ # return val
31
+ # end
32
+ # headers[key.downcase] = [val]
33
+ # end
34
+ #
35
+ # # [Ruby 1.8.3]
36
+ # # Adds header field instead of replace.
37
+ # # Second argument +val+ must be a String.
38
+ # # See also #[]=, #[] and #get_fields.
39
+ # #
40
+ # # request.add_field 'X-My-Header', 'a'
41
+ # # p request['X-My-Header'] #=> "a"
42
+ # # p request.get_fields('X-My-Header') #=> ["a"]
43
+ # # request.add_field 'X-My-Header', 'b'
44
+ # # p request['X-My-Header'] #=> "a, b"
45
+ # # p request.get_fields('X-My-Header') #=> ["a", "b"]
46
+ # # request.add_field 'X-My-Header', 'c'
47
+ # # p request['X-My-Header'] #=> "a, b, c"
48
+ # # p request.get_fields('X-My-Header') #=> ["a", "b", "c"]
49
+ # #
50
+ # def add_field(key, val)
51
+ # if headers.key?(key.downcase)
52
+ # headers[key.downcase].push val
53
+ # else
54
+ # headers[key.downcase] = [val]
55
+ # end
56
+ # end
57
+ #
58
+ # # [Ruby 1.8.3]
59
+ # # Returns an array of header field strings corresponding to the
60
+ # # case-insensitive +key+. This method allows you to get duplicated
61
+ # # header fields without any processing. See also #[].
62
+ # #
63
+ # # p response.get_fields('Set-Cookie')
64
+ # # #=> ["session=al98axx; expires=Fri, 31-Dec-1999 23:58:23",
65
+ # # "query=rubyscript; expires=Fri, 31-Dec-1999 23:58:23"]
66
+ # # p response['Set-Cookie']
67
+ # # #=> "session=al98axx; expires=Fri, 31-Dec-1999 23:58:23, query=rubyscript; expires=Fri, 31-Dec-1999 23:58:23"
68
+ # #
69
+ # def get_fields(key)
70
+ # return nil unless headers[key.downcase]
71
+ # headers[key.downcase].dup
72
+ # end
73
+ #
74
+ # # Returns the header field corresponding to the case-insensitive key.
75
+ # # Returns the default value +args+, or the result of the block, or nil,
76
+ # # if there's no header field named key. See Hash#fetch
77
+ # def fetch(key, *args, &block) #:yield: +key+
78
+ # a = headers.fetch(key.downcase, *args, &block)
79
+ # a.join(', ')
80
+ # end
81
+ #
82
+ # # Iterates for each header names and values.
83
+ # def each_header #:yield: +key+, +value+
84
+ # headers.each do |k,va|
85
+ # yield k, va.join(', ')
86
+ # end
87
+ # end
88
+ #
89
+ # alias each each_header
90
+ #
91
+ # # Iterates for each header names.
92
+ # def each_name(&block) #:yield: +key+
93
+ # headers.each_key(&block)
94
+ # end
95
+ #
96
+ # alias each_key each_name
97
+ #
98
+ # # Iterates for each capitalized header names.
99
+ # def each_capitalized_name(&block) #:yield: +key+
100
+ # headers.each_key do |k|
101
+ # yield capitalize(k)
102
+ # end
103
+ # end
104
+ #
105
+ # # Iterates for each header values.
106
+ # def each_value #:yield: +value+
107
+ # headers.each_value do |va|
108
+ # yield va.join(', ')
109
+ # end
110
+ # end
111
+ #
112
+ # # Removes a header field.
113
+ # def delete(key)
114
+ # headers.delete(key.downcase)
115
+ # end
116
+ #
117
+ # # true if +key+ header exists.
118
+ # def key?(key)
119
+ # headers.key?(key.downcase)
120
+ # end
121
+ #
122
+ # # Returns a Hash consist of header names and values.
123
+ # def to_hash
124
+ # headers.dup
125
+ # end
126
+ #
127
+ # # As for #each_header, except the keys are provided in capitalized form.
128
+ # def each_capitalized
129
+ # headers.each do |k,v|
130
+ # yield capitalize(k), v.join(', ')
131
+ # end
132
+ # end
133
+ #
134
+ # alias canonical_each each_capitalized
135
+ #
136
+ # def capitalize(name)
137
+ # name.split(/-/).map {|s| s.capitalize }.join('-')
138
+ # end
139
+ # private :capitalize
140
+ #
141
+ # # Returns an Array of Range objects which represents Range: header field,
142
+ # # or +nil+ if there is no such header.
143
+ # def range
144
+ # return nil unless headers['range']
145
+ # self['Range'].split(/,/).map {|spec|
146
+ # m = /bytes\s*=\s*(\d+)?\s*-\s*(\d+)?/i.match(spec) or
147
+ # raise HTTPHeaderSyntaxError, "wrong Range: #{spec}"
148
+ # d1 = m[1].to_i
149
+ # d2 = m[2].to_i
150
+ # if m[1] and m[2] then d1..d2
151
+ # elsif m[1] then d1..-1
152
+ # elsif m[2] then -d2..-1
153
+ # else
154
+ # raise HTTPHeaderSyntaxError, 'range is not specified'
155
+ # end
156
+ # }
157
+ # end
158
+ #
159
+ # # Set Range: header from Range (arg r) or beginning index and
160
+ # # length from it (arg idx&len).
161
+ # #
162
+ # # req.range = (0..1023)
163
+ # # req.set_range 0, 1023
164
+ # #
165
+ # def set_range(r, e = nil)
166
+ # unless r
167
+ # headers.delete 'range'
168
+ # return r
169
+ # end
170
+ # r = (r...r+e) if e
171
+ # case r
172
+ # when Numeric
173
+ # n = r.to_i
174
+ # rangestr = (n > 0 ? "0-#{n-1}" : "-#{-n}")
175
+ # when Range
176
+ # first = r.first
177
+ # last = r.last
178
+ # last -= 1 if r.exclude_end?
179
+ # if last == -1
180
+ # rangestr = (first > 0 ? "#{first}-" : "-#{-first}")
181
+ # else
182
+ # raise HTTPHeaderSyntaxError, 'range.first is negative' if first < 0
183
+ # raise HTTPHeaderSyntaxError, 'range.last is negative' if last < 0
184
+ # raise HTTPHeaderSyntaxError, 'must be .first < .last' if first > last
185
+ # rangestr = "#{first}-#{last}"
186
+ # end
187
+ # else
188
+ # raise TypeError, 'Range/Integer is required'
189
+ # end
190
+ # headers['range'] = ["bytes=#{rangestr}"]
191
+ # r
192
+ # end
193
+ #
194
+ # alias range= set_range
195
+ #
196
+ # # Returns an Integer object which represents the Content-Length: header field
197
+ # # or +nil+ if that field is not provided.
198
+ # def content_length
199
+ # return nil unless key?('Content-Length')
200
+ # len = self['Content-Length'].slice(/\d+/) or
201
+ # raise HTTPHeaderSyntaxError, 'wrong Content-Length format'
202
+ # len.to_i
203
+ # end
204
+ #
205
+ # def content_length=(len)
206
+ # unless len
207
+ # headers.delete 'content-length'
208
+ # return nil
209
+ # end
210
+ # headers['content-length'] = [len.to_i.to_s]
211
+ # end
212
+ #
213
+ # # Returns "true" if the "transfer-encoding" header is present and
214
+ # # set to "chunked". This is an HTTP/1.1 feature, allowing the
215
+ # # the content to be sent in "chunks" without at the outset
216
+ # # stating the entire content length.
217
+ # def chunked?
218
+ # return false unless headers['transfer-encoding']
219
+ # field = self['Transfer-Encoding']
220
+ # (/(?:\A|[^\-\w])chunked(?![\-\w])/i =~ field) ? true : false
221
+ # end
222
+ #
223
+ # # Returns a Range object which represents Content-Range: header field.
224
+ # # This indicates, for a partial entity body, where this fragment
225
+ # # fits inside the full entity body, as range of byte offsets.
226
+ # def content_range
227
+ # return nil unless headers['content-range']
228
+ # m = %r<bytes\s+(\d+)-(\d+)/(\d+|\*)>i.match(self['Content-Range']) or
229
+ # raise HTTPHeaderSyntaxError, 'wrong Content-Range format'
230
+ # m[1].to_i .. m[2].to_i + 1
231
+ # end
232
+ #
233
+ # # The length of the range represented in Content-Range: header.
234
+ # def range_length
235
+ # r = content_range() or return nil
236
+ # r.end - r.begin
237
+ # end
238
+ #
239
+ # # Returns a content type string such as "text/html".
240
+ # # This method returns nil if Content-Type: header field does not exist.
241
+ # def content_type
242
+ # return nil unless main_type()
243
+ # if sub_type()
244
+ # "#{main_type()}/#{sub_type()}"
245
+ # else
246
+ # main_type()
247
+ # end
248
+ # end
249
+ #
250
+ # # Returns a content type string such as "text".
251
+ # # This method returns nil if Content-Type: header field does not exist.
252
+ # def main_type
253
+ # return nil unless headers['content-type']
254
+ # self['Content-Type'].split(';').first.to_s.split('/')[0].to_s.strip
255
+ # end
256
+ #
257
+ # # Returns a content type string such as "html".
258
+ # # This method returns nil if Content-Type: header field does not exist
259
+ # # or sub-type is not given (e.g. "Content-Type: text").
260
+ # def sub_type
261
+ # return nil unless headers['content-type']
262
+ # main, sub = *self['Content-Type'].split(';').first.to_s.split('/')
263
+ # return nil unless sub
264
+ # sub.strip
265
+ # end
266
+ #
267
+ # # Returns content type parameters as a Hash as like
268
+ # # {"charset" => "iso-2022-jp"}.
269
+ # def type_params
270
+ # result = {}
271
+ # list = self['Content-Type'].to_s.split(';')
272
+ # list.shift
273
+ # list.each do |param|
274
+ # k, v = *param.split('=', 2)
275
+ # result[k.strip] = v.strip
276
+ # end
277
+ # result
278
+ # end
279
+ #
280
+ # # Set Content-Type: header field by +type+ and +params+.
281
+ # # +type+ must be a String, +params+ must be a Hash.
282
+ # def set_content_type(type, params = {})
283
+ # headers['content-type'] = [type + params.map{|k,v|"; #{k}=#{v}"}.join('')]
284
+ # end
285
+ #
286
+ # alias content_type= set_content_type
287
+ #
288
+ # # Set header fields and a body from HTML form data.
289
+ # # +params+ should be a Hash containing HTML form data.
290
+ # # Optional argument +sep+ means data record separator.
291
+ # #
292
+ # # This method also set Content-Type: header field to
293
+ # # application/x-www-form-urlencoded.
294
+ # #
295
+ # # Example:
296
+ # # http.form_data = {"q" => "ruby", "lang" => "en"}
297
+ # # http.form_data = {"q" => ["ruby", "perl"], "lang" => "en"}
298
+ # # http.set_form_data({"q" => "ruby", "lang" => "en"}, ';')
299
+ # #
300
+ # def set_form_data(params, sep = '&')
301
+ # self.body = params.map {|k, v| encode_kvpair(k, v) }.flatten.join(sep)
302
+ # self.content_type = 'application/x-www-form-urlencoded'
303
+ # end
304
+ #
305
+ # alias form_data= set_form_data
306
+ #
307
+ # def encode_kvpair(k, vs)
308
+ # Array(vs).map {|v| "#{urlencode(k)}=#{urlencode(v.to_s)}" }
309
+ # end
310
+ # private :encode_kvpair
311
+ #
312
+ # def urlencode(str)
313
+ # str.dup.force_encoding('ASCII-8BIT').gsub(/[^a-zA-Z0-9_\.\-]/){'%%%02x' % $&.ord}
314
+ # end
315
+ # private :urlencode
316
+ #
317
+ # # Set the Authorization: header for "Basic" authorization.
318
+ # def basic_auth(account, password)
319
+ # headers['authorization'] = [basic_encode(account, password)]
320
+ # end
321
+ #
322
+ # # Set Proxy-Authorization: header for "Basic" authorization.
323
+ # def proxy_basic_auth(account, password)
324
+ # headers['proxy-authorization'] = [basic_encode(account, password)]
325
+ # end
326
+ #
327
+ # def basic_encode(account, password)
328
+ # 'Basic ' + ["#{account}:#{password}"].pack('m').delete("\r\n")
329
+ # end
330
+ # private :basic_encode
331
+ #
332
+ # def connection_close?
333
+ # tokens(headers['connection']).include?('close') or
334
+ # tokens(headers['proxy-connection']).include?('close')
335
+ # end
336
+ #
337
+ # def connection_keep_alive?
338
+ # tokens(headers['connection']).include?('keep-alive') or
339
+ # tokens(headers['proxy-connection']).include?('keep-alive')
340
+ # end
341
+ #
342
+ # def tokens(vals)
343
+ # return [] unless vals
344
+ # vals.map {|v| v.split(',') }.flatten\
345
+ # .reject {|str| str.strip.empty? }\
346
+ # .map {|tok| tok.strip.downcase }
347
+ # end
348
+ end
349
+ end
350
+ end
@@ -0,0 +1,21 @@
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 #:nodoc:
11
+ module HttpShared #:nodoc:
12
+ module StandardHeaders
13
+ Connection = 'connection'
14
+ ContentType = 'content-type'
15
+ ContentLength = 'content-length'
16
+ IfNoneMatch = 'if-none-match'
17
+ end
18
+ end
19
+ end
20
+
21
+
@@ -0,0 +1,18 @@
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 #:nodoc:
11
+ module HttpShared #:nodoc:
12
+ module StandardTokens
13
+ Close = 'close'
14
+ KeepAlive = 'keep-alive'
15
+ FormEncoded = 'application/x-www-form-urlencoded'
16
+ end
17
+ end
18
+ end