rufus-verbs 0.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.txt ADDED
@@ -0,0 +1,248 @@
1
+
2
+ = 'rufus-verbs'
3
+
4
+ == what is it ?
5
+
6
+ 'rufus-verbs' is an extended HTTP client library. It provides the four main HTTP "verbs" as Ruby methods : get, put, post and delete.
7
+
8
+ It wraps a certain number of techniques that make it a decent tool for manipulating web resources.
9
+
10
+
11
+ == features
12
+
13
+ currently :
14
+
15
+ * follows redirections
16
+ * automatically adds _method={post|put} in the request parameters with the option :fake_put => true
17
+ * HTTPS aware ('verify none' by default)
18
+ * HTTP basic authentication
19
+ * doesn't propagate auth credentials in case of redirection to different host
20
+ * advertises and uses gzip compression
21
+ * proxy-aware (HTTP_PROXY env var or :proxy option)
22
+ * conditional GET (via ConditionalEndPoint class)
23
+ * request body built via a block (post and put)
24
+
25
+ maybe later :
26
+
27
+ * retry on failure
28
+ * greediness (automatic parsing for content like JSON or YAML)
29
+ * http digest authentication
30
+ * cache awareness
31
+ * head, options
32
+
33
+
34
+ == getting it
35
+
36
+ sudo gem install -y rufus-verbs
37
+
38
+ or download[http://rubyforge.org/frs/?group_id=4812] it from RubyForge.
39
+
40
+
41
+ == usage
42
+
43
+ The arguments to the "verbs" follow the schema <tt>method_name(uri, opts)</tt> or <tt>method_name(opts)</tt>. Post and put accept an optional block parameter.
44
+
45
+ require 'rubygems'
46
+ require 'rufus/verbs'
47
+
48
+ include Rufus::Verbs
49
+
50
+ using get(), post(), put() and delete() directly
51
+
52
+ res = get "http://en.wikipedia.org/wiki/Ruby"
53
+ puts res.body
54
+
55
+ res = get :uri => "http://en.wikipedia.org/wiki/Ruby"
56
+ puts res.body
57
+
58
+ post "http://resta.farian.server:7080/inventory/tools/0", :d => "hammer"
59
+ # passing the data via the :d (or :data) option
60
+
61
+ res = post "http://resta.farian.server:7080/inventory/tools/1" do
62
+ "sliver bullet"
63
+ end
64
+ # the data is generated by a block
65
+
66
+ puts res.code.to_i
67
+ # 201... resource created, note that by default,
68
+ # an instance of Net::HTTPResponse is returned
69
+
70
+ puts get("http://resta.farian.server:7080/inventory/tools/0", :body => true)
71
+ # "sliver bullet" (directly returning the content of the response)
72
+
73
+ # oops, typo
74
+
75
+ put "http://resta.farian.server:7080/inventory/tools/1" do
76
+ "silver bullet"
77
+ end
78
+
79
+ put "http://resta.farian.server:7080/inventory/tools/1" do |request|
80
+ request['Content-Type'] = "text/plain"
81
+ "no silver bullet"
82
+ end
83
+ # the block accepts a 'request' (Net::HTTPREquest) argument
84
+
85
+ delete "http://resta.farian.server:7080/inventory/tools/0"
86
+ # I don't need that hammer anymore
87
+
88
+
89
+ Using get() and co via an EndPoint to share common options for a set of requests
90
+
91
+ ep = EndPoint.new :host => "resta.farian.host", :port => 7080, :resource => "inventory/tools"
92
+
93
+ res = ep.get :id => 1
94
+ # still a silver bullet ?
95
+
96
+ res = ep.get :id => 0
97
+ # where did the hammer go ?
98
+
99
+
100
+ A ConditionalEndPoint is an EndPoint that will use conditional GETs whenever possible
101
+
102
+ ep = ConditionalEndPoint.new :host => "resta.farian.zion", :port => 7080, :resource => "inventory/tools"
103
+
104
+ res = ep.get :id => 1
105
+ # first call will retrieve the representation completely
106
+
107
+ res = ep.get :id => 1
108
+ # the server (provided that it supports conditional GET) only
109
+ # returned a 304 answer, the response is returned from the
110
+ # ConditionalEndPoint cache
111
+
112
+ More about conditional GETs at http://ruturajv.wordpress.com/2005/12/27/conditional-get-request/
113
+
114
+ The tests may provide good intel as on 'rufus-verbs' usage as well : http://rufus.rubyforge.org/svn/trunk/verbs/test/
115
+
116
+
117
+ == the options
118
+
119
+ A list of options supported by rufus-verbs, in alphabetical order.
120
+
121
+ Most of the options are, well, optional, see the usage for some clarifications about the preseance of the options among them (trying to do it in the 'least surprise' spirit).
122
+
123
+ R means that the option can be used at request level only, RE means Request or EndPoint level.
124
+
125
+
126
+ * <b>:auth</b> (proc, RE)
127
+ this option takes a Ruby proc, it can be used for custom authentication schemes
128
+
129
+ get "http://resource:7777/items/1", :auth => lambda do |request|
130
+ request['X-Secret-Auth-Header'] = "let me in, it's OK"
131
+ end
132
+
133
+ see :http_basic_authentication for the basic HTTP authentication mechanism
134
+
135
+ * <b>:base</b> (string, RE)
136
+ the base of a resource path
137
+
138
+ :base / :resource / :id -->
139
+ "inventory" / "tools" / "7" -->
140
+ "/inventory/tools/7"
141
+
142
+ * <b>:body</b> (boolean, RE)
143
+ by default, a request returns a Net::HTTPResponse instance, with :body => true, the request will return the body of response directly
144
+
145
+ * <b>:cache_size</b> (integer, ConditionalEndPoint only)
146
+ by default, a ConditionalEndPoint will cache 147 results (and it'll start discarded the least recently used cached responses). This option is used to set this cache's size.
147
+
148
+ * <b>:d</b> (string, R)
149
+ the short variant of :data
150
+
151
+ * <b>:data</b> (string, R)
152
+ the data (request body) for a put or a post.
153
+
154
+ * <b>:dry_run</b> (boolean, RE)
155
+ when <tt>:dry_run => true</tt>, the request will be prepared but not executed and will be returned instead of the HTTP response (used for testing)
156
+
157
+ * <b>:fake_put</b> (boolean, RE)
158
+ when set to true, PUT and DELETE requests will be faked as POST requests where the _method query parameter is set to 'put' or 'delete' respectively
159
+
160
+ * <b>:fd</b>
161
+ the short version of :form_data
162
+
163
+ * <b>:form_data</b>
164
+ this option expects a hash. The (post or put) request body will then be built with this hash.
165
+
166
+ * <b>:hba</b> (pair, RE)
167
+ short for :http_basic_authentication
168
+
169
+ * <b>:host</b> (string, RE)
170
+ the host or IP address for the request
171
+
172
+ * <b>:http_basic_authentication</b> (pair, RE)
173
+ will activate HTTP basic authentication, takes a pair (array) argument [ user, pass ]
174
+
175
+ * <b>:id</b> (string, R)
176
+ the id part of a full resource path (see :base)
177
+
178
+ * <b>:max_redirections</b> (integer, RE)
179
+ by default, rufus-verbs will follow any number of redirections. A limit can be set via this option
180
+
181
+ * <b>:nozip</b> (boolean, RE)
182
+ if set to true will prevent gzip encoding (advertising) when GETting content
183
+
184
+ * <b>:path</b> (string, RE)
185
+ the path (between port and the query string)
186
+
187
+ * <b>:port</b> (string, RE)
188
+ the port for the request
189
+
190
+ * <b>:proxy</b> (uri, string or false, RE)
191
+ by default, rufus-verbs will try to use the proxy given in the HTTP_PROXY environment variable (URI). If this :proxy option is set to false, no proxy will be used. It can take the value of a URI (String or URI instance) as well.
192
+
193
+ * <b>:query</b> (hash or string, R)
194
+ a hash of parameters that will get appended to the URI of the request. A string like "a=b?x=y" can be given as well
195
+
196
+ * <b>:raw_response</b> (boolean, RE)
197
+ the request will be executed and the HTTP response will be returned immediately, no redirection following, content decompression or eventual caching (conditional GET) will take place
198
+
199
+ * <b>:res</b> (string, RE)
200
+ a short version of :resource
201
+
202
+ * <b>:resource</b>
203
+ the resource (or the middle) of a full resource path (see :base)
204
+
205
+ * <b>:scheme</b> (string, R)
206
+ 'http' or 'https'
207
+
208
+ * <b>:u</b> (uri, string, RE)
209
+ the short version of :uri
210
+
211
+ * <b>:uri</b> (uri, string, RE)
212
+ the URI for the request (or the endpoint)
213
+
214
+ * <b>:user_agent</b> (string, RE)
215
+ for setting a custom 'User-Agent' HTTP header
216
+
217
+
218
+ == dependencies
219
+
220
+ the gem rufus-lru[http://rufus.rubyforge.org/rufus-lru]
221
+
222
+
223
+ == mailing list
224
+
225
+ On the OpenWFEru-user list[http://groups.google.com/group/openwferu-users] for now :
226
+
227
+ http://groups.google.com/group/openwferu-users
228
+
229
+ == issue tracker
230
+
231
+ http://rubyforge.org/tracker/?atid=18584&group_id=4812&func=browse
232
+
233
+
234
+ == source
235
+
236
+ svn checkout http://rufus.rubyforge.org/svn/trunk/verbs
237
+
238
+
239
+ == author
240
+
241
+ John Mettraux, jmettraux@gmail.com,
242
+ http://jmettraux.wordpress.com
243
+
244
+
245
+ == license
246
+
247
+ MIT
248
+
@@ -0,0 +1,74 @@
1
+ #
2
+ #--
3
+ # Copyright (c) 2008, John Mettraux, jmettraux@gmail.com
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ # THE SOFTWARE.
22
+ #
23
+ # (MIT license)
24
+ #++
25
+ #
26
+
27
+ #
28
+ # John Mettraux
29
+ #
30
+ # Made in Japan
31
+ #
32
+ # 2008/01/11
33
+ #
34
+
35
+ require 'rufus/verbs/endpoint'
36
+ require 'rufus/verbs/conditional'
37
+
38
+
39
+ module Rufus::Verbs
40
+
41
+
42
+ #
43
+ # GET
44
+ #
45
+ def get (*args)
46
+
47
+ EndPoint.request :get, args
48
+ end
49
+
50
+ #
51
+ # POST
52
+ #
53
+ def post (*args, &block)
54
+
55
+ EndPoint.request :post, args, &block
56
+ end
57
+
58
+ #
59
+ # PUT
60
+ #
61
+ def put (*args, &block)
62
+
63
+ EndPoint.request :put, args, &block
64
+ end
65
+
66
+ #
67
+ # DELETE
68
+ #
69
+ def delete (*args)
70
+
71
+ EndPoint.request :delete, args
72
+ end
73
+ end
74
+
@@ -0,0 +1,142 @@
1
+ #
2
+ #--
3
+ # Copyright (c) 2008, John Mettraux, jmettraux@gmail.com
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ # THE SOFTWARE.
22
+ #
23
+ # (MIT license)
24
+ #++
25
+ #
26
+
27
+ #
28
+ # John Mettraux
29
+ #
30
+ # Made in Japan
31
+ #
32
+ # 2008/01/16
33
+ #
34
+
35
+ module Rufus::Verbs
36
+
37
+ #
38
+ # An EndPoint with a cache for conditional GETs.
39
+ #
40
+ # ep = ConditionalEndPoint.new(
41
+ # :host => "restful.server",
42
+ # :port => 7080,
43
+ # :resource => "inventory/tools")
44
+ #
45
+ # res = ep.get :id => 1
46
+ # # first call will retrieve the representation completely
47
+ #
48
+ # res = ep.get :id => 1
49
+ # # the server (provided that it supports conditional GET) only
50
+ # # returned a 304 answer, the response is returned from the
51
+ # # ConditionalEndPoint cache
52
+ #
53
+ # The :cache_size option allows to set the size of the conditional GET
54
+ # cache. The default size is currently 147.
55
+ #
56
+ class ConditionalEndPoint < EndPoint
57
+
58
+ def initialize (opts)
59
+
60
+ super
61
+
62
+ cs = opts[:cache_size] || 147
63
+
64
+ require 'rubygems'
65
+ begin
66
+ require 'rufus/lru'
67
+ rescue LoadError
68
+ raise "gem 'rufus-lru' is missing, please install it."
69
+ end
70
+
71
+ @cache = LruHash.new cs
72
+ end
73
+
74
+ #
75
+ # Returns the count of representation 'cached' here for the
76
+ # purpose of conditional GET requests.
77
+ #
78
+ def cache_current_size
79
+
80
+ @cache.size
81
+ end
82
+
83
+ #
84
+ # Returns the max size of the conditional GET cache.
85
+ #
86
+ def cache_size
87
+
88
+ @cache.maxsize
89
+ end
90
+
91
+ private
92
+
93
+ #
94
+ # If the representation has already been gotten, send
95
+ # potential If-Modified-Since and/or If-None-Match.
96
+ #
97
+ def add_conditional_headers (req, opts)
98
+
99
+ # if path is cached send since and/or match
100
+
101
+ e = @cache[opts[:c_uri]]
102
+
103
+ return unless e # not cached
104
+
105
+ req['If-Modified-Since'] = e.lastmod if e.lastmod
106
+ req['If-None-Match'] = e.etag if e.etag
107
+
108
+ opts[:c_cached] = e
109
+ end
110
+
111
+ def handle_response (method, res, opts)
112
+
113
+ # if method is get and reply is 200, cache (if et and/or lm)
114
+ # if method is get and reply is 304, return from cache
115
+
116
+ super
117
+
118
+ code = res.code.to_i
119
+
120
+ return opts[:c_cached] if code == 304
121
+
122
+ cache(res, opts) if code == 200
123
+
124
+ res
125
+ end
126
+
127
+ def cache (res, opts)
128
+
129
+ class << res
130
+ def lastmod
131
+ self['Last-Modified']
132
+ end
133
+ def etag
134
+ self['Etag']
135
+ end
136
+ end
137
+
138
+ @cache[opts[:c_uri]] = res
139
+ end
140
+ end
141
+ end
142
+