restfolia 1.0.0

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/.gitignore ADDED
@@ -0,0 +1,8 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ tags
6
+ .rvmrc*
7
+ .yardoc*
8
+ doc/
data/.travis.yml ADDED
@@ -0,0 +1,3 @@
1
+ rvm:
2
+ - 1.8.7
3
+ - 1.9.3
data/.yardopts ADDED
@@ -0,0 +1 @@
1
+ --plugin yard-tomdoc -r Readme.md - MIT-LICENSE ReadmeDeveloper.md
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in librarian.gemspec
4
+ gemspec
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2012 Roger Leite http://1up4dev.org
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new do |t|
5
+ t.libs.push "lib"
6
+ t.libs.push "test"
7
+ t.test_files = FileList['test/**/*_test.rb']
8
+ t.verbose = true
9
+ end
10
+
11
+ task :default => :test
data/Readme.md ADDED
@@ -0,0 +1,101 @@
1
+ # Restfolia [![Build Status][travis_status]][travis]
2
+
3
+ [travis_status]: https://secure.travis-ci.org/rogerleite/restfolia.png
4
+ [travis]: http://travis-ci.org/rogerleite/restfolia
5
+
6
+ REST client to consume and interact with Hypermedia API, using JSON as Media Type.
7
+
8
+ ## Description
9
+
10
+ Restfolia is a REST client and it's main goal is help you **consume and interact** with Hypermedia APIs.
11
+
12
+ Against the grain, Restfolia is very opinionated about some REST's concepts:
13
+
14
+ * Aims only **JSON Media Type**.
15
+ * All responses are parsed and returned as Restfolia::Resource.
16
+ * Less is more. Restfolia is very proud to be small, easy to maintain and evolve. You can compare Restfolia's code with "Similar Projects" at page's bottom.
17
+ * Restfolia::Resource is Ruby object with attributes from JSON and can optionally contains **hypermedia links** which have to be a specific format. See the examples below.
18
+ * All code is very well documented, using [TomDoc](http://tomdoc.org style).
19
+
20
+ Obs: This is a draft version. Not ready for production (yet!).
21
+
22
+ ## References
23
+
24
+ You can find more information about arquitecture REST below:
25
+
26
+ * [Roy Fielding's](http://roy.gbiv.com/untangled) see this post for example: [REST APIs must be hypertext-driven](http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven).
27
+ * [Rest in Practice](http://restinpractice.com), especially the chapter titled "Hypermedia Formats".
28
+ * [Mike Amundsen's Blog](http://amundsen.com/blog)
29
+ * ROAR - [Resource Oriented Arquitectures in Ruby](https://github.com/apotonick/roar) it seems really good to build a hypermedia API, of course you can go with Sinatra+rabl solutions too.
30
+
31
+ ## Examples of use
32
+
33
+ ```js
34
+ // GET http://localhost:9292/recursos/busca
35
+ { "itens_por_pagina" : 10,
36
+ "paginal_atual" : 1,
37
+ "paginas_totais" : 1,
38
+ "query" : "",
39
+ "total_resultado" : 100,
40
+ "resultado" : [ { "id" : 1,
41
+ "name" : "Test1",
42
+ "links" : [ { "href" : "http://localhost:9292/recursos/id/1",
43
+ "rel" : "recurso",
44
+ "type" : "application/json"
45
+ } ]
46
+ },
47
+ { "id" : 2,
48
+ "name" : "Test2",
49
+ "links" : [ { "href" : "http://localhost:9292/recursos/id/2",
50
+ "rel" : "recurso",
51
+ "type" : "application/json"
52
+ } ]
53
+ }
54
+ ],
55
+ "links" : { "href" : "http://localhost:9292/recursos/busca",
56
+ "rel" : "self",
57
+ "type" : "application/json"
58
+ },
59
+ }
60
+ ```
61
+
62
+ ```js
63
+ // GET http://localhost:9292/recursos/id/1
64
+ { "id" : 1,
65
+ "name" : "Test1",
66
+ "links" : { "href" : "http://localhost:9292/recursos/id/1",
67
+ "rel" : "self",
68
+ "type" : "application/json"
69
+ }
70
+ }
71
+ ```
72
+
73
+ ```ruby
74
+ # getting a resource
75
+ resource = Restfolia.at('http://localhost:9292/recursos/busca').get
76
+ resource.pagina_atual # => 1
77
+ resource.resultado # => [#<Resource ...>, #<Resource ...>]
78
+
79
+ # example of hypermedia navigation
80
+ r1 = resource.resultado.first
81
+ r1 = r1.links("recurso").get # => #<Resource ...>
82
+ r1.name # => "Test1"
83
+ ```
84
+
85
+ ## Similar Projects
86
+
87
+ * [ROAR](https://github.com/apotonick/roar)
88
+ * [Leadlight](https://github.com/avdi/leadlight)
89
+ * [Frenetic](https://github.com/dlindahl/frenetic)
90
+ * [Restfulie](https://github.com/caelum/restfulie)
91
+
92
+ ## What is "folia"?
93
+
94
+ Folia is a portuguese word and a simple translation in English can be:
95
+
96
+ > sf merry-making, merriment, revelry. que folia! what a fun!
97
+
98
+ ## License
99
+
100
+ Restfolia is copyright 2012 Roger Leite and contributors. It is licensed under the MIT license. See the include MIT-LICENSE file for details.
101
+
@@ -0,0 +1,30 @@
1
+ ## Steps to generate doc
2
+
3
+ ```
4
+ # dependencies
5
+ $ gem install yard
6
+ $ gem install yard-tomdoc
7
+ $ gem install redcarpet
8
+
9
+ # use params from .yardopts file
10
+ $ yard
11
+ $ open doc/index.html
12
+ ```
13
+ **Obs:** ignore errors :X, until my [pull request](https://github.com/rubyworks/yard-tomdoc/pull/5) be accepted.
14
+
15
+ ## TODO:
16
+
17
+ Improvements:
18
+
19
+ * Add "events" before and after request. This could be
20
+ cool to make projects that extends Restfolia features.
21
+
22
+ Resource & EntryPoint
23
+
24
+ * facilitate cache (Cache Control, ETag, Last-Modified).
25
+ This could be another project like restfolia-cazuza.
26
+
27
+ Future Ideas
28
+
29
+ * Support to JSON HAL
30
+ * Another project, to Restfolia be a "Restfulie like". Main mission: migrate old projects
@@ -0,0 +1,156 @@
1
+ module Restfolia
2
+
3
+
4
+ # Public: Responsible for request and validate a Resource.
5
+ # Abstract details of how to deal with HTTP, like headers,
6
+ # cookies, auth etc.
7
+ # The correct form to create an EntryPoint, is using Restfolia.at
8
+ # or links from some instance of Restfolia::Resource. See the
9
+ # examples for more details.
10
+ #
11
+ # Examples
12
+ #
13
+ # ep = Restfolia.at("http://fakeurl.com/some/service")
14
+ # # => #<EntryPoint ...>
15
+ #
16
+ # resource = Restfolia.at("http://fakeurl.com/service/id/1").get
17
+ # resource.links("contacts")
18
+ # # => #<EntryPoint ...> to "contacts" from this resource
19
+ class EntryPoint
20
+
21
+ include Restfolia::HTTP::Configuration
22
+
23
+ # Public: Returns the String url of EntryPoint.
24
+ attr_reader :url
25
+
26
+ # Public: Returns String that represents the relation of EntryPoint.
27
+ attr_reader :rel
28
+
29
+ # Public: Creates an EntryPoint.
30
+ #
31
+ # url - A String address of some API service.
32
+ # rel - An optional String that represents the relation of EntryPoint.
33
+ def initialize(url, rel = nil)
34
+ @url = url
35
+ @rel = rel
36
+ end
37
+
38
+ # Public: Get the Resource from this EntryPoint's url.
39
+ #
40
+ # params - an optional query String or Hash object. String parameter
41
+ # is passed direct as query. Hash object, before mounting query,
42
+ # URI.encode is used on values.
43
+ #
44
+ # Examples
45
+ #
46
+ # # GET on http://service.com/search
47
+ # resource = Restfolia.at("http://service.com/search").get
48
+ #
49
+ # # GET on http://service.com/search?q=test
50
+ # resource = Restfolia.at("http://service.com/search").get(:q => "test")
51
+ # # or if you want to control your query, you can send a String
52
+ # resource = Restfolia.at("http://service.com/search").get("q=test")
53
+ #
54
+ # Returns depends on http code from response. For each "range"
55
+ # (ex. 2xx, 3xx ... etc) you can have a different return value.
56
+ # For 2xx range, you can expect an instance of Restfolia::Resource.
57
+ # You can see Restfolia::HttpBehaviour for more details.
58
+ #
59
+ # Raises Restfolia::ResponseError for unexpected conditions. See
60
+ # Restfolia::HTTP::Behaviour methods for more details.
61
+ # Raises URI::InvalidURIError if url attribute is invalid.
62
+ def get(params = nil)
63
+ query = if params && params.is_a?(String)
64
+ params
65
+ elsif params && params.is_a?(Hash)
66
+ params.map { |k, v| "#{k}=#{URI.encode(v)}" }.join
67
+ end
68
+
69
+ args = self.configuration.merge(:query => query)
70
+ http_resp = Restfolia::HTTP::Request.do_request(:get, self.url, args)
71
+ Restfolia::HTTP.response_by_status_code(http_resp)
72
+ end
73
+
74
+ # Public: Post data to EntryPoint's url.
75
+ #
76
+ # params - Hash object with data to be encoded as JSON and send as
77
+ # request body.
78
+ #
79
+ # Examples
80
+ #
81
+ # # Expecting API respond with 201 and Location header
82
+ # data = {:name => "Test"}
83
+ # resource = Restfolia.at("http://service.com/resource/1").post(data)
84
+ #
85
+ # Returns depends on http code from response. For each "range"
86
+ # (ex. 2xx, 3xx ... etc) you can have a different return value.
87
+ # For 2xx range, you can expect an instance of Restfolia::Resource.
88
+ # You can see Restfolia::HttpBehaviour for more details.
89
+ #
90
+ # Raises Restfolia::ResponseError for unexpected conditions. See
91
+ # Restfolia::HTTP::Behaviour methods for more details.
92
+ # Raises URI::InvalidURIError if url attribute is invalid.
93
+ def post(params)
94
+ body = MultiJson.dump(params)
95
+
96
+ args = self.configuration.merge(:body => body)
97
+ http_resp = Restfolia::HTTP::Request.do_request(:post, self.url, args)
98
+ Restfolia::HTTP.response_by_status_code(http_resp)
99
+ end
100
+
101
+ # Public: Put data to EntryPoint's url.
102
+ #
103
+ # params - Hash object with data to be encoded as JSON and send as
104
+ # request body.
105
+ #
106
+ # Examples
107
+ #
108
+ # # Expecting API respond with 201 and Location header
109
+ # data = {:name => "Test"}
110
+ # resource = Restfolia.at("http://service.com/resource/1").put(data)
111
+ #
112
+ # Returns depends on http code from response. For each "range"
113
+ # (ex. 2xx, 3xx ... etc) you can have a different return value.
114
+ # For 2xx range, you can expect an instance of Restfolia::Resource.
115
+ # You can see Restfolia::HttpBehaviour for more details.
116
+ #
117
+ # Raises Restfolia::ResponseError for unexpected conditions. See
118
+ # Restfolia::HTTP::Behaviour methods for more details.
119
+ # Raises URI::InvalidURIError if url attribute is invalid.
120
+ def put(params)
121
+ body = MultiJson.dump(params)
122
+
123
+ args = self.configuration.merge(:body => body)
124
+ http_resp = Restfolia::HTTP::Request.do_request(:put, self.url, args)
125
+ Restfolia::HTTP.response_by_status_code(http_resp)
126
+ end
127
+
128
+ # Public: Send Delete verb to EntryPoint's url.
129
+ #
130
+ # Examples
131
+ #
132
+ # # Expecting API respond with 204 and empty body
133
+ # resource = Restfolia.at("http://service.com/resource/1").delete
134
+ #
135
+ # Returns depends on http code from response. For each "range"
136
+ # (ex. 2xx, 3xx ... etc) you can have a different return value.
137
+ # For 2xx range, you can expect an instance of Restfolia::Resource.
138
+ # You can see Restfolia::HttpBehaviour for more details.
139
+ #
140
+ # Raises Restfolia::ResponseError for unexpected conditions. See
141
+ # Restfolia::HTTP::Behaviour methods for more details.
142
+ # Raises URI::InvalidURIError if url attribute is invalid.
143
+ def delete
144
+ http_resp = Restfolia::HTTP::Request.do_request(:delete, self.url, self.configuration)
145
+ Restfolia::HTTP.response_by_status_code(http_resp)
146
+ end
147
+
148
+ # Returns url and rel for inspecting.
149
+ def inspect
150
+ "#<#{self.class} @url=\"#{@url}\" @rel=\"#{@rel}\">"
151
+ end
152
+
153
+ end
154
+
155
+
156
+ end
@@ -0,0 +1,109 @@
1
+ module Restfolia
2
+
3
+ # Public: Exception to represent an invalid HTTP response.
4
+ #
5
+ # Examples
6
+ #
7
+ # begin
8
+ # # assuming http_response is 404 response
9
+ # raise ResponseError.new("message", caller, http_response)
10
+ # rescue Restfolia::ResponseError => ex
11
+ # ex.http_code # => 404
12
+ # ex.http_message # => "Not Found"
13
+ # ex.http_object # => http_response object
14
+ # end
15
+ #
16
+ class ResponseError < StandardError
17
+
18
+ # Returns nil or #code from http_response instance
19
+ attr_reader :http_code
20
+
21
+ # Returns nil or status code definition from #http_code
22
+ attr_reader :http_message
23
+
24
+ # List of HTTP Status code definitions.
25
+ # Source http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
26
+ HTTP_CODE_MSG = {
27
+ # 2xx
28
+ 200 => 'OK',
29
+ 201 => 'Created',
30
+ 202 => 'Accepted',
31
+ 203 => 'Non-Authoritative Information',
32
+ 204 => 'No Content',
33
+ 205 => 'Reset Content',
34
+ 206 => 'Partial Content',
35
+ # 3xx
36
+ 300 => 'Multiple Choices',
37
+ 301 => 'MovedPermanently',
38
+ 302 => 'Found',
39
+ 303 => 'SeeOther',
40
+ 304 => 'NotModified',
41
+ 305 => 'UseProxy',
42
+ 306 => '(Unused)',
43
+ 307 => 'TemporaryRedirect',
44
+ # 4xx
45
+ 400 => 'Bad Request',
46
+ 401 => 'Unauthorized',
47
+ 402 => 'Payment Required',
48
+ 403 => 'Forbidden',
49
+ 404 => 'Not Found',
50
+ 405 => 'Method Not Allowed',
51
+ 406 => 'Not Acceptable',
52
+ 407 => 'Proxy Authentication Required',
53
+ 408 => 'Request Timeout',
54
+ 409 => 'Conflict',
55
+ 410 => 'Gone',
56
+ 411 => 'Length Required',
57
+ 412 => 'Precondition Failed',
58
+ 413 => 'Request Entity Too Large',
59
+ 414 => 'Request-URI Too Long',
60
+ 415 => 'Unsupported Media Type',
61
+ 416 => 'Requested Range Not Satisfiable',
62
+ 417 => 'Expectation Failed',
63
+ # 5xx
64
+ 500 => 'Internal Server Error',
65
+ 501 => 'Not Implemented',
66
+ 502 => 'Bad Gateway',
67
+ 503 => 'Service Unavailable',
68
+ 504 => 'Gateway Timeout',
69
+ 505 => 'HTTP Version Not Supported'
70
+ }
71
+
72
+ # Public: Creates a ResponseError.
73
+ #
74
+ # message - String to describe the error.
75
+ # backtrace - Array, usually mounted by Kernel#caller.
76
+ # http_response - Net::HTTPResponse with error.
77
+ #
78
+ # Examples
79
+ #
80
+ # begin
81
+ # # assuming http_response is 404 response
82
+ # raise ResponseError.new("message", caller, http_response)
83
+ # rescue Restfolia::ResponseError => ex
84
+ # ex.http_code # => 404
85
+ # ex.http_message # => "Not Found"
86
+ # ex.http_object # => http_response object
87
+ # end
88
+ #
89
+ def initialize(message, backtrace, http_response)
90
+ super(message)
91
+ self.set_backtrace(backtrace)
92
+
93
+ @http_response = http_response
94
+ @http_code, @http_message = nil
95
+ if http_response.respond_to?(:code)
96
+ @http_code = http_response.code.to_i
97
+ @http_message = HTTP_CODE_MSG[@http_code] \
98
+ || "Unknown HTTP code (#{@http_code})"
99
+ end
100
+ end
101
+
102
+ # Returns nil or Net::HTTPResponse instance.
103
+ def http_object
104
+ @http_response
105
+ end
106
+
107
+ end
108
+
109
+ end
@@ -0,0 +1,164 @@
1
+ module Restfolia::HTTP
2
+
3
+ # Public: Separated methods to handle HTTP response by status code.
4
+ module Behaviour
5
+
6
+ # Returns Restfolia::HTTP::Behaviour::Store instance.
7
+ def self.store
8
+ @store ||= Store.new
9
+ end
10
+
11
+ # Internal: Helpers Available to behaviours blocks
12
+ #
13
+ # Examples
14
+ #
15
+ # Restfolia::HTTP.behaviours do
16
+ # on(200) do |http_response|
17
+ # helpers.parse_json(http_response.body)
18
+ # end
19
+ # end
20
+ class Helpers
21
+
22
+ # Internal: Parse response body, checking for errors.
23
+ #
24
+ # http_response - HTTP Response with body. Expected to be a JSON.
25
+ #
26
+ # Returns Hash who represents JSON parsed.
27
+ # Raises Restfolia::ResponseError if body seens invalid somehow.
28
+ def parse_json(http_response)
29
+ body = http_response.body
30
+ begin
31
+ MultiJson.load(body, :symbolize_keys => true)
32
+ rescue MultiJson::DecodeError => ex
33
+ msg = "Body should be a valid json. #{ex.message}"
34
+ raise Restfolia::ResponseError.new(msg, caller, http_response)
35
+ end
36
+ end
37
+
38
+ # Public: Request url with GET and forwards to Restfolia::HTTP.
39
+ #
40
+ # url - String. Ex: http://service.com/resources
41
+ #
42
+ # Returns what Restfolia::HTTP.response_by_status_code returns.
43
+ def follow_url(url)
44
+ http_resp = Request.do_request(:get, url)
45
+ Restfolia::HTTP.response_by_status_code(http_resp)
46
+ end
47
+
48
+ end
49
+
50
+ # Public: Responsible to store behaviours. See #behaviours for details.
51
+ class Store
52
+
53
+ # Returns Restfolia::HTTP::Behaviour::Helpers instance.
54
+ attr_reader :helpers
55
+
56
+ # Public: Creates a Store.
57
+ def initialize
58
+ self.clear
59
+ @helpers = Helpers.new
60
+ end
61
+
62
+ # Public: clear all defined behaviours.
63
+ # Returns nothing.
64
+ def clear
65
+ @behaviours = {}
66
+ @behaviours_range = {}
67
+ nil
68
+ end
69
+
70
+ # Public: It's a nice way to define configurations for
71
+ # your behaves using a block.
72
+ #
73
+ # block - Required block to customize your behaves. Below are
74
+ # the methods available inside block:
75
+ # #on - See #on
76
+ #
77
+ # Examples
78
+ #
79
+ # store = Restfolia::HTTP::Behaviour::Store.new
80
+ # store.behaviours do
81
+ # on(200) { '200 behaviour' }
82
+ # on([201, 204]) { 'behaviour for 201 and 204 codes' }
83
+ # on(300...400) { '3xx range' }
84
+ # end
85
+ #
86
+ # Returns nothing.
87
+ def behaviours(&block)
88
+ self.instance_eval(&block)
89
+ nil
90
+ end
91
+
92
+ # Public: Add behaviour on this store. See #behaviours for
93
+ # examples.
94
+ #
95
+ # code - Integer or any object that respond to #include?
96
+ # block - Required block with behaviour for this code.
97
+ #
98
+ # Returns nothing.
99
+ def on(code, &block)
100
+ if code.is_a?(Integer)
101
+ @behaviours[code] = block
102
+ elsif code.respond_to?(:include?)
103
+ @behaviours_range[code] = block
104
+ end
105
+ nil
106
+ end
107
+
108
+ # Public: Method called by #execute in case of 'not found' http code.
109
+ #
110
+ # http_response - Net::HTTPResponse object.
111
+ #
112
+ # Examples
113
+ #
114
+ # store = Restfolia::HTTP::Behaviour::Store.new
115
+ # store.behaviours do
116
+ # on(200) { '200 ok' }
117
+ # end
118
+ # http_resp = OpenStruct.new(:code => 201) #simulate response 201
119
+ # store.execute(http_resp)
120
+ # # => #<Restfolia::ResponseError "Undefined behaviour for 201" ...>
121
+ #
122
+ # Returns nothing.
123
+ # Raises Restfolia::ResponseError
124
+ def default_behaviour(http_response)
125
+ msg = "Undefined behaviour for #{http_response.code}"
126
+ raise Restfolia::ResponseError.new(msg, caller, http_response)
127
+ end
128
+
129
+ # Public: Look for defined behaviour, based on HTTP code.
130
+ # If behaviour not found, call #default_behaviour.
131
+ #
132
+ # http_response - Net::HTTPResponse.
133
+ # Returns Result from Proc behaviour or default_behaviour method.
134
+ def execute(http_response)
135
+ code = http_response.code.to_i
136
+ if (behaviour = find(code))
137
+ behaviour.call(http_response)
138
+ else
139
+ default_behaviour(http_response)
140
+ end
141
+ end
142
+
143
+ protected
144
+
145
+ # Internal: Search for defined behaviour.
146
+ #
147
+ # code - Integer or object that respond to #include?
148
+ #
149
+ # Returns nil or Proc
150
+ def find(code)
151
+ behaviour = @behaviours[code]
152
+ if behaviour.nil?
153
+ _, behaviour = @behaviours_range.detect do |range, proc|
154
+ range.include?(code)
155
+ end
156
+ end
157
+ behaviour
158
+ end
159
+
160
+ end
161
+
162
+ end
163
+
164
+ end
@@ -0,0 +1,74 @@
1
+ module Restfolia::HTTP
2
+
3
+ # Internal: Simply a bag of HTTP options like headers, cookies, auth ... etc.
4
+ module Configuration
5
+
6
+ # Public: Sets/Returns cookies values as String.
7
+ attr_accessor :cookies
8
+
9
+ # Public: Returns Hash to be used as Headers on request.
10
+ def headers
11
+ @headers ||= {}
12
+ end
13
+
14
+ # Public: A fluent way to add Cookies to Request.
15
+ #
16
+ # cookies - String in cookie format.
17
+ #
18
+ # Examples
19
+ #
20
+ # # setting cookie from Google Translate
21
+ # cookies = "PREF=ID=07eb...; expires=Sat, 26-Apr-2014 19:19:36 GMT; path=/; domain=.google.com, NID=59...; expires=Fri, 26-Oct-2012 19:19:36 GMT; path=/; domain=.google.com; HttpOnly"
22
+ # resource = Restfolia.at("http://fake.com").
23
+ # set_cookies(cookies).get
24
+ #
25
+ # Returns self, always!
26
+ def set_cookies(cookies)
27
+ self.cookies = cookies
28
+ self
29
+ end
30
+
31
+ # Public: A fluent way to add HTTP headers.
32
+ # Headers informed here are merged with headers attribute.
33
+ #
34
+ # new_headers - Hash with headers.
35
+ #
36
+ # Examples
37
+ #
38
+ # entry_point = Restfolia.at("http://fake.com")
39
+ # entry_point.with_headers("X-Custom1" => "value",
40
+ # "X-Custom2" => "value2").get
41
+ #
42
+ # Returns self, always!
43
+ # Raises ArgumentError unless new_headers is a Hash.
44
+ def with_headers(new_headers)
45
+ unless new_headers.is_a?(Hash)
46
+ raise ArgumentError, "New Headers should Hash object."
47
+ end
48
+
49
+ headers.merge!(new_headers)
50
+ self
51
+ end
52
+
53
+ # Public: A fluent way to add Content-Type and Accept headers.
54
+ #
55
+ # content_type - String value. Ex: "application/json"
56
+ #
57
+ # Returns self, always!
58
+ def as(content_type)
59
+ headers["Content-Type"] = content_type
60
+ headers["Accept"] = content_type
61
+ self
62
+ end
63
+
64
+ protected
65
+
66
+ # Returns Hash with headers, cookies, auth ... etc.
67
+ def configuration
68
+ {:headers => headers,
69
+ :cookies => cookies}
70
+ end
71
+
72
+ end
73
+
74
+ end