api-transformer 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/.overcommit.yml +27 -0
- data/.rubocop.yml +9 -0
- data/.rubocop_todo.yml +15 -0
- data/.travis.yml +4 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +358 -0
- data/Rakefile +9 -0
- data/api-transformer.gemspec +31 -0
- data/examples/ip_server.rb +19 -0
- data/lib/api/transformer.rb +1 -0
- data/lib/api_transformer/backend_request.rb +79 -0
- data/lib/api_transformer/backend_request_sender.rb +56 -0
- data/lib/api_transformer/backend_response.rb +62 -0
- data/lib/api_transformer/endpoint.rb +120 -0
- data/lib/api_transformer/errors.rb +4 -0
- data/lib/api_transformer/frontend_response.rb +52 -0
- data/lib/api_transformer/frontend_response_builder.rb +138 -0
- data/lib/api_transformer/params.rb +8 -0
- data/lib/api_transformer/rack/cookie_params.rb +38 -0
- data/lib/api_transformer/routes.rb +71 -0
- data/lib/api_transformer/version.rb +4 -0
- data/lib/api_transformer.rb +147 -0
- data/spec/server_spec.rb +746 -0
- data/spec/spec_helper.rb +3 -0
- metadata +199 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 87a3b324b1f0fd77ef0091e47311ef9e0029b92a
|
4
|
+
data.tar.gz: 7cf42588afe1e037df1ce743e4ac2c0e4c5a2398
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ddf7f252707a1340651a815251a1597a461495cee7be30a70521c01faea1d5c1394af59c753cb34422e96a3a91d61494fd22f515ed036cd27416fa123ac622a0
|
7
|
+
data.tar.gz: e670c237da02b04c635ad9b7ad76acec3612b8640afe0174257903802276d56d55852c5461324885634a41a8d5866b44190a35698f532a2f0fb89f68b1da5fcb
|
data/.gitignore
ADDED
data/.overcommit.yml
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# Use this file to configure the Overcommit hooks you wish to use. This will
|
2
|
+
# extend the default configuration defined in:
|
3
|
+
# https://github.com/causes/overcommit/blob/master/config/default.yml
|
4
|
+
#
|
5
|
+
# At the topmost level of this YAML file is a key representing type of hook
|
6
|
+
# being run (e.g. pre-commit, commit-msg, etc.). Within each type you can
|
7
|
+
# customize each hook, such as whether to only run it on certain files (via
|
8
|
+
# `include`), whether to only display output if it fails (via `quiet`), etc.
|
9
|
+
#
|
10
|
+
# For a complete list of hooks, see:
|
11
|
+
# https://github.com/causes/overcommit/tree/master/lib/overcommit/hook
|
12
|
+
#
|
13
|
+
# For a complete list of options that you can use to customize hooks, see:
|
14
|
+
# https://github.com/causes/overcommit#configuration
|
15
|
+
#
|
16
|
+
# Uncomment the following lines to make the configuration take effect.
|
17
|
+
|
18
|
+
PreCommit:
|
19
|
+
Rubocop:
|
20
|
+
on_warn: fail # Treat all warnings as failures
|
21
|
+
|
22
|
+
#PostCheckout:
|
23
|
+
# ALL: # Special hook name that customizes all hooks of this type
|
24
|
+
# quiet: true # Change all post-checkout hooks to only display output on failure
|
25
|
+
#
|
26
|
+
# IndexTags:
|
27
|
+
# enabled: true # Generate a tags file with `ctags` each time HEAD changes
|
data/.rubocop.yml
ADDED
data/.rubocop_todo.yml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# This configuration was generated by `rubocop --auto-gen-config`
|
2
|
+
# on 2014-09-12 14:27:20 -0700 using RuboCop version 0.24.1.
|
3
|
+
# The point is for the user to remove these configuration records
|
4
|
+
# one by one as the offenses are removed from the code base.
|
5
|
+
# Note that changes in the inspected code, or installation of new
|
6
|
+
# versions of RuboCop, may require this file to be generated again.
|
7
|
+
|
8
|
+
# Offense count: 2
|
9
|
+
Style/ClassVars:
|
10
|
+
Enabled: false
|
11
|
+
|
12
|
+
# Offense count: 1
|
13
|
+
# Configuration parameters: CountComments.
|
14
|
+
Metrics/ClassLength:
|
15
|
+
Max: 110
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Bruz Marzolf
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,358 @@
|
|
1
|
+
[![Build Status](https://travis-ci.org/CXInc/api-transformer.svg)](https://travis-ci.org/CXInc/api-transformer)
|
2
|
+
[![Code Climate](https://codeclimate.com/github/CXInc/api-transformer/badges/gpa.svg)](https://codeclimate.com/github/CXInc/api-transformer)
|
3
|
+
|
4
|
+
# api-transformer
|
5
|
+
|
6
|
+
**NOTE: this is currently a work in progress**
|
7
|
+
|
8
|
+
A Ruby web server DSL for exposing one or more back-end services through a different API.
|
9
|
+
|
10
|
+
## Installation
|
11
|
+
|
12
|
+
Add this line to your application's Gemfile:
|
13
|
+
|
14
|
+
```ruby
|
15
|
+
gem "api-transformer"
|
16
|
+
```
|
17
|
+
|
18
|
+
And then execute:
|
19
|
+
|
20
|
+
```bash
|
21
|
+
$ bundle
|
22
|
+
```
|
23
|
+
|
24
|
+
Or install it yourself as:
|
25
|
+
|
26
|
+
```bash
|
27
|
+
$ gem install api-transformer
|
28
|
+
```
|
29
|
+
|
30
|
+
## Usage
|
31
|
+
|
32
|
+
### Quick Start
|
33
|
+
|
34
|
+
Create a file ip_server.rb:
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
require 'api_transformer'
|
38
|
+
|
39
|
+
class IpServer < ApiTransformer::Server
|
40
|
+
base_url "http://ip.jsontest.com/"
|
41
|
+
|
42
|
+
get "/ip" do
|
43
|
+
request :ip do
|
44
|
+
path "/"
|
45
|
+
method :get
|
46
|
+
end
|
47
|
+
|
48
|
+
response do |data|
|
49
|
+
success do
|
50
|
+
status 200
|
51
|
+
attribute :your_ip, data[:ip][:ip]
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
```
|
57
|
+
|
58
|
+
Run it:
|
59
|
+
|
60
|
+
```bash
|
61
|
+
$ ruby ip_server.rb -sv
|
62
|
+
```
|
63
|
+
|
64
|
+
Try it:
|
65
|
+
|
66
|
+
```bash
|
67
|
+
$ curl -i http://localhost:9000/ip
|
68
|
+
HTTP/1.1 200 OK
|
69
|
+
Server: Goliath
|
70
|
+
Date: Tue, 30 Sep 2014 23:19:34 GMT
|
71
|
+
|
72
|
+
{"your_ip":"74.125.228.96"}
|
73
|
+
```
|
74
|
+
|
75
|
+
Let's break this down:
|
76
|
+
|
77
|
+
```ruby
|
78
|
+
base_url "http://ip.jsontest.com/"
|
79
|
+
```
|
80
|
+
|
81
|
+
Declare the base URL for back-end requests, which will each provide a path under this.
|
82
|
+
|
83
|
+
```ruby
|
84
|
+
get "/ip" do |params|
|
85
|
+
```
|
86
|
+
|
87
|
+
This defines a single endpoint that responds to GET requests at the path '/ip'.
|
88
|
+
|
89
|
+
request :ip do
|
90
|
+
path "/"
|
91
|
+
method :get
|
92
|
+
end
|
93
|
+
|
94
|
+
It makes a single GET request to the root path of the base_url (http://ip.jsontest.com/).
|
95
|
+
|
96
|
+
```ruby
|
97
|
+
response do |data|
|
98
|
+
success do
|
99
|
+
status 200
|
100
|
+
attribute :your_ip, data[:ip][:ip]
|
101
|
+
end
|
102
|
+
end
|
103
|
+
```
|
104
|
+
|
105
|
+
Upon completion of the request to ip.jsontest.com with a 2XX response, it responds with a status of 200 and a JSON attribute of your_ip.
|
106
|
+
|
107
|
+
### Endpoints without any requests
|
108
|
+
|
109
|
+
Back-end requests are not required.
|
110
|
+
|
111
|
+
```ruby
|
112
|
+
get "/ping" do
|
113
|
+
response do
|
114
|
+
success { attribute :result, "pong" }
|
115
|
+
end
|
116
|
+
end
|
117
|
+
```
|
118
|
+
|
119
|
+
### Accepting parameters
|
120
|
+
|
121
|
+
Query params:
|
122
|
+
|
123
|
+
```ruby
|
124
|
+
get "/some_params" do
|
125
|
+
request :greeting do
|
126
|
+
path "/greeting"
|
127
|
+
method :get
|
128
|
+
|
129
|
+
query_param :greeting, "hello"
|
130
|
+
query_param :name, "Bob"
|
131
|
+
end
|
132
|
+
|
133
|
+
response do
|
134
|
+
success { attribute :result, "hello Bob" }
|
135
|
+
end
|
136
|
+
end
|
137
|
+
```
|
138
|
+
|
139
|
+
Form params:
|
140
|
+
|
141
|
+
```ruby
|
142
|
+
post "/some_params" do
|
143
|
+
request :greeting do
|
144
|
+
path "/greeting"
|
145
|
+
method :post
|
146
|
+
|
147
|
+
form_param :greeting, "hello"
|
148
|
+
form_param :name, "Bob"
|
149
|
+
end
|
150
|
+
|
151
|
+
response do
|
152
|
+
success { attribute :result, "hello Bob" }
|
153
|
+
end
|
154
|
+
end
|
155
|
+
```
|
156
|
+
|
157
|
+
JSON params:
|
158
|
+
|
159
|
+
```ruby
|
160
|
+
post "/some_params" do
|
161
|
+
request :greeting do
|
162
|
+
path "/greeting"
|
163
|
+
method :post
|
164
|
+
|
165
|
+
json_param :greeting, "hello"
|
166
|
+
json_param :name, "Bob"
|
167
|
+
end
|
168
|
+
|
169
|
+
response do
|
170
|
+
success { attribute :result, "hello Bob" }
|
171
|
+
end
|
172
|
+
end
|
173
|
+
```
|
174
|
+
|
175
|
+
JSON params are accepted as a JSON-encoded request body. In this case what would get sent to the back-end endpoint is {"greeting":"hello","name":"Bob"}.
|
176
|
+
|
177
|
+
Form and JSON params can't both be used on the same request.
|
178
|
+
|
179
|
+
### HTTP verbs
|
180
|
+
|
181
|
+
GET, POST, PUT and DELETE are provided:
|
182
|
+
|
183
|
+
```ruby
|
184
|
+
delete "/ping" do
|
185
|
+
response do
|
186
|
+
success { attribute :result, "I should probably delete something" }
|
187
|
+
end
|
188
|
+
end
|
189
|
+
```
|
190
|
+
|
191
|
+
### Pass-through of headers
|
192
|
+
|
193
|
+
```ruby
|
194
|
+
get "/user_agent" do |_, headers|
|
195
|
+
response do
|
196
|
+
success { attribute :user_agent, headers["User-Agent"] }
|
197
|
+
end
|
198
|
+
end
|
199
|
+
```
|
200
|
+
|
201
|
+
### JSON objects and arrays
|
202
|
+
|
203
|
+
Classes can be used to parse data and return JSON objects:
|
204
|
+
|
205
|
+
```ruby
|
206
|
+
class Bob
|
207
|
+
def initialize(last_name)
|
208
|
+
@last_name = last_name
|
209
|
+
end
|
210
|
+
|
211
|
+
def to_hash
|
212
|
+
{ first_name: "Bob", last_name: @last_name }
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
get "/object" do
|
217
|
+
response do
|
218
|
+
success { object :bob, Bob, "Saget" }
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
# => {"bob":{"first_name":"Bob","last_name":"Saget"}}
|
223
|
+
```
|
224
|
+
|
225
|
+
These can also be used to return arrays of data:
|
226
|
+
|
227
|
+
```ruby
|
228
|
+
get "/array" do
|
229
|
+
response do
|
230
|
+
success { array :bobs, Bob, %w(Ross Marley) }
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
# => {"bobs":[{"first_name":"Bob","last_name":"Ross"},{"first_name":"Bob","last_name":"Marley"}]}
|
235
|
+
```
|
236
|
+
|
237
|
+
### Use request data on subsequent requests
|
238
|
+
|
239
|
+
This is perhaps easiest to explain with an example:
|
240
|
+
|
241
|
+
```ruby
|
242
|
+
get "/multi" do
|
243
|
+
request :one do
|
244
|
+
path "/one"
|
245
|
+
method :get
|
246
|
+
end
|
247
|
+
|
248
|
+
request :two do |data|
|
249
|
+
path "/two"
|
250
|
+
method :get
|
251
|
+
|
252
|
+
query_param :name, data[:one][:name]
|
253
|
+
end
|
254
|
+
|
255
|
+
response do |data|
|
256
|
+
success { attribute :name, data[:two][:result] }
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
get "/one" do
|
261
|
+
response do
|
262
|
+
success { attribute :name, "Bob" }
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
get "/two" do |params|
|
267
|
+
response do
|
268
|
+
success { attribute :result, params[:name] }
|
269
|
+
end
|
270
|
+
end
|
271
|
+
```
|
272
|
+
|
273
|
+
Notably, on this line:
|
274
|
+
|
275
|
+
```ruby
|
276
|
+
request :two do |data|
|
277
|
+
```
|
278
|
+
|
279
|
+
`data` will contain the response data from the first request.
|
280
|
+
|
281
|
+
### Conditional requests
|
282
|
+
|
283
|
+
It can be useful to only send back-end requests under certain conditions:
|
284
|
+
|
285
|
+
```ruby
|
286
|
+
get "/conditional" do |params|
|
287
|
+
request :start_background_job, when: params[:make_it_so] do
|
288
|
+
path "/job"
|
289
|
+
method :post
|
290
|
+
end
|
291
|
+
|
292
|
+
response do
|
293
|
+
success { attribute :result, "OK" }
|
294
|
+
end
|
295
|
+
end
|
296
|
+
```
|
297
|
+
|
298
|
+
### Streaming
|
299
|
+
|
300
|
+
It can be done without a back-end request:
|
301
|
+
|
302
|
+
```ruby
|
303
|
+
get "/stream_no_backend" do
|
304
|
+
stream true
|
305
|
+
|
306
|
+
response do
|
307
|
+
success do
|
308
|
+
stream do
|
309
|
+
(1..9).each { |n| stream_write n }
|
310
|
+
end
|
311
|
+
end
|
312
|
+
end
|
313
|
+
end
|
314
|
+
```
|
315
|
+
|
316
|
+
Things to notice:
|
317
|
+
- Inside the endpoint block, `stream true` is needed
|
318
|
+
- Inside the success block, there's a `stream` block
|
319
|
+
- The `stream` block uses `stream_write` to write the response
|
320
|
+
|
321
|
+
This gets more useful when proxying to a back-end request that is going to return a lot of data:
|
322
|
+
|
323
|
+
```ruby
|
324
|
+
get "/stream_download" do
|
325
|
+
stream true
|
326
|
+
|
327
|
+
request :download do
|
328
|
+
path "/huge_download"
|
329
|
+
method :get
|
330
|
+
end
|
331
|
+
|
332
|
+
response do |data|
|
333
|
+
success do
|
334
|
+
stream do
|
335
|
+
data[:one].stream do |chunk|
|
336
|
+
stream_write chunk
|
337
|
+
end
|
338
|
+
end
|
339
|
+
end
|
340
|
+
end
|
341
|
+
end
|
342
|
+
```
|
343
|
+
|
344
|
+
The `stream do |chunk|` block will receive the data in small chunks as it comes off the socket, so that the entire response body doesn't go into memory.
|
345
|
+
|
346
|
+
## Testing
|
347
|
+
|
348
|
+
```bash
|
349
|
+
$ rake
|
350
|
+
```
|
351
|
+
|
352
|
+
## Contributing
|
353
|
+
|
354
|
+
1. Fork it ( https://github.com/CXInc/api-transformer/fork )
|
355
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
356
|
+
3. Commit your changes (`git commit -am "Add some feature"`)
|
357
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
358
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "api_transformer/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "api-transformer"
|
8
|
+
spec.version = ApiTransformer::VERSION
|
9
|
+
spec.authors = ["Bruz Marzolf"]
|
10
|
+
spec.email = ["bruz@bruzilla.com"]
|
11
|
+
spec.summary = "API transformation Ruby DSL and server"
|
12
|
+
spec.description = ""
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(/^bin\//) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(/^(test|spec|features)\//)
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency "rack", "~> 1.5"
|
22
|
+
spec.add_dependency "goliath", "~> 1.0"
|
23
|
+
spec.add_dependency "em-http-request", "~> 1.1"
|
24
|
+
spec.add_dependency "json", "~> 1.8"
|
25
|
+
spec.add_dependency "hashie", "~> 3.3"
|
26
|
+
|
27
|
+
spec.add_development_dependency "bundler", "~> 1.6"
|
28
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
29
|
+
spec.add_development_dependency "pry", "~> 0.10"
|
30
|
+
spec.add_development_dependency "mocha", "~> 1.1"
|
31
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require_relative '../lib/api_transformer'
|
2
|
+
|
3
|
+
class IpServer < ApiTransformer::Server
|
4
|
+
base_url "http://ip.jsontest.com"
|
5
|
+
|
6
|
+
get "/ip" do
|
7
|
+
request :ip do
|
8
|
+
path "/"
|
9
|
+
method :get
|
10
|
+
end
|
11
|
+
|
12
|
+
response do |data|
|
13
|
+
success do
|
14
|
+
status 200
|
15
|
+
attribute :your_ip, data[:ip][:ip]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require_relative "../api_transformer"
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require "em-synchrony/em-http"
|
2
|
+
|
3
|
+
module ApiTransformer
|
4
|
+
# Process request blocks
|
5
|
+
class BackendRequest
|
6
|
+
attr_reader :name
|
7
|
+
attr_accessor :path, :method, :query_params, :form_params, :json_params,
|
8
|
+
:cookie_params
|
9
|
+
|
10
|
+
def initialize(name, base_url, frontend_headers)
|
11
|
+
@name = name
|
12
|
+
@base_url = base_url
|
13
|
+
@frontend_headers = frontend_headers
|
14
|
+
|
15
|
+
@query_params = {}
|
16
|
+
@form_params = {}
|
17
|
+
@json_params = {}
|
18
|
+
@cookie_params = {}
|
19
|
+
end
|
20
|
+
|
21
|
+
def send
|
22
|
+
url = @base_url + @path
|
23
|
+
|
24
|
+
EM::HttpRequest.new(url).send(
|
25
|
+
"a#{@method}",
|
26
|
+
query: @query_params,
|
27
|
+
body: body,
|
28
|
+
head: headers
|
29
|
+
)
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def body
|
35
|
+
case [@form_params.any?, @json_params.any?]
|
36
|
+
when [true, true]
|
37
|
+
fail RequestError, "A request cannot have both json and form parameters"
|
38
|
+
when [true, false]
|
39
|
+
@form_params
|
40
|
+
when [false, true]
|
41
|
+
@json_params.to_json
|
42
|
+
when [false, false]
|
43
|
+
nil
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def headers
|
48
|
+
ret = [stripped_frontend_headers, content_type, cookies].reduce(&:merge)
|
49
|
+
ret.delete("Host")
|
50
|
+
ret
|
51
|
+
end
|
52
|
+
|
53
|
+
def stripped_frontend_headers
|
54
|
+
@frontend_headers.reject { |key, _| key == "Content-Length" }
|
55
|
+
end
|
56
|
+
|
57
|
+
def content_type
|
58
|
+
if @json_params.any?
|
59
|
+
{ "Content-Type" => "application/json" }
|
60
|
+
elsif @form_params.any?
|
61
|
+
{ "Content-Type" => "application/x-www-form-urlencoded" }
|
62
|
+
else
|
63
|
+
{}
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def cookies
|
68
|
+
if @cookie_params.any?
|
69
|
+
cookie_string = @cookie_params
|
70
|
+
.map { |key, value| "#{key}=#{value};" }
|
71
|
+
.join(" ")
|
72
|
+
|
73
|
+
{ "Cookie" => cookie_string }
|
74
|
+
else
|
75
|
+
{}
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module ApiTransformer
|
2
|
+
# Processes the request block
|
3
|
+
class BackendRequestSender
|
4
|
+
def initialize(name, options, block, frontend_headers, helper_blocks)
|
5
|
+
@backend_request = BackendRequest.new(
|
6
|
+
name,
|
7
|
+
options[:base_url],
|
8
|
+
frontend_headers
|
9
|
+
)
|
10
|
+
|
11
|
+
@block = block
|
12
|
+
@helper_blocks = helper_blocks
|
13
|
+
end
|
14
|
+
|
15
|
+
def send(backend_responses)
|
16
|
+
@helper_blocks.each { |block| instance_eval(&block) }
|
17
|
+
instance_exec(backend_responses, &@block)
|
18
|
+
|
19
|
+
unless @backend_request.method
|
20
|
+
fail RequestError, "Missing method for backend request: #{request_name}"
|
21
|
+
end
|
22
|
+
|
23
|
+
@backend_request.send
|
24
|
+
end
|
25
|
+
|
26
|
+
def request_name
|
27
|
+
@backend_request.name
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def path(value)
|
33
|
+
@backend_request.path = value
|
34
|
+
end
|
35
|
+
|
36
|
+
def method(value)
|
37
|
+
@backend_request.method = value
|
38
|
+
end
|
39
|
+
|
40
|
+
def query_param(key, value)
|
41
|
+
@backend_request.query_params[key] = value
|
42
|
+
end
|
43
|
+
|
44
|
+
def form_param(key, value)
|
45
|
+
@backend_request.form_params[key] = value
|
46
|
+
end
|
47
|
+
|
48
|
+
def json_param(key, value)
|
49
|
+
@backend_request.json_params[key] = value
|
50
|
+
end
|
51
|
+
|
52
|
+
def cookie_param(key, value)
|
53
|
+
@backend_request.cookie_params[key] = value
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|