ibsciss-middleware 0.3.2 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -1
- data/README.md +57 -10
- data/Rakefile +3 -3
- data/lib/middleware.rb +2 -2
- data/lib/middleware/builder.rb +27 -15
- data/lib/middleware/logger.rb +49 -0
- data/lib/middleware/runner.rb +2 -2
- data/middleware.gemspec +14 -14
- data/spec/middleware/builder_spec.rb +78 -44
- data/spec/middleware/logger_spec.rb +58 -0
- data/spec/middleware/runner_spec.rb +56 -48
- data/spec/spec_helper.rb +45 -47
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 45a7f568a5dd19fa3ed4060972af8eab369d6cc7
|
4
|
+
data.tar.gz: 9324a50e02d47da8f6a4232db2d0f373dda717f5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cc1c0601887f79ce0580705cf7031124315cc25109703765f1b92e66147c8c2ef79b2ee9ffca951ff7bb4ef739bebdf8d21f3ec226fab2630852fa073be45204
|
7
|
+
data.tar.gz: ad2c8c9a03d3da09664e879322906b405423e0fdb8cd801da3fab30c0cfba90ea0529aeeea330a5c1bb4ff28d4922b20f0b61249ab1c7ab57d6d5c161a9dcd94
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,14 @@
|
|
1
|
+
## 0.4.0
|
2
|
+
- Add a name displayed in the logger & inspect methods
|
3
|
+
- Add a logger middleware
|
4
|
+
- Fixed rubocop offenses
|
5
|
+
- Fix builder#inspect to display class name
|
6
|
+
|
1
7
|
## 0.3.2
|
2
|
-
- Add CI
|
8
|
+
- Add CI, Code Climate, Gitter & Improve documentation
|
9
|
+
- Add `insert_after_each` and `insert_before_each` methods
|
10
|
+
- Improve the `inspect` method to a more readable version
|
11
|
+
- Enable lambda to receive additional arguments
|
3
12
|
|
4
13
|
## 0.3.1
|
5
14
|
- Enable lambda to change the given object
|
data/README.md
CHANGED
@@ -140,18 +140,17 @@ A basic description of the two methods that a middleware must implement:
|
|
140
140
|
state sent in (defined by the caller, but usually a Hash). This call should also
|
141
141
|
call `app.call(env)` at some point to move on.
|
142
142
|
|
143
|
-
This architecture offers the biggest advantage of letting you enhance the env variable before passing it to the next middleware,
|
144
|
-
and giving you the abilities to change the returned datas, as follow:
|
143
|
+
This architecture offers the biggest advantage of letting you enhance the `env` variable before passing it to the next middleware, and giving you the ability to change the returned data, as follows:
|
145
144
|
|
146
145
|
```ruby
|
147
146
|
class Greeting
|
148
|
-
def initialize(app,
|
147
|
+
def initialize(app, datas = nil)
|
149
148
|
@app = app
|
150
149
|
@datas = datas
|
151
150
|
end
|
152
151
|
|
153
152
|
def call(env)
|
154
|
-
env = "#{
|
153
|
+
env = "#{@datas} #{env}"
|
155
154
|
result = @app(env)
|
156
155
|
"#{result} !"
|
157
156
|
end
|
@@ -205,6 +204,12 @@ end.call()
|
|
205
204
|
The call method takes an optional parameter which is the state to pass into the
|
206
205
|
initial middleware.
|
207
206
|
|
207
|
+
You can optionally set a name, that will be displayed in inspect and for logging purpose, for the current middleware:
|
208
|
+
|
209
|
+
```ruby
|
210
|
+
Middleware::Builder.new(name: 'MyPersonalMiddleware')
|
211
|
+
```
|
212
|
+
|
208
213
|
### Manipulating a Stack
|
209
214
|
|
210
215
|
Stacks also provide a set of methods for manipulating the middleware stack. This
|
@@ -254,7 +259,7 @@ stack.insert_before_each logger
|
|
254
259
|
#### Replace
|
255
260
|
|
256
261
|
```ruby
|
257
|
-
# Replace the
|
262
|
+
# Replace the second middleware
|
258
263
|
stack.replace(1, SomeOtherMiddleware)
|
259
264
|
|
260
265
|
# Replace the Trace middleware
|
@@ -264,7 +269,7 @@ stack.replace(Trace, SomeOtherMiddleware)
|
|
264
269
|
#### Delete
|
265
270
|
|
266
271
|
```ruby
|
267
|
-
# Delete the
|
272
|
+
# Delete the second middleware
|
268
273
|
stack.delete(1)
|
269
274
|
|
270
275
|
# Delete the Trace middleware
|
@@ -304,7 +309,7 @@ Note that you can also pass blocks in using the `use` method.
|
|
304
309
|
|
305
310
|
#### Lambda
|
306
311
|
|
307
|
-
Lambda work the same with additional arguments:
|
312
|
+
Lambda work the same, with additional arguments:
|
308
313
|
|
309
314
|
```ruby
|
310
315
|
Middleware::Builder.new { |b|
|
@@ -324,8 +329,50 @@ Middleware::Builder.new { |b|
|
|
324
329
|
}.inspect
|
325
330
|
```
|
326
331
|
|
327
|
-
|
332
|
+
It will output:
|
333
|
+
|
334
|
+
```ruby
|
335
|
+
Middleware[Trace(), Echo("Hello, World!")]
|
336
|
+
```
|
337
|
+
|
338
|
+
_If you have set a name, it will be displayed instead of `Middleware`_.
|
339
|
+
|
340
|
+
#### Logging
|
341
|
+
|
342
|
+
A built-in logging mechanism is provided, it will output for each provider of the stack:
|
343
|
+
|
344
|
+
- The provided arguments
|
345
|
+
- The returned values (the first 255 chars) and the time (in milliseconds) elapsed in the call method
|
346
|
+
|
347
|
+
To initialize the logging you must provide a valid logger instance to `#inject_logger`.
|
348
|
+
|
349
|
+
It is also recommended to give a name to your middleware stack.
|
328
350
|
|
329
351
|
```ruby
|
330
|
-
|
331
|
-
|
352
|
+
require 'logger'
|
353
|
+
|
354
|
+
class UpperCaseMiddleware
|
355
|
+
def initialize app
|
356
|
+
@app = app
|
357
|
+
end
|
358
|
+
|
359
|
+
def call env
|
360
|
+
sleep(1)
|
361
|
+
env.upcase
|
362
|
+
end
|
363
|
+
end
|
364
|
+
|
365
|
+
# Build the middleware:
|
366
|
+
Middleware::Builder.new(name: 'MyMiddleware') { |b|
|
367
|
+
b.use UpperCaseMiddleware
|
368
|
+
}.inject_logger(Logger.new(STDOUT)).call('a message')
|
369
|
+
```
|
370
|
+
|
371
|
+
It will output something like:
|
372
|
+
|
373
|
+
```
|
374
|
+
INFO -- MyMiddleware: UpperCaseMiddleware has been called with: "a message"
|
375
|
+
INFO -- MyMiddleware: UpperCaseMiddleware finished in 1001 ms and returned: "A MESSAGE"
|
376
|
+
```
|
377
|
+
|
378
|
+
_Note: the provided logger instance must respond to `#call(level severity, message, app name)`_
|
data/Rakefile
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
#!/usr/bin/env rake
|
2
|
-
require
|
3
|
-
require
|
2
|
+
require 'bundler/gem_tasks'
|
3
|
+
require 'rspec/core/rake_task'
|
4
4
|
|
5
5
|
# RSpec test task
|
6
6
|
RSpec::Core::RakeTask.new
|
7
7
|
|
8
8
|
# Make sure the default is to run RSpec
|
9
|
-
task :
|
9
|
+
task default: 'spec'
|
data/lib/middleware.rb
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require 'middleware/builder'
|
2
|
+
require 'middleware/runner'
|
data/lib/middleware/builder.rb
CHANGED
@@ -17,6 +17,7 @@ module Middleware
|
|
17
17
|
# app.call(7)
|
18
18
|
#
|
19
19
|
class Builder
|
20
|
+
|
20
21
|
# Initializes the builder. An optional block can be passed which
|
21
22
|
# will either yield the builder or be evaluated in the context of the instance.
|
22
23
|
#
|
@@ -37,9 +38,10 @@ module Middleware
|
|
37
38
|
# in which knows how to run them.
|
38
39
|
# @yield [] Evaluated in this instance which allows you to use methods
|
39
40
|
# like {#use} and such.
|
40
|
-
def initialize(opts=nil, &block)
|
41
|
+
def initialize(opts = nil, &block)
|
41
42
|
opts ||= {}
|
42
43
|
@runner_class = opts[:runner_class] || Runner
|
44
|
+
@middleware_name = opts[:name] || 'Middleware'
|
43
45
|
|
44
46
|
if block_given?
|
45
47
|
if block.arity == 1
|
@@ -50,12 +52,17 @@ module Middleware
|
|
50
52
|
end
|
51
53
|
end
|
52
54
|
|
55
|
+
# Returns the name of the current middleware
|
56
|
+
def name
|
57
|
+
@middleware_name
|
58
|
+
end
|
59
|
+
|
53
60
|
# Returns a mergeable version of the builder. If `use` is called with
|
54
61
|
# the return value of this method, then the stack will merge, instead
|
55
62
|
# of being treated as a separate single middleware.
|
56
63
|
def flatten
|
57
64
|
lambda do |env|
|
58
|
-
|
65
|
+
call(env)
|
59
66
|
end
|
60
67
|
end
|
61
68
|
|
@@ -65,11 +72,11 @@ module Middleware
|
|
65
72
|
#
|
66
73
|
# @param [Class] middleware The middleware class
|
67
74
|
def use(middleware, *args, &block)
|
68
|
-
if middleware.
|
75
|
+
if middleware.is_a?(Builder)
|
69
76
|
# Merge in the other builder's stack into our own
|
70
|
-
|
77
|
+
stack.concat(middleware.stack)
|
71
78
|
else
|
72
|
-
|
79
|
+
stack << [middleware, args, block]
|
73
80
|
end
|
74
81
|
|
75
82
|
self
|
@@ -79,7 +86,7 @@ module Middleware
|
|
79
86
|
# given middleware object.
|
80
87
|
def insert(index, middleware, *args, &block)
|
81
88
|
index = self.index(index) unless index.is_a?(Integer)
|
82
|
-
|
89
|
+
fail "no such middleware to insert before: #{index.inspect}" unless index
|
83
90
|
stack.insert(index, [middleware, args, block])
|
84
91
|
end
|
85
92
|
|
@@ -88,7 +95,7 @@ module Middleware
|
|
88
95
|
# Inserts a middleware after the given index or middleware object.
|
89
96
|
def insert_after(index, middleware, *args, &block)
|
90
97
|
index = self.index(index) unless index.is_a?(Integer)
|
91
|
-
|
98
|
+
fail "no such middleware to insert after: #{index.inspect}" unless index
|
92
99
|
insert(index + 1, middleware, *args, &block)
|
93
100
|
end
|
94
101
|
|
@@ -125,14 +132,22 @@ module Middleware
|
|
125
132
|
end
|
126
133
|
|
127
134
|
# Runs the builder stack with the given environment.
|
128
|
-
def call(env=nil)
|
135
|
+
def call(env = nil)
|
129
136
|
to_app.call(env)
|
130
137
|
end
|
131
138
|
|
132
139
|
def inspect
|
133
|
-
|
134
|
-
|
135
|
-
|
140
|
+
name+'[' + stack.reduce([]) do |carry, middleware|
|
141
|
+
name = middleware[0].is_a?(Proc) ? 'Proc' : middleware[0].name
|
142
|
+
|
143
|
+
carry << "#{name}(#{middleware[1].join(', ')})"
|
144
|
+
end.join(', ') + ']'
|
145
|
+
end
|
146
|
+
|
147
|
+
def inject_logger logger
|
148
|
+
insert_before_each Middleware::Logger, logger, name
|
149
|
+
|
150
|
+
self
|
136
151
|
end
|
137
152
|
|
138
153
|
protected
|
@@ -160,9 +175,7 @@ module Middleware
|
|
160
175
|
# you shouldn't use this method
|
161
176
|
#
|
162
177
|
# @return [Array]
|
163
|
-
|
164
|
-
@stack = stack
|
165
|
-
end
|
178
|
+
attr_writer :stack
|
166
179
|
|
167
180
|
# Converts the builder stack to a runnable action sequence.
|
168
181
|
#
|
@@ -170,6 +183,5 @@ module Middleware
|
|
170
183
|
def to_app
|
171
184
|
@runner_class.new(stack.dup)
|
172
185
|
end
|
173
|
-
|
174
186
|
end
|
175
187
|
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'logger'
|
2
|
+
require 'pp'
|
3
|
+
|
4
|
+
module Middleware
|
5
|
+
|
6
|
+
class Logger
|
7
|
+
def initialize app, logger, name = nil
|
8
|
+
@app = app
|
9
|
+
@write_to = logger
|
10
|
+
@middleware_name = name
|
11
|
+
end
|
12
|
+
|
13
|
+
def call env
|
14
|
+
write(
|
15
|
+
way_in_message(
|
16
|
+
next_middleware_name, env
|
17
|
+
))
|
18
|
+
|
19
|
+
time = Time.now
|
20
|
+
|
21
|
+
@app.call(env).tap { |env|
|
22
|
+
write(
|
23
|
+
way_out_message(
|
24
|
+
next_middleware_name, (Time.now - time) * 1000.0, env
|
25
|
+
))
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
29
|
+
def next_middleware_name
|
30
|
+
@app.class.name
|
31
|
+
end
|
32
|
+
|
33
|
+
def pretty_print item
|
34
|
+
->(out){ PP.pp(item, out) }.('')
|
35
|
+
end
|
36
|
+
|
37
|
+
def way_in_message name, env
|
38
|
+
' %s has been called with: %s' % [name, pretty_print(env)]
|
39
|
+
end
|
40
|
+
|
41
|
+
def way_out_message name, time, value
|
42
|
+
' %s finished in %.0f ms and returned: %s' % [name, time, pretty_print(value)]
|
43
|
+
end
|
44
|
+
|
45
|
+
def write msg
|
46
|
+
@write_to.add(::Logger::INFO, msg.slice(0, 255).strip!, @middleware_name)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/lib/middleware/runner.rb
CHANGED
@@ -4,7 +4,7 @@ module Middleware
|
|
4
4
|
# in order, then reversing the order.
|
5
5
|
class Runner
|
6
6
|
# A middleware which does nothing
|
7
|
-
EMPTY_MIDDLEWARE =
|
7
|
+
EMPTY_MIDDLEWARE = ->(env) { env }
|
8
8
|
|
9
9
|
# Build a new middleware runner with the given middleware
|
10
10
|
# stack.
|
@@ -60,7 +60,7 @@ module Middleware
|
|
60
60
|
next_middleware.call(klass.call(env, *args))
|
61
61
|
end
|
62
62
|
else
|
63
|
-
|
63
|
+
fail "Invalid middleware, doesn't respond to `call`: #{klass.inspect}"
|
64
64
|
end
|
65
65
|
end
|
66
66
|
end
|
data/middleware.gemspec
CHANGED
@@ -1,23 +1,23 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
|
3
3
|
Gem::Specification.new do |gem|
|
4
|
-
gem.authors = [
|
5
|
-
gem.email = [
|
6
|
-
gem.description =
|
7
|
-
gem.summary =
|
8
|
-
gem.homepage =
|
9
|
-
gem.license =
|
4
|
+
gem.authors = ['Mitchell Hashimoto', 'Arnaud Lemaire']
|
5
|
+
gem.email = ['mitchell.hashimoto@gmail.com', 'alemaire@ibsciss.com']
|
6
|
+
gem.description = 'Generalized implementation of the rack middleware abstraction for Ruby.'
|
7
|
+
gem.summary = 'Generalized implementation of the rack middleware abstraction for Ruby (chain of responsibility design pattern).'
|
8
|
+
gem.homepage = 'https://github.com/ibsciss/ruby-middleware'
|
9
|
+
gem.license = 'MIT'
|
10
10
|
|
11
|
-
gem.add_development_dependency
|
12
|
-
gem.add_development_dependency
|
13
|
-
gem.add_development_dependency
|
14
|
-
gem.add_development_dependency
|
11
|
+
gem.add_development_dependency 'rake', '~> 10.4.2'
|
12
|
+
gem.add_development_dependency 'rspec-core', '~> 3.2'
|
13
|
+
gem.add_development_dependency 'rspec-expectations', '~> 3.2'
|
14
|
+
gem.add_development_dependency 'rspec-mocks', '~> 3.2'
|
15
15
|
gem.add_development_dependency 'codeclimate-test-reporter', '~> 0.4.7'
|
16
16
|
|
17
|
-
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
17
|
+
gem.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
18
18
|
gem.files = `git ls-files`.split("\n")
|
19
19
|
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
20
|
-
gem.name =
|
21
|
-
gem.require_paths = [
|
22
|
-
gem.version = '0.
|
20
|
+
gem.name = 'ibsciss-middleware'
|
21
|
+
gem.require_paths = ['lib']
|
22
|
+
gem.version = '0.4.0'
|
23
23
|
end
|
@@ -1,20 +1,20 @@
|
|
1
|
-
require
|
1
|
+
require 'middleware'
|
2
2
|
|
3
3
|
describe Middleware::Builder do
|
4
|
-
let(:data) { { :
|
4
|
+
let(:data) { { data: [] } }
|
5
5
|
let(:instance) { described_class.new }
|
6
6
|
|
7
7
|
# This returns a proc that can be used with the builder
|
8
8
|
# that simply appends data to an array in the env.
|
9
9
|
def appender_proc(data)
|
10
|
-
|
10
|
+
proc { |obj| obj.tap { |env| env[:data] << data } }
|
11
11
|
end
|
12
12
|
|
13
|
-
context
|
14
|
-
context
|
15
|
-
it
|
13
|
+
context 'initialized with a block' do
|
14
|
+
context 'without explicit receiver' do
|
15
|
+
it 'instance evals the block' do
|
16
16
|
data = {}
|
17
|
-
proc =
|
17
|
+
proc = proc { |env| env[:data] = true }
|
18
18
|
|
19
19
|
app = described_class.new do
|
20
20
|
use proc
|
@@ -26,10 +26,10 @@ describe Middleware::Builder do
|
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
|
-
context
|
30
|
-
it
|
29
|
+
context 'with explicit receiver' do
|
30
|
+
it 'yields self to the block' do
|
31
31
|
data = {}
|
32
|
-
proc =
|
32
|
+
proc = proc { |env| env[:data] = true }
|
33
33
|
|
34
34
|
app = described_class.new do |b|
|
35
35
|
b.use proc
|
@@ -42,10 +42,10 @@ describe Middleware::Builder do
|
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
45
|
-
context
|
46
|
-
it
|
45
|
+
context 'basic `use`' do
|
46
|
+
it 'should add items to the stack and make them callable' do
|
47
47
|
data = {}
|
48
|
-
proc =
|
48
|
+
proc = proc { |env| env[:data] = true }
|
49
49
|
|
50
50
|
instance.use proc
|
51
51
|
instance.call(data)
|
@@ -53,10 +53,10 @@ describe Middleware::Builder do
|
|
53
53
|
expect(data[:data]).to be_truthy
|
54
54
|
end
|
55
55
|
|
56
|
-
it
|
56
|
+
it 'should be able to add multiple items' do
|
57
57
|
data = {}
|
58
|
-
proc1 =
|
59
|
-
proc2 =
|
58
|
+
proc1 = proc { |env| env.tap { |obj| obj[:one] = true } }
|
59
|
+
proc2 = proc { |env| env.tap { |obj| obj[:two] = true } }
|
60
60
|
|
61
61
|
instance.use proc1
|
62
62
|
instance.use proc2
|
@@ -66,16 +66,16 @@ describe Middleware::Builder do
|
|
66
66
|
expect(data[:two]).to be_truthy
|
67
67
|
end
|
68
68
|
|
69
|
-
it
|
69
|
+
it 'should be able to add another builder' do
|
70
70
|
data = {}
|
71
|
-
proc1 =
|
71
|
+
proc1 = proc { |env| env[:one] = true }
|
72
72
|
|
73
73
|
# Build the first builder
|
74
74
|
one = described_class.new
|
75
75
|
one.use proc1
|
76
76
|
|
77
77
|
# Add it to this builder
|
78
|
-
two
|
78
|
+
two = described_class.new
|
79
79
|
two.use one
|
80
80
|
|
81
81
|
# Call the 2nd and verify results
|
@@ -83,19 +83,19 @@ describe Middleware::Builder do
|
|
83
83
|
expect(data[:one]).to be_truthy
|
84
84
|
end
|
85
85
|
|
86
|
-
it
|
86
|
+
it 'should default the env to `nil` if not given' do
|
87
87
|
result = false
|
88
|
-
proc =
|
88
|
+
proc = proc { |env| result = env.nil? }
|
89
89
|
|
90
90
|
instance.use proc
|
91
91
|
instance.call
|
92
92
|
|
93
93
|
expect(result).to be_truthy
|
94
|
-
|
94
|
+
end
|
95
95
|
end
|
96
96
|
|
97
|
-
context
|
98
|
-
it
|
97
|
+
context 'inserting' do
|
98
|
+
it 'can insert at an index' do
|
99
99
|
instance.use appender_proc(1)
|
100
100
|
instance.insert(0, appender_proc(2))
|
101
101
|
instance.call(data)
|
@@ -103,7 +103,7 @@ describe Middleware::Builder do
|
|
103
103
|
expect(data[:data]).to eq [2, 1]
|
104
104
|
end
|
105
105
|
|
106
|
-
it
|
106
|
+
it 'can insert next to a previous object' do
|
107
107
|
proc2 = appender_proc(2)
|
108
108
|
instance.use appender_proc(1)
|
109
109
|
instance.use proc2
|
@@ -113,7 +113,7 @@ describe Middleware::Builder do
|
|
113
113
|
expect(data[:data]).to eq [1, 3, 2]
|
114
114
|
end
|
115
115
|
|
116
|
-
it
|
116
|
+
it 'can insert before' do
|
117
117
|
instance.use appender_proc(1)
|
118
118
|
instance.insert_before 0, appender_proc(2)
|
119
119
|
instance.call(data)
|
@@ -121,12 +121,12 @@ describe Middleware::Builder do
|
|
121
121
|
expect(data[:data]).to eq [2, 1]
|
122
122
|
end
|
123
123
|
|
124
|
-
it
|
125
|
-
expect { instance.insert
|
126
|
-
to raise_error(RuntimeError)
|
124
|
+
it 'raises an exception if attempting to insert before an invalid object' do
|
125
|
+
expect { instance.insert 'object', appender_proc(1) }
|
126
|
+
.to raise_error(RuntimeError)
|
127
127
|
end
|
128
128
|
|
129
|
-
it
|
129
|
+
it 'can insert after each' do
|
130
130
|
instance.use appender_proc(1)
|
131
131
|
instance.use appender_proc(2)
|
132
132
|
instance.use appender_proc(3)
|
@@ -135,7 +135,7 @@ describe Middleware::Builder do
|
|
135
135
|
expect(data[:data]).to eq [1, 9, 2, 9, 3, 9]
|
136
136
|
end
|
137
137
|
|
138
|
-
it
|
138
|
+
it 'can insert before each' do
|
139
139
|
instance.use appender_proc(1)
|
140
140
|
instance.use appender_proc(2)
|
141
141
|
instance.use appender_proc(3)
|
@@ -144,14 +144,14 @@ describe Middleware::Builder do
|
|
144
144
|
expect(data[:data]).to eq [9, 1, 9, 2, 9, 3]
|
145
145
|
end
|
146
146
|
|
147
|
-
it
|
148
|
-
expect { instance.insert_after
|
149
|
-
to raise_error(RuntimeError)
|
147
|
+
it 'raises an exception if attempting to insert after an invalid object' do
|
148
|
+
expect { instance.insert_after 'object', appender_proc(1) }
|
149
|
+
.to raise_error(RuntimeError)
|
150
150
|
end
|
151
151
|
end
|
152
152
|
|
153
|
-
context
|
154
|
-
it
|
153
|
+
context 'replace' do
|
154
|
+
it 'can replace an object' do
|
155
155
|
proc1 = appender_proc(1)
|
156
156
|
proc2 = appender_proc(2)
|
157
157
|
|
@@ -162,7 +162,7 @@ describe Middleware::Builder do
|
|
162
162
|
expect(data[:data]).to eq [2]
|
163
163
|
end
|
164
164
|
|
165
|
-
it
|
165
|
+
it 'can replace by index' do
|
166
166
|
proc1 = appender_proc(1)
|
167
167
|
proc2 = appender_proc(2)
|
168
168
|
|
@@ -174,8 +174,8 @@ describe Middleware::Builder do
|
|
174
174
|
end
|
175
175
|
end
|
176
176
|
|
177
|
-
context
|
178
|
-
it
|
177
|
+
context 'deleting' do
|
178
|
+
it 'can delete by object' do
|
179
179
|
proc1 = appender_proc(1)
|
180
180
|
|
181
181
|
instance.use proc1
|
@@ -186,7 +186,7 @@ describe Middleware::Builder do
|
|
186
186
|
expect(data[:data]).to eq [2]
|
187
187
|
end
|
188
188
|
|
189
|
-
it
|
189
|
+
it 'can delete by index' do
|
190
190
|
proc1 = appender_proc(1)
|
191
191
|
|
192
192
|
instance.use proc1
|
@@ -198,11 +198,45 @@ describe Middleware::Builder do
|
|
198
198
|
end
|
199
199
|
end
|
200
200
|
|
201
|
-
context
|
202
|
-
|
201
|
+
context 'debugging' do
|
202
|
+
class Echo
|
203
|
+
def initialize app
|
204
|
+
@app = app
|
205
|
+
end
|
206
|
+
|
207
|
+
def call env
|
208
|
+
@app.call(env)
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
it 'has an inspect method' do
|
203
213
|
instance.use appender_proc(1)
|
204
214
|
instance.use appender_proc(1), 2
|
205
|
-
|
215
|
+
instance.use Echo, 'Hi, how are you?'
|
216
|
+
expect(instance.inspect).to eq 'Middleware[Proc(), Proc(2), Echo(Hi, how are you?)]'
|
217
|
+
end
|
218
|
+
|
219
|
+
it 'displays his name in the inspect' do
|
220
|
+
middleware = described_class.new(name: 'Dumb') { |b|
|
221
|
+
b.use appender_proc(1)
|
222
|
+
}
|
223
|
+
expect(middleware.inspect).to eq 'Dumb[Proc()]'
|
224
|
+
end
|
225
|
+
|
226
|
+
it "can have a name" do
|
227
|
+
expect(described_class.new(name: 'Name').name).to eq 'Name'
|
228
|
+
end
|
229
|
+
|
230
|
+
it "can have a Logger" do
|
231
|
+
mocked_logger = instance_double(Logger)
|
232
|
+
expect(mocked_logger).to receive(:add).exactly(4).times
|
233
|
+
|
234
|
+
described_class.new(name: 'Dumb') { |b|
|
235
|
+
b.use Echo
|
236
|
+
b.use Echo
|
237
|
+
}.inject_logger(mocked_logger)
|
238
|
+
.call()
|
206
239
|
end
|
207
240
|
end
|
208
|
-
|
241
|
+
|
242
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require_relative '../../lib/middleware/logger'
|
2
|
+
require 'logger'
|
3
|
+
|
4
|
+
class NEXT_Middleware
|
5
|
+
def initialize app
|
6
|
+
@app = app
|
7
|
+
end
|
8
|
+
|
9
|
+
def call env
|
10
|
+
env
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
#Middleware.new('tchoutchou_orchestrator') {
|
15
|
+
#}.inject_logger(Logger.new IO::String(''))
|
16
|
+
|
17
|
+
describe Middleware::Logger do
|
18
|
+
|
19
|
+
it 'wrote the names of the next middleware in the logger' do
|
20
|
+
mocked_logger = instance_double('Logger');
|
21
|
+
expect(mocked_logger).to receive(:add).twice
|
22
|
+
|
23
|
+
described_class.new(NEXT_Middleware.new(nil), mocked_logger, 'dump_middleware').call(1)
|
24
|
+
end
|
25
|
+
|
26
|
+
describe '#next_middleware_name' do
|
27
|
+
context 'when the next middleware is a Class' do
|
28
|
+
it 'extracts the next middleware name from the class name' do
|
29
|
+
expect(described_class.new(NEXT_Middleware.new(nil), nil).next_middleware_name).to eq 'NEXT_Middleware'
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context 'when the next middleware is a Lambda' do
|
34
|
+
it 'gives "Proc" for the next middleware' do
|
35
|
+
expect(described_class.new(->(env){env}, nil).next_middleware_name).to eq 'Proc'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe '#way_out_message' do
|
41
|
+
it 'returns a formatted message' do
|
42
|
+
expect(described_class.new(nil, nil).way_out_message('Dumb', 2400, [1, 2])).to eq " Dumb finished in 2400 ms and returned: [1, 2]\n"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe '#way_in_message' do
|
47
|
+
it 'returns a formatted message' do
|
48
|
+
expect(described_class.new(nil, nil).way_in_message('Dumb', [1, 2])).to eq " Dumb has been called with: [1, 2]\n"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe '#pretty_print' do
|
53
|
+
it 'pretty prints given var' do
|
54
|
+
expect(described_class.new(nil, nil).pretty_print([1, 2, 3, 4, 5])).to eq "[1, 2, 3, 4, 5]\n"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
@@ -1,21 +1,21 @@
|
|
1
|
-
require
|
1
|
+
require 'middleware'
|
2
2
|
|
3
3
|
describe Middleware::Runner do
|
4
|
-
it
|
4
|
+
it 'should work with an empty stack' do
|
5
5
|
instance = described_class.new([])
|
6
6
|
expect { instance.call({}) }.to_not raise_error
|
7
7
|
end
|
8
8
|
|
9
|
-
it
|
9
|
+
it 'should call classes in the proper order' do
|
10
10
|
a = Class.new do
|
11
11
|
def initialize(app)
|
12
12
|
@app = app
|
13
13
|
end
|
14
14
|
|
15
15
|
def call(env)
|
16
|
-
env[:result] <<
|
16
|
+
env[:result] << 'A'
|
17
17
|
@app.call(env)
|
18
|
-
env[:result] <<
|
18
|
+
env[:result] << 'A'
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
@@ -25,40 +25,40 @@ describe Middleware::Runner do
|
|
25
25
|
end
|
26
26
|
|
27
27
|
def call(env)
|
28
|
-
env[:result] <<
|
28
|
+
env[:result] << 'B'
|
29
29
|
@app.call(env)
|
30
|
-
env[:result] <<
|
30
|
+
env[:result] << 'B'
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
|
-
env = { :
|
34
|
+
env = { result: [] }
|
35
35
|
instance = described_class.new([a, b])
|
36
36
|
instance.call(env)
|
37
|
-
expect(env[:result]).to eq
|
37
|
+
expect(env[:result]).to eq %w(A B B A)
|
38
38
|
end
|
39
39
|
|
40
|
-
it
|
40
|
+
it 'should call lambdas in the proper order' do
|
41
41
|
data = []
|
42
|
-
a =
|
43
|
-
b =
|
42
|
+
a = ->(_env) { data << 'A' }
|
43
|
+
b = ->(_env) { data << 'B' }
|
44
44
|
|
45
45
|
instance = described_class.new([a, b])
|
46
46
|
instance.call({})
|
47
47
|
|
48
|
-
expect(data).to eq
|
48
|
+
expect(data).to eq %w(A B)
|
49
49
|
end
|
50
50
|
|
51
|
-
it
|
52
|
-
a =
|
53
|
-
b =
|
51
|
+
it 'should let lambdas to change the given argument' do
|
52
|
+
a = ->(env) { env + 1 }
|
53
|
+
b = ->(env) { env + 2 }
|
54
54
|
|
55
55
|
instance = described_class.new([a, b])
|
56
56
|
expect(instance.call(1)).to eq 4
|
57
57
|
end
|
58
58
|
|
59
|
-
it
|
59
|
+
it 'passes in arguments to lambda if given' do
|
60
60
|
data = []
|
61
|
-
a =
|
61
|
+
a = ->(_env, arg) { data << arg }
|
62
62
|
|
63
63
|
instance = described_class.new([[a, 1]])
|
64
64
|
instance.call(nil)
|
@@ -66,7 +66,7 @@ describe Middleware::Runner do
|
|
66
66
|
expect(data).to eq [1]
|
67
67
|
end
|
68
68
|
|
69
|
-
it
|
69
|
+
it 'passes in arguments if given' do
|
70
70
|
a = Class.new do
|
71
71
|
def initialize(app, value)
|
72
72
|
@app = app
|
@@ -85,9 +85,9 @@ describe Middleware::Runner do
|
|
85
85
|
expect(env[:result]).to eq 42
|
86
86
|
end
|
87
87
|
|
88
|
-
it
|
88
|
+
it 'passes in a block if given' do
|
89
89
|
a = Class.new do
|
90
|
-
def initialize(
|
90
|
+
def initialize(_app, &block)
|
91
91
|
@block = block
|
92
92
|
end
|
93
93
|
|
@@ -96,7 +96,7 @@ describe Middleware::Runner do
|
|
96
96
|
end
|
97
97
|
end
|
98
98
|
|
99
|
-
block =
|
99
|
+
block = proc { 42 }
|
100
100
|
env = {}
|
101
101
|
instance = described_class.new([[a, nil, block]])
|
102
102
|
instance.call(env)
|
@@ -104,7 +104,7 @@ describe Middleware::Runner do
|
|
104
104
|
expect(env[:result]).to eq 42
|
105
105
|
end
|
106
106
|
|
107
|
-
it
|
107
|
+
it 'should raise an error if an invalid middleware is given' do
|
108
108
|
expect { described_class.new([27]) }.to raise_error(/Invalid middleware/)
|
109
109
|
end
|
110
110
|
|
@@ -112,24 +112,26 @@ describe Middleware::Runner do
|
|
112
112
|
# A does not call B, so B should never execute
|
113
113
|
data = []
|
114
114
|
a = Class.new do
|
115
|
-
def initialize(app)
|
115
|
+
def initialize(app)
|
116
|
+
@app = app
|
117
|
+
end
|
116
118
|
|
117
|
-
define_method :call do |
|
118
|
-
data <<
|
119
|
+
define_method :call do |_env|
|
120
|
+
data << 'a'
|
119
121
|
end
|
120
122
|
end
|
121
123
|
|
122
|
-
b =
|
124
|
+
b = ->(_env) { data << 'b' }
|
123
125
|
|
124
126
|
env = {}
|
125
127
|
instance = described_class.new([a, b])
|
126
128
|
instance.call(env)
|
127
129
|
|
128
|
-
expect(data).to eq [
|
130
|
+
expect(data).to eq ['a']
|
129
131
|
end
|
130
132
|
|
131
|
-
describe
|
132
|
-
it
|
133
|
+
describe 'exceptions' do
|
134
|
+
it 'should propagate the exception up the middleware chain' do
|
133
135
|
# This tests a few important properties:
|
134
136
|
# * Exceptions propagate multiple middlewares
|
135
137
|
# - C raises an exception, which raises through B to A.
|
@@ -141,70 +143,76 @@ describe Middleware::Runner do
|
|
141
143
|
end
|
142
144
|
|
143
145
|
define_method :call do |env|
|
144
|
-
data <<
|
146
|
+
data << 'a'
|
145
147
|
begin
|
146
148
|
@app.call(env)
|
147
|
-
data <<
|
149
|
+
data << 'never'
|
148
150
|
rescue Exception => e
|
149
|
-
data <<
|
151
|
+
data << 'e'
|
150
152
|
raise
|
151
153
|
end
|
152
154
|
end
|
153
155
|
end
|
154
156
|
|
155
157
|
b = Class.new do
|
156
|
-
def initialize(app)
|
158
|
+
def initialize(app)
|
159
|
+
@app = app
|
160
|
+
end
|
157
161
|
|
158
162
|
define_method :call do |env|
|
159
|
-
data <<
|
163
|
+
data << 'b'
|
160
164
|
@app.call(env)
|
161
165
|
end
|
162
166
|
end
|
163
167
|
|
164
|
-
c =
|
168
|
+
c = ->(_env) { fail 'ERROR' }
|
165
169
|
|
166
170
|
env = {}
|
167
171
|
instance = described_class.new([a, b, c])
|
168
172
|
expect { instance.call(env) }.to raise_error 'ERROR'
|
169
173
|
|
170
|
-
expect(data).to eq
|
174
|
+
expect(data).to eq %w(a b e)
|
171
175
|
end
|
172
176
|
|
173
|
-
it
|
177
|
+
it 'should stop propagation if rescued' do
|
174
178
|
# This test mainly tests that if there is a sequence A, B, C, and
|
175
179
|
# an exception is raised in C, that if B rescues this, then the chain
|
176
180
|
# continues fine backwards.
|
177
181
|
data = []
|
178
182
|
a = Class.new do
|
179
|
-
def initialize(app)
|
183
|
+
def initialize(app)
|
184
|
+
@app = app
|
185
|
+
end
|
180
186
|
|
181
187
|
define_method :call do |env|
|
182
|
-
data <<
|
188
|
+
data << 'in_a'
|
183
189
|
@app.call(env)
|
184
|
-
data <<
|
190
|
+
data << 'out_a'
|
185
191
|
end
|
186
192
|
end
|
187
193
|
|
188
194
|
b = Class.new do
|
189
|
-
def initialize(app)
|
195
|
+
def initialize(app)
|
196
|
+
@app = app
|
197
|
+
end
|
190
198
|
|
191
199
|
define_method :call do |env|
|
192
|
-
data <<
|
200
|
+
data << 'in_b'
|
193
201
|
@app.call(env) rescue nil
|
194
|
-
data <<
|
202
|
+
data << 'out_b'
|
195
203
|
end
|
196
204
|
end
|
197
205
|
|
198
|
-
c = lambda do |
|
199
|
-
data <<
|
200
|
-
|
206
|
+
c = lambda do |_env|
|
207
|
+
data << 'in_c'
|
208
|
+
fail 'BAD'
|
201
209
|
end
|
202
210
|
|
203
211
|
env = {}
|
204
212
|
instance = described_class.new([a, b, c])
|
205
213
|
instance.call(env)
|
206
214
|
|
207
|
-
expect(data).to eq
|
215
|
+
expect(data).to eq %w(in_a in_b in_c out_b out_a)
|
208
216
|
end
|
209
217
|
end
|
210
218
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require 'codeclimate-test-reporter'
|
2
2
|
CodeClimate::TestReporter.start
|
3
3
|
# This file was generated by the `rspec --init` command. Conventionally, all
|
4
4
|
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
@@ -42,50 +42,48 @@ RSpec.configure do |config|
|
|
42
42
|
|
43
43
|
# The settings below are suggested to provide a good initial experience
|
44
44
|
# with RSpec, but feel free to customize to your heart's content.
|
45
|
-
|
46
|
-
#
|
47
|
-
#
|
48
|
-
#
|
49
|
-
#
|
50
|
-
config.
|
51
|
-
|
52
|
-
|
53
|
-
#
|
54
|
-
#
|
55
|
-
# - http://
|
56
|
-
# - http://
|
57
|
-
#
|
58
|
-
|
59
|
-
|
60
|
-
#
|
61
|
-
#
|
62
|
-
|
63
|
-
|
64
|
-
#
|
65
|
-
#
|
66
|
-
#
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
#
|
75
|
-
#
|
76
|
-
#
|
77
|
-
|
78
|
-
|
79
|
-
#
|
80
|
-
#
|
81
|
-
#
|
82
|
-
#
|
83
|
-
|
84
|
-
|
85
|
-
#
|
86
|
-
#
|
87
|
-
#
|
88
|
-
#
|
89
|
-
Kernel.srand config.seed
|
90
|
-
=end
|
45
|
+
# # These two settings work together to allow you to limit a spec run
|
46
|
+
# # to individual examples or groups you care about by tagging them with
|
47
|
+
# # `:focus` metadata. When nothing is tagged with `:focus`, all examples
|
48
|
+
# # get run.
|
49
|
+
# config.filter_run :focus
|
50
|
+
# config.run_all_when_everything_filtered = true
|
51
|
+
#
|
52
|
+
# # Limits the available syntax to the non-monkey patched syntax that is recommended.
|
53
|
+
# # For more details, see:
|
54
|
+
# # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
|
55
|
+
# # - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
|
56
|
+
# # - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching
|
57
|
+
# config.disable_monkey_patching!
|
58
|
+
#
|
59
|
+
# # This setting enables warnings. It's recommended, but in some cases may
|
60
|
+
# # be too noisy due to issues in dependencies.
|
61
|
+
# config.warnings = true
|
62
|
+
#
|
63
|
+
# # Many RSpec users commonly either run the entire suite or an individual
|
64
|
+
# # file, and it's useful to allow more verbose output when running an
|
65
|
+
# # individual spec file.
|
66
|
+
# if config.files_to_run.one?
|
67
|
+
# # Use the documentation formatter for detailed output,
|
68
|
+
# # unless a formatter has already been configured
|
69
|
+
# # (e.g. via a command-line flag).
|
70
|
+
# config.default_formatter = 'doc'
|
71
|
+
# end
|
72
|
+
#
|
73
|
+
# # Print the 10 slowest examples and example groups at the
|
74
|
+
# # end of the spec run, to help surface which specs are running
|
75
|
+
# # particularly slow.
|
76
|
+
# config.profile_examples = 10
|
77
|
+
#
|
78
|
+
# # Run specs in random order to surface order dependencies. If you find an
|
79
|
+
# # order dependency and want to debug it, you can fix the order by providing
|
80
|
+
# # the seed, which is printed after each run.
|
81
|
+
# # --seed 1234
|
82
|
+
# config.order = :random
|
83
|
+
#
|
84
|
+
# # Seed global randomization in this process using the `--seed` CLI option.
|
85
|
+
# # Setting this allows you to use `--seed` to deterministically reproduce
|
86
|
+
# # test failures related to randomization by passing the same `--seed` value
|
87
|
+
# # as the one that triggered the failure.
|
88
|
+
# Kernel.srand config.seed
|
91
89
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ibsciss-middleware
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mitchell Hashimoto
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2015-
|
12
|
+
date: 2015-11-10 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
@@ -98,9 +98,11 @@ files:
|
|
98
98
|
- Rakefile
|
99
99
|
- lib/middleware.rb
|
100
100
|
- lib/middleware/builder.rb
|
101
|
+
- lib/middleware/logger.rb
|
101
102
|
- lib/middleware/runner.rb
|
102
103
|
- middleware.gemspec
|
103
104
|
- spec/middleware/builder_spec.rb
|
105
|
+
- spec/middleware/logger_spec.rb
|
104
106
|
- spec/middleware/runner_spec.rb
|
105
107
|
- spec/spec_helper.rb
|
106
108
|
homepage: https://github.com/ibsciss/ruby-middleware
|
@@ -130,5 +132,6 @@ summary: Generalized implementation of the rack middleware abstraction for Ruby
|
|
130
132
|
of responsibility design pattern).
|
131
133
|
test_files:
|
132
134
|
- spec/middleware/builder_spec.rb
|
135
|
+
- spec/middleware/logger_spec.rb
|
133
136
|
- spec/middleware/runner_spec.rb
|
134
137
|
- spec/spec_helper.rb
|