restfully 0.7.1.rc5 → 0.7.1.rc6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +1 -2
- data/README.md +52 -113
- data/lib/restfully/resource.rb +34 -20
- data/lib/restfully/session.rb +37 -4
- data/lib/restfully/version.rb +1 -1
- data/spec/restfully/session_spec.rb +40 -24
- metadata +4 -4
data/LICENSE
CHANGED
@@ -1,5 +1,4 @@
|
|
1
|
-
Copyright (c) 2009 Cyril Rohr
|
2
|
-
Copyright (c) 2009 INRIA Rennes - Bretagne Atlantique
|
1
|
+
Copyright (c) 2009-2011 Cyril Rohr, INRIA Rennes - Bretagne Atlantique
|
3
2
|
|
4
3
|
Permission is hereby granted, free of charge, to any person obtaining
|
5
4
|
a copy of this software and associated documentation files (the
|
data/README.md
CHANGED
@@ -1,134 +1,78 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
|
4
|
-
It
|
5
|
-
|
6
|
-
1.
|
7
|
-
2.
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
]
|
19
|
-
}
|
20
|
-
|
21
|
-
* Adding a <tt>parent</tt> link automatically creates a <tt>#parent</tt> method on the current resource.
|
22
|
-
* Adding a <tt>collection</tt> link automatically creates a <tt>#my_collection</tt> method that will fetch the Collection when called.
|
23
|
-
* Adding a <tt>member</tt> link automatically creates a <tt>#member_title</tt> method that will fetch the Resource when called.
|
24
|
-
|
25
|
-
5. Advertise allowed HTTP methods in the response to GET requests by returning a <tt>Allow</tt> HTTP header containing a comma-separated list of the HTTP methods that can be used on the resource. This will allow the automatic generation of methods to interact with the resource. e.g.: advertising a <tt>POST</tt> method (<tt>Allow: GET, POST</tt>) will result in the creation of a <tt>submit</tt> method on the resource.
|
1
|
+
# Restfully
|
2
|
+
Restfully is a general-purpose client library for RESTful APIs. It is written in Ruby. Its goal is to abstract the nitty-gritty details of exchanging HTTP requests between the user-agent and the server. It also discovers resources at runtime, which means should the API change and add a new functionality, the client will automatically discover it.
|
3
|
+
|
4
|
+
It works on simple concepts:
|
5
|
+
|
6
|
+
1. All APIs are made of **resources**, and **collections of resources**.
|
7
|
+
2. The **media-type** of a resource dictates the relationships between that resource and the other resources, and what it is possible to do with them.
|
8
|
+
|
9
|
+
Therefore, Restfully can work with any reasonably RESTful API provided that:
|
10
|
+
|
11
|
+
* The API returns semantically correct HTTP status codes;
|
12
|
+
* The API make use of `GET`, `POST`, `PUT`, `DELETE` HTTP methods;
|
13
|
+
* The API returns a valid `Content-Type` header in all responses;
|
14
|
+
* The API returns a `Location` HTTP header on 201 and 202 responses;
|
15
|
+
* The API returns links to other resources in all responses (the so-called HATEOAS constraint of REST).
|
16
|
+
|
17
|
+
If one of the API `Content-Type` is not already supported by one of the `Restfully::MediaType` objects (see `lib/restfully/media_type`), then you just have to build it and register it with Restfully.
|
26
18
|
|
27
19
|
## Installation
|
28
20
|
|
29
21
|
$ gem install restfully
|
30
22
|
|
23
|
+
If you require media-types that need an XML parser, you must also install the `libxml-ruby` library:
|
24
|
+
|
25
|
+
$ gem install libxml-ruby
|
26
|
+
|
31
27
|
## Usage
|
32
28
|
|
33
29
|
### Command line
|
34
30
|
|
35
31
|
$ export RUBYOPT="-rubygems"
|
36
|
-
$ restfully
|
32
|
+
$ restfully URI [-u username] [-p password]
|
37
33
|
|
38
|
-
e.g., for the
|
34
|
+
e.g., for the [Grid'5000 API](https://www.grid5000.fr/mediawiki/index.php/API):
|
39
35
|
|
40
36
|
$ restfully https://api.grid5000.fr/sid/grid5000 -u username -p password
|
41
37
|
|
42
38
|
If the connection was successful, you should get a prompt. You may enter:
|
43
39
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
#<Restfully::Resource:0x91f08c
|
49
|
-
@uri=#<URI::HTTP:0x123e30c URL:http://api.local/sid/grid5000>
|
50
|
-
LINKS
|
51
|
-
@environments=#<Restfully::Collection:0x917666>,
|
52
|
-
@sites=#<Restfully::Collection:0x9170d0>,
|
53
|
-
@version=#<Restfully::Resource:0x91852a>,
|
54
|
-
@versions=#<Restfully::Collection:0x917e68>
|
40
|
+
ruby-1.8.7-p249 > pp root
|
41
|
+
#<Resource:0x8108399c uri=https://api.grid5000.fr/sid/grid5000
|
42
|
+
RELATIONSHIPS
|
43
|
+
environments, self, sites, version, versions
|
55
44
|
PROPERTIES
|
56
|
-
"uid"=>"grid5000"
|
57
|
-
"type"=>"grid"
|
58
|
-
"version"=>"
|
45
|
+
"uid"=>"grid5000"
|
46
|
+
"type"=>"grid"
|
47
|
+
"version"=>"da6abdd13e2e626f64502a648b784372eac790b1">
|
48
|
+
=> nil
|
59
49
|
|
60
|
-
|
50
|
+
And then follow the links advertised under the `RELATIONSHIPS` header to discover the other API resources. For instance, the `sites` resource can be accessed as follows:
|
61
51
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
and get back:
|
67
|
-
|
68
|
-
#<Restfully::Collection:0x9170d0
|
69
|
-
@uri=#<URI::HTTP:0x122e128 URL:http://api.local/sid/grid5000/sites>
|
70
|
-
LINKS
|
71
|
-
@version=#<Restfully::Resource:0x8f553e>,
|
72
|
-
@versions=#<Restfully::Collection:0x8f52be>
|
73
|
-
PROPERTIES
|
74
|
-
"total"=>9,
|
75
|
-
"version"=>"4fe96b25d2cbfee16abe5a4fb999c82dbafc2ee8",
|
76
|
-
"offset"=>0
|
52
|
+
ruby-1.8.7-p249 > pp root.sites
|
53
|
+
#<Collection:0x8106d55c uri=https://api.grid5000.fr/sid/grid5000/sites
|
54
|
+
RELATIONSHIPS
|
55
|
+
self, version, versions
|
77
56
|
ITEMS (0..9)/9
|
78
|
-
#<
|
79
|
-
#<
|
80
|
-
#<
|
81
|
-
#<
|
82
|
-
#<
|
83
|
-
#<
|
84
|
-
#<
|
85
|
-
#<
|
86
|
-
#<
|
87
|
-
|
88
|
-
A Restfully::Collection is a special kind of Resource, which includes the Enumerable module, which means you can call all of its methods on the `Restfully::Collection` object.
|
89
|
-
For example:
|
90
|
-
|
91
|
-
irb(main):003:0> pp root.sites.find{|s| s['uid'] == 'rennes'}
|
92
|
-
#<Restfully::Resource:0x8fa782
|
93
|
-
@uri=#<URI::HTTP:0x11f4e64 URL:http://api.local/sid/grid5000/sites/rennes>
|
94
|
-
LINKS
|
95
|
-
@environments=#<Restfully::Collection:0x8f9ab2>,
|
96
|
-
@parent=#<Restfully::Resource:0x8f981e>,
|
97
|
-
@deployments=#<Restfully::Collection:0x8f935a>,
|
98
|
-
@clusters=#<Restfully::Collection:0x8f9d46>,
|
99
|
-
@version=#<Restfully::Resource:0x8fa354>,
|
100
|
-
@versions=#<Restfully::Collection:0x8fa0b6>,
|
101
|
-
@status=#<Restfully::Collection:0x8f95ee>
|
102
|
-
PROPERTIES
|
103
|
-
"name"=>"Rennes",
|
104
|
-
"latitude"=>48.1,
|
105
|
-
"location"=>"Rennes, France",
|
106
|
-
"security_contact"=>"rennes-staff@lists.grid5000.fr",
|
107
|
-
"uid"=>"rennes",
|
108
|
-
"type"=>"site",
|
109
|
-
"user_support_contact"=>"rennes-staff@lists.grid5000.fr",
|
110
|
-
"version"=>"4fe96b25d2cbfee16abe5a4fb999c82dbafc2ee8",
|
111
|
-
"description"=>"",
|
112
|
-
"longitude"=>-1.6667,
|
113
|
-
"compilation_server"=>false,
|
114
|
-
"email_contact"=>"rennes-staff@lists.grid5000.fr",
|
115
|
-
"web"=>"http://www.irisa.fr",
|
116
|
-
"sys_admin_contact"=>"rennes-staff@lists.grid5000.fr">
|
57
|
+
#<Resource:0x81055a9c uri=https://api.grid5000.fr/sid/grid5000/sites/bordeaux>
|
58
|
+
#<Resource:0x81040d54 uri=https://api.grid5000.fr/sid/grid5000/sites/grenoble>
|
59
|
+
#<Resource:0x8102c070 uri=https://api.grid5000.fr/sid/grid5000/sites/lille>
|
60
|
+
#<Resource:0x8101738c uri=https://api.grid5000.fr/sid/grid5000/sites/lyon>
|
61
|
+
#<Resource:0x81002658 uri=https://api.grid5000.fr/sid/grid5000/sites/nancy>
|
62
|
+
#<Resource:0x80fed924 uri=https://api.grid5000.fr/sid/grid5000/sites/orsay>
|
63
|
+
#<Resource:0x80fd8bb4 uri=https://api.grid5000.fr/sid/grid5000/sites/rennes>
|
64
|
+
#<Resource:0x80fc3dcc uri=https://api.grid5000.fr/sid/grid5000/sites/sophia>
|
65
|
+
#<Resource:0x80faf070 uri=https://api.grid5000.fr/sid/grid5000/sites/toulouse>>
|
66
|
+
=> nil
|
117
67
|
|
118
|
-
|
68
|
+
Note that we're using `pp` to pretty-print the output, but it's not required.
|
119
69
|
|
120
|
-
|
121
|
-
=> ["grenoble", "rennes"]
|
70
|
+
A Collection is a specific kind of Resource, and it has access to all the methods provided by the Ruby [Enumerable](http://www.rubydoc.info/stdlib/core/1.9.2/Enumerable) module.
|
122
71
|
|
123
|
-
|
124
|
-
|
125
|
-
irb(main):007:0> root.sites[:rennes]
|
126
|
-
# will find the item whose uid is "rennes"
|
127
|
-
|
128
|
-
For ease of use and better security, you may prefer to use a configuration file to avoid re-entering the options every time you use the client:
|
72
|
+
For ease of use and better security, you may prefer to use a configuration file to avoid re-entering the Restfully options every time:
|
129
73
|
|
130
74
|
$ echo '
|
131
|
-
|
75
|
+
uri: https://api.grid5000.fr/sid/grid5000
|
132
76
|
username: MYLOGIN
|
133
77
|
password: MYPASSWORD
|
134
78
|
' > ~/.restfully/api.grid5000.fr.yml && chmod 600 ~/.restfully/api.grid5000.fr.yml
|
@@ -140,12 +84,6 @@ And then:
|
|
140
84
|
### As a library
|
141
85
|
See the `examples` directory for examples.
|
142
86
|
|
143
|
-
## Discovering the API capabilities
|
144
|
-
A `Restfully::Resource` (and by extension its child `Restfully::Collection`) has the following methods available for introspection:
|
145
|
-
|
146
|
-
* `links` will return a hash whose keys are the name of the methods that can be called to navigate between resources;
|
147
|
-
* `http_methods` will return an array containing the list of the HTTP methods that are allowed on the resource;
|
148
|
-
|
149
87
|
## Development
|
150
88
|
|
151
89
|
### Testing
|
@@ -163,4 +101,5 @@ A `Restfully::Resource` (and by extension its child `Restfully::Collection`) has
|
|
163
101
|
|
164
102
|
## Copyright
|
165
103
|
|
166
|
-
Copyright (c) 2009 Cyril Rohr, INRIA Rennes - Bretagne Atlantique.
|
104
|
+
Copyright (c) 2009-2011 [Cyril Rohr](http://crohr.me), INRIA Rennes - Bretagne Atlantique.
|
105
|
+
See LICENSE for details.
|
data/lib/restfully/resource.rb
CHANGED
@@ -2,9 +2,9 @@ module Restfully
|
|
2
2
|
# This class represents a Resource, which can be accessed and manipulated
|
3
3
|
# via HTTP methods.
|
4
4
|
#
|
5
|
-
#
|
6
|
-
#
|
7
|
-
#
|
5
|
+
# Some resources can be collection of other resources.
|
6
|
+
# In that case the <tt>Restfully::Collection</tt> module is included in the <tt>Restfully::Resource</tt> class.
|
7
|
+
# See the corresponding documentation for the list of additional methods that you can use on a collection resource.
|
8
8
|
class Resource
|
9
9
|
attr_reader :response, :request, :session
|
10
10
|
|
@@ -17,11 +17,10 @@ module Restfully
|
|
17
17
|
@associations = {}
|
18
18
|
end
|
19
19
|
|
20
|
-
# == Description
|
21
20
|
# Returns the value corresponding to the specified key,
|
22
|
-
# among the list of resource properties
|
21
|
+
# among the list of resource properties.
|
23
22
|
#
|
24
|
-
#
|
23
|
+
# e.g.:
|
25
24
|
# resource["uid"]
|
26
25
|
# => "rennes"
|
27
26
|
def [](key)
|
@@ -31,26 +30,32 @@ module Restfully
|
|
31
30
|
media_type.property(key)
|
32
31
|
end
|
33
32
|
|
33
|
+
# Returns the resource URI.
|
34
34
|
def uri
|
35
35
|
request.uri
|
36
36
|
end
|
37
37
|
|
38
|
+
# Returns the Restfully::MediaType object that was used to parse the response.
|
38
39
|
def media_type
|
39
40
|
response.media_type
|
40
41
|
end
|
41
|
-
|
42
|
+
|
43
|
+
# Does this resource contain only a fragment of the full resource?
|
42
44
|
def complete?
|
43
45
|
media_type.complete?
|
44
46
|
end
|
45
47
|
|
48
|
+
# Is this resource a collection of items?
|
46
49
|
def collection?
|
47
50
|
media_type.collection?
|
48
51
|
end
|
49
|
-
|
52
|
+
|
53
|
+
# Returns the resource kind: "Collection" or "Resource".
|
50
54
|
def kind
|
51
55
|
collection? ? "Collection" : "Resource"
|
52
56
|
end
|
53
|
-
|
57
|
+
|
58
|
+
# Returns the "signature" of the resource. Used for (pretty-)inspection.
|
54
59
|
def signature(closed=true)
|
55
60
|
s = "#<#{kind}:0x#{object_id.to_s(16)}"
|
56
61
|
s += " uri=#{uri.to_s}"
|
@@ -58,6 +63,9 @@ module Restfully
|
|
58
63
|
s
|
59
64
|
end
|
60
65
|
|
66
|
+
# Load the resource. The <tt>options</tt> Hash can contain any number of parameters among which:
|
67
|
+
# <tt>:head</tt>:: a Hash of HTTP headers to pass when fetching the resource.
|
68
|
+
# <tt>:query</tt>:: a Hash of query parameters to add to the URI when fetching the resource.
|
61
69
|
def load(options = {})
|
62
70
|
# Send a GET request only if given a different set of options
|
63
71
|
if @request.update!(options) || @request.no_cache?
|
@@ -72,28 +80,29 @@ module Restfully
|
|
72
80
|
|
73
81
|
build
|
74
82
|
end
|
75
|
-
|
83
|
+
|
84
|
+
# Returns the list of relationships for this resource, extracted from the resource links ("rel" attribute).
|
76
85
|
def relationships
|
77
86
|
response.links.map(&:id).sort
|
78
87
|
end
|
79
|
-
|
88
|
+
|
89
|
+
# Returns the Hash of properties for this resource.
|
80
90
|
def properties
|
81
91
|
media_type.property.reject{|k,v|
|
82
92
|
# do not return keys used for internal use
|
83
93
|
k.to_s =~ HIDDEN_PROPERTIES_REGEXP
|
84
94
|
}
|
85
95
|
end
|
86
|
-
|
87
|
-
#
|
88
|
-
# cache instead of explicitly saying @request.no_cache! (and update the
|
89
|
-
# #load method accordingly)
|
90
|
-
|
91
|
-
# Force reloading of the request
|
96
|
+
|
97
|
+
# Force reloading of the resource.
|
92
98
|
def reload
|
93
99
|
@request.no_cache!
|
94
100
|
load
|
95
101
|
end
|
96
102
|
|
103
|
+
# POST some payload on that resource URI.
|
104
|
+
# Either you pass a serialized payload as first argument, followed by an optional Hash of <tt>:head</tt> and <tt>:query</tt> parameters.
|
105
|
+
# Or you pass your payload as a Hash, and the serialization will occur based on the Content-Type you set (and only if a corresponding MediaType can be found in the MediaType catalog).
|
97
106
|
def submit(*args)
|
98
107
|
if allow?("POST")
|
99
108
|
@request.no_cache!
|
@@ -104,6 +113,8 @@ module Restfully
|
|
104
113
|
end
|
105
114
|
end
|
106
115
|
|
116
|
+
# Send a DELETE HTTP request on the resource URI.
|
117
|
+
# See <tt>#load</tt> for the list of arguments this method can take.
|
107
118
|
def delete(options = {})
|
108
119
|
if allow?("DELETE")
|
109
120
|
@request.no_cache!
|
@@ -113,6 +124,8 @@ module Restfully
|
|
113
124
|
end
|
114
125
|
end
|
115
126
|
|
127
|
+
# Send a PUT HTTP request with some payload on the resource URI.
|
128
|
+
# See <tt>#submit</tt> for the list of arguments this method can take.
|
116
129
|
def update(*args)
|
117
130
|
if allow?("PUT")
|
118
131
|
@request.no_cache!
|
@@ -123,6 +136,7 @@ module Restfully
|
|
123
136
|
end
|
124
137
|
end
|
125
138
|
|
139
|
+
# Returns true if the resource supports the given HTTP <tt>method</tt> (String or Symbol).
|
126
140
|
def allow?(method)
|
127
141
|
response.allow?(method) || reload.response.allow?(method)
|
128
142
|
end
|
@@ -173,8 +187,7 @@ module Restfully
|
|
173
187
|
nil
|
174
188
|
end
|
175
189
|
|
176
|
-
|
177
|
-
|
190
|
+
# Build the resource after loading.
|
178
191
|
def build
|
179
192
|
metaclass = class << self; self; end
|
180
193
|
# only build once
|
@@ -192,7 +205,8 @@ module Restfully
|
|
192
205
|
# end
|
193
206
|
self
|
194
207
|
end
|
195
|
-
|
208
|
+
|
209
|
+
# Reload itself if the resource is not <tt>#complete?</tt>.
|
196
210
|
def expand
|
197
211
|
reload unless complete?
|
198
212
|
self
|
data/lib/restfully/session.rb
CHANGED
@@ -13,9 +13,34 @@ module Restfully
|
|
13
13
|
attr_reader :config
|
14
14
|
attr_writer :default_headers
|
15
15
|
|
16
|
+
# Builds a new client session.
|
17
|
+
# Takes a number of <tt>options</tt> as input.
|
18
|
+
# Yields or return the <tt>root</tt> Restfully::Resource object, and the Restfully::Session object.
|
19
|
+
#
|
20
|
+
# <tt>:configuration_file</tt>:: the location of a YAML configuration file that contains any of the parameters below.
|
21
|
+
# <tt>:uri</tt>:: the entry-point URI for this session.
|
22
|
+
# <tt>:logger</tt>:: a Logger object, used to display information.
|
23
|
+
# <tt>:require</tt>:: an Array of Restfully::MediaType objects to automatically require for this session.
|
24
|
+
# <tt>:retry_on_error</tt>:: the maximum number of attempts to make when a server (502,502,504) or connection error occurs.
|
25
|
+
# <tt>:wait_before_retry</tt>:: the number of seconds to wait before making another attempt when a server or connection error occurs.
|
26
|
+
# <tt>:default_headers</tt>:: a Hash of default HTTP headers to send with each request.
|
27
|
+
# <tt>:cache</tt>:: a Hash of parameters to configure the caching component. See <http://rtomayko.github.com/rack-cache/configuration> for more information.
|
28
|
+
#
|
29
|
+
# e.g.
|
30
|
+
# Restfully::Session.new(
|
31
|
+
# :uri => "https://api.bonfire-project.eu:444/",
|
32
|
+
# :username => "crohr",
|
33
|
+
# :password => "PASSWORD",
|
34
|
+
# :require => ['ApplicationVndBonfireXml']
|
35
|
+
# ) {|root, session| p root}
|
36
|
+
#
|
16
37
|
def initialize(options = {})
|
17
38
|
@config = options.symbolize_keys
|
18
|
-
@logger = @config.delete(:logger)
|
39
|
+
@logger = @config.delete(:logger)
|
40
|
+
if @logger.nil?
|
41
|
+
@logger = Logger.new(STDERR)
|
42
|
+
@logger.level = Logger::INFO
|
43
|
+
end
|
19
44
|
|
20
45
|
# Read configuration from file:
|
21
46
|
config_file = @config.delete(:configuration_file) || ENV['RESTFULLY_CONFIG']
|
@@ -46,25 +71,30 @@ module Restfully
|
|
46
71
|
|
47
72
|
disable RestClient::Rack::Compatibility
|
48
73
|
authenticate(@config)
|
49
|
-
setup_cache
|
74
|
+
setup_cache((@config.delete(:cache) || {}).symbolize_keys)
|
50
75
|
|
51
76
|
yield root, self if block_given?
|
52
77
|
end
|
53
78
|
|
79
|
+
# Enable a RestClient Rack component.
|
54
80
|
def enable(rack, *args)
|
55
81
|
logger.info "Enabling #{rack.inspect}."
|
56
82
|
RestClient.enable rack, *args
|
57
83
|
end
|
58
84
|
|
85
|
+
# Disable a RestClient Rack component.
|
59
86
|
def disable(rack, *args)
|
60
87
|
logger.info "Disabling #{rack.inspect}."
|
61
88
|
RestClient.disable rack, *args
|
62
89
|
end
|
63
90
|
|
91
|
+
# Returns the list of middleware components enabled.
|
92
|
+
# See rest-client-components for more information.
|
64
93
|
def middleware
|
65
94
|
RestClient.components.map{|(rack, args)| rack}
|
66
95
|
end
|
67
96
|
|
97
|
+
# Authnenticates the request using Basic Authentication.
|
68
98
|
def authenticate(options = {})
|
69
99
|
if options[:username]
|
70
100
|
enable(
|
@@ -80,6 +110,7 @@ module Restfully
|
|
80
110
|
Addressable::URI.join(uri.to_s, path.to_s)
|
81
111
|
end
|
82
112
|
|
113
|
+
# Return the Hash of default HTTP headers that are sent with each request.
|
83
114
|
def default_headers
|
84
115
|
@default_headers ||= {
|
85
116
|
'Accept' => '*/*',
|
@@ -87,6 +118,7 @@ module Restfully
|
|
87
118
|
}
|
88
119
|
end
|
89
120
|
|
121
|
+
# Returns the root Restfully::Resource.
|
90
122
|
def root
|
91
123
|
get(uri.path).load
|
92
124
|
end
|
@@ -153,8 +185,9 @@ module Restfully
|
|
153
185
|
end
|
154
186
|
|
155
187
|
protected
|
156
|
-
def setup_cache
|
157
|
-
|
188
|
+
def setup_cache(options = {})
|
189
|
+
opts = {:verbose => (logger.level <= Logger::INFO)}.merge(options)
|
190
|
+
enable ::Rack::Cache, opts
|
158
191
|
end
|
159
192
|
|
160
193
|
def error_message(request, response)
|
data/lib/restfully/version.rb
CHANGED
@@ -11,17 +11,47 @@ describe Restfully::Session do
|
|
11
11
|
}
|
12
12
|
end
|
13
13
|
|
14
|
-
|
15
|
-
session
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
14
|
+
describe "intialization" do
|
15
|
+
it "should initialize a session with the correct properties" do
|
16
|
+
session = Restfully::Session.new(@config.merge("key" => "value"))
|
17
|
+
session.logger.should == @logger
|
18
|
+
session.uri.should == Addressable::URI.parse(@uri)
|
19
|
+
session.config.should == {:wait_before_retry=>5, :key=>"value", :retry_on_error=>5}
|
20
|
+
end
|
20
21
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
22
|
+
it "should raise an error if no URI given" do
|
23
|
+
lambda{
|
24
|
+
Restfully::Session.new(@config.merge(:uri => ""))
|
25
|
+
}.should raise_error(ArgumentError)
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should add or replace additional headers to the default set" do
|
29
|
+
session = Restfully::Session.new(
|
30
|
+
@config.merge(:default_headers => {
|
31
|
+
'Accept' => 'application/xml',
|
32
|
+
'Cache-Control' => 'no-cache'
|
33
|
+
})
|
34
|
+
)
|
35
|
+
session.default_headers.should == {
|
36
|
+
'Accept' => 'application/xml',
|
37
|
+
'Cache-Control' => 'no-cache',
|
38
|
+
'Accept-Encoding' => 'gzip, deflate'
|
39
|
+
}
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should pass configuration options to Rack::Cache" do
|
43
|
+
session = Restfully::Session.new(@config.merge({
|
44
|
+
:cache => {
|
45
|
+
:metastore => 'file:/var/cache/rack/meta',
|
46
|
+
:entitystore => 'file:/var/cache/rack/body'
|
47
|
+
}
|
48
|
+
}))
|
49
|
+
RestClient.components.should == [[Rack::Cache, [{
|
50
|
+
:verbose => true,
|
51
|
+
:metastore => 'file:/var/cache/rack/meta',
|
52
|
+
:entitystore => 'file:/var/cache/rack/body'
|
53
|
+
}]]]
|
54
|
+
end
|
25
55
|
end
|
26
56
|
|
27
57
|
it "should fetch the root path [no URI path]" do
|
@@ -42,20 +72,6 @@ describe Restfully::Session do
|
|
42
72
|
session.root.should == res
|
43
73
|
end
|
44
74
|
|
45
|
-
it "should add or replace additional headers to the default set" do
|
46
|
-
session = Restfully::Session.new(
|
47
|
-
@config.merge(:default_headers => {
|
48
|
-
'Accept' => 'application/xml',
|
49
|
-
'Cache-Control' => 'no-cache'
|
50
|
-
})
|
51
|
-
)
|
52
|
-
session.default_headers.should == {
|
53
|
-
'Accept' => 'application/xml',
|
54
|
-
'Cache-Control' => 'no-cache',
|
55
|
-
'Accept-Encoding' => 'gzip, deflate'
|
56
|
-
}
|
57
|
-
end
|
58
|
-
|
59
75
|
describe "middleware" do
|
60
76
|
it "should only have Rack::Cache enabled by default" do
|
61
77
|
session = Restfully::Session.new(@config)
|
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: restfully
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 15424097
|
5
5
|
prerelease: 6
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 7
|
9
9
|
- 1
|
10
10
|
- rc
|
11
|
-
-
|
12
|
-
version: 0.7.1.
|
11
|
+
- 6
|
12
|
+
version: 0.7.1.rc6
|
13
13
|
platform: ruby
|
14
14
|
authors:
|
15
15
|
- Cyril Rohr
|
@@ -17,7 +17,7 @@ autorequire:
|
|
17
17
|
bindir: bin
|
18
18
|
cert_chain: []
|
19
19
|
|
20
|
-
date: 2011-05-
|
20
|
+
date: 2011-05-17 00:00:00 +02:00
|
21
21
|
default_executable:
|
22
22
|
dependencies:
|
23
23
|
- !ruby/object:Gem::Dependency
|