rest_api_builder 0.0.6 → 0.1.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.
- checksums.yaml +4 -4
- data/README.md +65 -26
- data/lib/rest_api_builder.rb +20 -9
- data/lib/rest_api_builder/response_handler.rb +2 -0
- data/rest_api_builder.gemspec +1 -1
- metadata +1 -2
- data/lib/rest_api_builder/request.rb +0 -46
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2e0a07766b5d80c9e2913f70d5004cf946a3c01eb08ea9f43f4c36961122f441
|
4
|
+
data.tar.gz: 7be95767413d7fa4ce3f881282ff75b1c575353ef9fe5522e85c6936eac5d303
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 45531bd762b6039b93f63306be50ada5b880099e04f1c9c59ffbbbca457b790fc2b3f032899b9dfdd65b469e7be319b052d8b024f035d2f0dd82e5e44dc96a1a
|
7
|
+
data.tar.gz: b75b1bfc01db61ebd28bc50200a0ec3c18f487819515e9cf558db7f4411fdd4a58d5039addaab209ba2896ba48160e2439a0f9fb6c4aa90c0b6af32780bd02f4
|
data/README.md
CHANGED
@@ -8,7 +8,7 @@ RestClient is great, but after building a few API clients with it you will almos
|
|
8
8
|
- Handling and extracting details from non-200 responses
|
9
9
|
- Creating testing interfaces for your API clients
|
10
10
|
|
11
|
-
This library's tries to solve these and similar issues by providing a
|
11
|
+
This library's tries to solve these and similar issues by providing a set of helper methods to improve on [rest-client](https://github.com/rest-client/rest-client) features and an optional [webmock](https://github.com/bblimke/webmock) testing interface for it.
|
12
12
|
|
13
13
|
## Installation
|
14
14
|
```
|
@@ -30,7 +30,7 @@ Simply require webmock interface before your test, for example in your `test_hel
|
|
30
30
|
describe 'my test' do
|
31
31
|
it 'performs a request' do
|
32
32
|
RestAPIBuilder::WebMockRequestExpectations.expect_execute(...).to_return(body: "hi!")
|
33
|
-
result =
|
33
|
+
result = RestClient::Request.execute(...)
|
34
34
|
|
35
35
|
# some assertions
|
36
36
|
end
|
@@ -43,23 +43,39 @@ Simply require webmock interface before your test, for example in your `test_hel
|
|
43
43
|
```rb
|
44
44
|
require "rest_api_builder"
|
45
45
|
|
46
|
-
|
46
|
+
class MyRequest
|
47
|
+
include RestAPIBuilder
|
48
|
+
|
49
|
+
def execute(options)
|
50
|
+
handle_response do
|
51
|
+
RestClient::Request.execute(compose_request_options(**options))
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def json_execute(options)
|
56
|
+
handle_json_response do
|
57
|
+
RestClient::Request.execute(compose_json_request_options(**options))
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
my_request = MyRequest.new
|
47
63
|
|
48
64
|
# Simple request:
|
49
|
-
response =
|
65
|
+
response = my_request.execute(base_url: "example.com", method: :get)
|
50
66
|
response[:success] #=> true
|
51
67
|
response[:status] #=> 200
|
52
68
|
response[:body] #=> "<!doctype html>\n<html>..."
|
53
69
|
response[:headers] #=> {:accept_ranges=>"bytes", ...}
|
54
70
|
|
55
71
|
# Non-200 responses:
|
56
|
-
response =
|
72
|
+
response = my_request.execute(base_url: "example.com", path: "/foo", method: :get)
|
57
73
|
response[:success] #=> false
|
58
74
|
response[:status] #=> 404
|
59
75
|
response[:body] #=> "<!doctype html>\n<html>..."
|
60
76
|
|
61
77
|
# JSON requests:
|
62
|
-
response =
|
78
|
+
response = my_request.json_execute(base_url: "api.github.com", path: "/users/octocat/orgs", method: :get)
|
63
79
|
response[:success] #=> true
|
64
80
|
response[:body] #=> []
|
65
81
|
```
|
@@ -72,12 +88,29 @@ require "rest_api_builder/webmock_request_expectations"
|
|
72
88
|
|
73
89
|
WebMock.disable_net_connect!
|
74
90
|
|
75
|
-
|
91
|
+
class MyRequest
|
92
|
+
include RestAPIBuilder
|
93
|
+
|
94
|
+
def execute(options)
|
95
|
+
handle_response do
|
96
|
+
RestClient::Request.execute(compose_request_options(**options))
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def json_execute(options)
|
101
|
+
handle_json_response do
|
102
|
+
RestClient::Request.execute(compose_json_request_options(**options))
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
my_request = MyRequest.new
|
108
|
+
|
76
109
|
Expectations = RestAPIBuilder::WebMockRequestExpectations
|
77
110
|
|
78
111
|
# Simple expectation
|
79
112
|
Expectations.expect_execute(base_url: "test.com", method: :get)
|
80
|
-
response =
|
113
|
+
response = my_request.execute(base_url: "test.com", method: :get)
|
81
114
|
|
82
115
|
response[:success] #=> true
|
83
116
|
response[:status] #=> 200
|
@@ -88,7 +121,7 @@ response[:headers] #=> {}
|
|
88
121
|
Expectations
|
89
122
|
.expect_execute(base_url: "test.com", method: :get)
|
90
123
|
.to_return(status: 404, body: "not found")
|
91
|
-
response =
|
124
|
+
response = my_request.execute(base_url: "test.com", method: :get)
|
92
125
|
|
93
126
|
response[:success] #=> false
|
94
127
|
response[:status] #=> 404
|
@@ -101,11 +134,11 @@ Expectations.expect_execute(
|
|
101
134
|
response: { body: 'hello' },
|
102
135
|
request: { body: WebMock::API.hash_including({foo: "bar"}) }
|
103
136
|
)
|
104
|
-
response =
|
137
|
+
response = my_request.json_execute(base_url: "test.com", method: :post, body: {foo: "bar"})
|
105
138
|
response[:success] #=> true
|
106
139
|
response[:body] #=> 'hello'
|
107
140
|
|
108
|
-
|
141
|
+
my_request.json_execute(base_url: "test.com", method: :post, body: {bar: "baz"}) # => Raises WebMock::NetConnectNotAllowedError
|
109
142
|
|
110
143
|
# Using #expect_json_execute
|
111
144
|
Expectations.expect_json_execute(
|
@@ -113,17 +146,14 @@ Expectations.expect_json_execute(
|
|
113
146
|
method: :get,
|
114
147
|
response: { body: {hi: 'hello'} }
|
115
148
|
)
|
116
|
-
response =
|
149
|
+
response = my_request.execute(base_url: "test.com", method: :get)
|
117
150
|
response[:success] #=> true
|
118
151
|
response[:body] #=> "{\"hi\":\"hello\"}"
|
119
152
|
```
|
120
153
|
|
121
154
|
## Request API
|
122
|
-
### RestAPIBuilder
|
123
|
-
|
124
|
-
Returns ruby hash with following keys: `:success`, `:status`, `:body`, `:headers`\
|
125
|
-
Does not throw on non-200 responses like RestClient does, but will throw on any error without defined response(e.g server timeout)
|
126
|
-
|
155
|
+
### RestAPIBuilder#compose_request_options(options)
|
156
|
+
Composes request options that can be passed to `RestClient::Request.execute`.
|
127
157
|
#### Options:
|
128
158
|
* **base_url**: Base URL of the request. Required.
|
129
159
|
* **method**: HTTP method of the request(e.g :get, :post, :patch). Required.
|
@@ -131,17 +161,26 @@ Does not throw on non-200 responses like RestClient does, but will throw on any
|
|
131
161
|
* **body**: Request Body. Optional.
|
132
162
|
* **headers**: Request Headers. Optional.
|
133
163
|
* **query**: Query hash to be appended to the resulting url. Optional.
|
134
|
-
* **logger**: A `Logger` instance to be passed to RestClient in `log` option. Will also log response details as RestClient does not do this by default. Optional
|
135
|
-
* **parse_json**: Boolean. If `true`, will attempt to parse the response body as JSON. Will return the response body unchanged if it does not contain valid JSON. `false` by default.
|
136
|
-
* **raw_response**: Boolean. If `true`, the response returned by RestClient will not be parsed into {:status, :body, :headers}, but instead returned as {:raw_response}. `false` by default.
|
137
|
-
* **rest_client_options**: Any additional options to be passed to `RestClient::Request.execute` unchanged. **Any option set here will completely overwrite all custom options**. For example, if you call `RestAPIBuilder::Request.execute(method: :post, rest_client_options: {method: :get})`, the resulting request will be sent as GET. Optional.
|
138
164
|
|
139
|
-
### RestAPIBuilder
|
140
|
-
|
165
|
+
### RestAPIBuilder#compose_json_request_options(options)
|
166
|
+
Accepts same options as `compose_request_options` but will also:
|
141
167
|
- Add `Content-Type: 'application/json'` to request `headers`
|
142
|
-
- Convert request `body` to JSON
|
143
|
-
|
168
|
+
- Convert request `body` to JSON if it's present
|
169
|
+
|
170
|
+
### RestAPIBuilder#handle_response(options, &block)
|
171
|
+
Executes given block, expecting to receive `RestClient::Response` as a result.\
|
172
|
+
Returns **plain ruby hash** with following keys: `:success`, `:status`, `:body`, `:headers`\
|
173
|
+
This will also gracefully handle non-200 responses, but will throw on any error without defined response(e.g server timeout)
|
174
|
+
|
175
|
+
#### Options:
|
176
|
+
* **logger**: A `Logger` instance. If provided, will log response details as RestClient wont do this by default. Optional
|
177
|
+
|
178
|
+
### RestAPIBuilder#handle_json_response(options, &block)
|
179
|
+
Same as `#handle_response` but will also attempt to decode response `:body`, returning it as is if a parsing error occurrs
|
144
180
|
|
181
|
+
### RestAPIBuilder#handle_response_error(options, &block)
|
182
|
+
Low-level API, you can use this method if you want to work with the RestClient's responses directly without any conversions(e.g when using `block_response` or `raw_response` options of RestClient). This will handle errors in the same way as `#handle_response` does, but will not do anything else.\
|
183
|
+
Returns ruby hash with `:success` and `:raw_response` keys.
|
145
184
|
|
146
185
|
## WebMockRequestExpectations API
|
147
186
|
### RestAPIBuilder::WebMockRequestExpectations.expect_execute(options)
|
@@ -155,7 +194,7 @@ Defines a request expectation using WebMock's `stub_request`. Returns an instanc
|
|
155
194
|
* **response**: response details which will be passed to `WebMock::RequestStub#to_return` if provided. Optional
|
156
195
|
|
157
196
|
### RestAPIBuilder::WebMockRequestExpectations.expect_json_execute(options)
|
158
|
-
A convenience shortcut for `#json_execute` which will convert `request[:body]` to JSON if it's
|
197
|
+
A convenience shortcut for `#json_execute` which will convert `request[:body]` to JSON if it's present
|
159
198
|
|
160
199
|
## License
|
161
200
|
MIT
|
data/lib/rest_api_builder.rb
CHANGED
@@ -1,21 +1,32 @@
|
|
1
1
|
require 'forwardable'
|
2
|
-
require 'rest_api_builder/request'
|
3
2
|
require 'rest_api_builder/request_options'
|
4
3
|
require 'rest_api_builder/response_handler'
|
5
4
|
|
6
5
|
module RestAPIBuilder
|
7
|
-
|
6
|
+
class APIHelpers
|
7
|
+
extend Forwardable
|
8
8
|
|
9
|
-
|
10
|
-
|
9
|
+
def initialize
|
10
|
+
@request_options = RequestOptions.new
|
11
|
+
@response_handler = ResponseHandler.new
|
12
|
+
end
|
11
13
|
|
12
|
-
|
14
|
+
def_delegator :@request_options, :compose, :compose_request_options
|
15
|
+
def_delegator :@request_options, :compose_json, :compose_json_request_options
|
13
16
|
|
14
|
-
|
15
|
-
RequestOptions.new
|
17
|
+
def_delegators :@response_handler, :handle_response, :handle_json_response, :handle_response_error
|
16
18
|
end
|
17
19
|
|
18
|
-
|
19
|
-
|
20
|
+
extend Forwardable
|
21
|
+
|
22
|
+
def_delegators :rest_api_builder_helpers,
|
23
|
+
:compose_request_options,
|
24
|
+
:compose_json_request_options,
|
25
|
+
:handle_response,
|
26
|
+
:handle_json_response,
|
27
|
+
:handle_response_error
|
28
|
+
|
29
|
+
def rest_api_builder_helpers
|
30
|
+
APIHelpers.new
|
20
31
|
end
|
21
32
|
end
|
data/rest_api_builder.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'rest_api_builder'
|
3
|
-
s.version = '0.0
|
3
|
+
s.version = '0.1.0'
|
4
4
|
s.summary = "A simple wrapper for rest-client"
|
5
5
|
s.description = "A simple wrapper for rest-client aiming to make creation and testing of API clients easier."
|
6
6
|
s.authors = ["Alexey D"]
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rest_api_builder
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alexey D
|
@@ -62,7 +62,6 @@ files:
|
|
62
62
|
- LICENSE
|
63
63
|
- README.md
|
64
64
|
- lib/rest_api_builder.rb
|
65
|
-
- lib/rest_api_builder/request.rb
|
66
65
|
- lib/rest_api_builder/request_options.rb
|
67
66
|
- lib/rest_api_builder/response_handler.rb
|
68
67
|
- lib/rest_api_builder/url_helper.rb
|
@@ -1,46 +0,0 @@
|
|
1
|
-
require 'rest-client'
|
2
|
-
|
3
|
-
module RestAPIBuilder
|
4
|
-
class RequestSingleton
|
5
|
-
def json_execute(headers: {}, body: nil, **options)
|
6
|
-
headers = headers.merge(content_type: :json)
|
7
|
-
body &&= JSON.generate(body)
|
8
|
-
execute(**options, parse_json: true, headers: headers, body: body)
|
9
|
-
end
|
10
|
-
|
11
|
-
def execute(
|
12
|
-
base_url:,
|
13
|
-
method:,
|
14
|
-
body: nil,
|
15
|
-
headers: {},
|
16
|
-
query: nil,
|
17
|
-
path: nil,
|
18
|
-
logger: nil,
|
19
|
-
parse_json: false,
|
20
|
-
raw_response: false,
|
21
|
-
rest_client_options: {}
|
22
|
-
)
|
23
|
-
options = RequestOptions.new.compose(
|
24
|
-
base_url: base_url,
|
25
|
-
method: method,
|
26
|
-
body: body,
|
27
|
-
headers: headers,
|
28
|
-
query: query,
|
29
|
-
path: path
|
30
|
-
)
|
31
|
-
|
32
|
-
response_handler = ResponseHandler.new
|
33
|
-
execute_request = proc { RestClient::Request.execute(**options, log: logger, **rest_client_options) }
|
34
|
-
|
35
|
-
if raw_response
|
36
|
-
response_handler.handle_response_error(&execute_request)
|
37
|
-
elsif parse_json
|
38
|
-
response_handler.handle_json_response(logger: logger, &execute_request)
|
39
|
-
else
|
40
|
-
response_handler.handle_response(logger: logger, &execute_request)
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
Request = RequestSingleton.new
|
46
|
-
end
|