midler 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 +7 -0
- data/.gitignore +9 -0
- data/.rspec +1 -0
- data/.travis.yml +3 -0
- data/Gemfile +4 -0
- data/README.md +105 -0
- data/Rakefile +9 -0
- data/lib/midler/builder.rb +135 -0
- data/lib/midler/runner.rb +69 -0
- data/lib/midler/version.rb +3 -0
- data/lib/midler.rb +3 -0
- data/midler.gemspec +24 -0
- data/midler.jpg +0 -0
- metadata +126 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: f2237664840e88240019d59937eb343b6e109f7c
|
4
|
+
data.tar.gz: 8369600f8a0ae3b9b26890378e991842b2446138
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: bd98a7aa3a7465ae44468292a789002e6db8afee3c820d56ab5c29b02a26bb39f2311710b6c9072317fea4241a13eaf83802155e3b21784fa0cb5ee4c9d5c13b
|
7
|
+
data.tar.gz: d775a38ce73e3f5000a984f7b257591e6b1c045d8cfbcb90a5de93b2c9a7a4c8daacd7eacc8cb55b2a7b76e8b80a6bc6c4febc432148ccc2c5cf50a1bba9f430
|
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
# Midler
|
2
|
+
|
3
|
+
This is a fork of [Middleware](https://github.com/mitchellh/middleware) that allows multiple env arguments, and is fully backward compatible. Refer to the parent gem for additional documentation.
|
4
|
+
|
5
|
+

|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'midler'
|
13
|
+
```
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install midler
|
22
|
+
|
23
|
+
## Variadic Middleware Usage
|
24
|
+
|
25
|
+
This is where this fork of the gem really shines. We can now pass variadic arguments in place of env. For example, we can now call the stack with a `request` and `response` for this express-style webserver example.
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
class JsonResponse
|
29
|
+
def initialize(app)
|
30
|
+
@app = app
|
31
|
+
end
|
32
|
+
|
33
|
+
def call(request, response)
|
34
|
+
Logger.info { "Received #{request[:body]} from request" }
|
35
|
+
response[:accept] = "application/json"
|
36
|
+
@app.call(request, response)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
stack = Midler::Builder.new do
|
41
|
+
use JsonResponse
|
42
|
+
use Authenticate
|
43
|
+
use Authorized
|
44
|
+
end
|
45
|
+
|
46
|
+
# Run it!
|
47
|
+
stack.call(request, response)
|
48
|
+
```
|
49
|
+
|
50
|
+
## Singular Env Usage
|
51
|
+
|
52
|
+
Once you create a basic middleware, you can use the builder to
|
53
|
+
have a nice DSL to build middleware stacks. Calling the middleware
|
54
|
+
is simple, as well.
|
55
|
+
|
56
|
+
```ruby
|
57
|
+
# Basic middleware that just prints the inbound and
|
58
|
+
# outbound steps.
|
59
|
+
class Trace
|
60
|
+
def initialize(app, value)
|
61
|
+
@app = app
|
62
|
+
@value = value
|
63
|
+
end
|
64
|
+
|
65
|
+
def call(env)
|
66
|
+
puts "--> #{@value}"
|
67
|
+
@app.call(env)
|
68
|
+
puts "<-- #{@value}"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# Build the actual middleware stack which runs a sequence
|
73
|
+
# of slightly different versions of our middleware.
|
74
|
+
stack = Midler::Builder.new do
|
75
|
+
use Trace, "A"
|
76
|
+
use Trace, "B"
|
77
|
+
use Trace, "C"
|
78
|
+
end
|
79
|
+
|
80
|
+
# Run it!
|
81
|
+
stack.call(nil)
|
82
|
+
```
|
83
|
+
|
84
|
+
And the output:
|
85
|
+
|
86
|
+
```
|
87
|
+
--> A
|
88
|
+
--> B
|
89
|
+
--> C
|
90
|
+
<-- C
|
91
|
+
<-- B
|
92
|
+
<-- A
|
93
|
+
```
|
94
|
+
|
95
|
+
## Development
|
96
|
+
|
97
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release` to create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
98
|
+
|
99
|
+
## Contributing
|
100
|
+
|
101
|
+
1. Fork it ( https://github.com/film42/midler/fork )
|
102
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
103
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
104
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
105
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,135 @@
|
|
1
|
+
module Midler
|
2
|
+
# This provides a DSL for building up a stack of middlewares.
|
3
|
+
#
|
4
|
+
# This code is based heavily off of `Rack::Builder` and
|
5
|
+
# `ActionDispatch::MiddlewareStack` in Rack and Rails, respectively.
|
6
|
+
#
|
7
|
+
# # Usage
|
8
|
+
#
|
9
|
+
# Building a middleware stack is very easy:
|
10
|
+
#
|
11
|
+
# app = Midler::Builder.new do
|
12
|
+
# use A
|
13
|
+
# use B
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# # Call the middleware
|
17
|
+
# app.call(7)
|
18
|
+
#
|
19
|
+
class Builder
|
20
|
+
# Initializes the builder. An optional block can be passed which
|
21
|
+
# will be evaluated in the context of the instance.
|
22
|
+
#
|
23
|
+
# Example:
|
24
|
+
#
|
25
|
+
# Builder.new do
|
26
|
+
# use A
|
27
|
+
# use B
|
28
|
+
# end
|
29
|
+
#
|
30
|
+
# @param [Hash] opts Options hash
|
31
|
+
# @option opts [Class] :runner_class The class to wrap the middleware stack
|
32
|
+
# in which knows how to run them.
|
33
|
+
# @yield [] Evaluated in this instance which allows you to use methods
|
34
|
+
# like {#use} and such.
|
35
|
+
def initialize(opts=nil, &block)
|
36
|
+
opts ||= {}
|
37
|
+
@runner_class = opts[:runner_class] || Runner
|
38
|
+
instance_eval(&block) if block_given?
|
39
|
+
end
|
40
|
+
|
41
|
+
# Returns a mergeable version of the builder. If `use` is called with
|
42
|
+
# the return value of this method, then the stack will merge, instead
|
43
|
+
# of being treated as a separate single middleware.
|
44
|
+
def flatten
|
45
|
+
lambda do |*envs|
|
46
|
+
self.call(*envs)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Adds a middleware class to the middleware stack. Any additional
|
51
|
+
# args and a block, if given, are saved and passed to the initializer
|
52
|
+
# of the middleware.
|
53
|
+
#
|
54
|
+
# @param [Class] middleware The middleware class
|
55
|
+
def use(middleware, *args, &block)
|
56
|
+
if middleware.kind_of?(Builder)
|
57
|
+
# Merge in the other builder's stack into our own
|
58
|
+
self.stack.concat(middleware.stack)
|
59
|
+
else
|
60
|
+
self.stack << [middleware, args, block]
|
61
|
+
end
|
62
|
+
|
63
|
+
self
|
64
|
+
end
|
65
|
+
|
66
|
+
# Inserts a middleware at the given index or directly before the
|
67
|
+
# given middleware object.
|
68
|
+
def insert(index, middleware, *args, &block)
|
69
|
+
index = self.index(index) unless index.is_a?(Integer)
|
70
|
+
stack.insert(index, [middleware, args, block])
|
71
|
+
end
|
72
|
+
|
73
|
+
alias_method :insert_before, :insert
|
74
|
+
|
75
|
+
# Inserts a middleware after the given index or middleware object.
|
76
|
+
def insert_after(index, middleware, *args, &block)
|
77
|
+
index = self.index(index) unless index.is_a?(Integer)
|
78
|
+
raise "no such middleware to insert after: #{index.inspect}" unless index
|
79
|
+
insert(index + 1, middleware, *args, &block)
|
80
|
+
end
|
81
|
+
|
82
|
+
# Replaces the given middlware object or index with the new
|
83
|
+
# middleware.
|
84
|
+
def replace(index, middleware, *args, &block)
|
85
|
+
if index.is_a?(Integer)
|
86
|
+
delete(index)
|
87
|
+
insert(index, middleware, *args, &block)
|
88
|
+
else
|
89
|
+
insert_before(index, middleware, *args, &block)
|
90
|
+
delete(index)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# Deletes the given middleware object or index
|
95
|
+
def delete(index)
|
96
|
+
index = self.index(index) unless index.is_a?(Integer)
|
97
|
+
stack.delete_at(index)
|
98
|
+
end
|
99
|
+
|
100
|
+
# Runs the builder stack with the given environments.
|
101
|
+
def call(*envs)
|
102
|
+
envs = [nil] if envs.empty?
|
103
|
+
to_app.call(*envs)
|
104
|
+
end
|
105
|
+
|
106
|
+
protected
|
107
|
+
|
108
|
+
# Returns the numeric index for the given middleware object.
|
109
|
+
#
|
110
|
+
# @param [Object] object The item to find the index for
|
111
|
+
# @return [Integer]
|
112
|
+
def index(object)
|
113
|
+
stack.each_with_index do |item, i|
|
114
|
+
return i if item[0] == object
|
115
|
+
end
|
116
|
+
|
117
|
+
nil
|
118
|
+
end
|
119
|
+
|
120
|
+
# Returns the current stack of middlewares. You probably won't
|
121
|
+
# need to use this directly, and it's recommended that you don't.
|
122
|
+
#
|
123
|
+
# @return [Array]
|
124
|
+
def stack
|
125
|
+
@stack ||= []
|
126
|
+
end
|
127
|
+
|
128
|
+
# Converts the builder stack to a runnable action sequence.
|
129
|
+
#
|
130
|
+
# @return [Object] A callable object
|
131
|
+
def to_app
|
132
|
+
@runner_class.new(stack.dup)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module Midler
|
2
|
+
# This is a basic runner for middleware stacks. This runner does
|
3
|
+
# the default expected behavior of running the middleware stacks
|
4
|
+
# in order, then reversing the order.
|
5
|
+
class Runner
|
6
|
+
# A middleware which does nothing
|
7
|
+
EMPTY_MIDDLEWARE = lambda { |*envs| }
|
8
|
+
|
9
|
+
# Build a new middleware runner with the given middleware
|
10
|
+
# stack.
|
11
|
+
#
|
12
|
+
# Note: This class usually doesn't need to be used directly.
|
13
|
+
# Instead, take a look at using the {Builder} class, which is
|
14
|
+
# a much friendlier way to build up a middleware stack.
|
15
|
+
#
|
16
|
+
# @param [Array] stack An array of the middleware to run.
|
17
|
+
def initialize(stack)
|
18
|
+
# We need to take the stack of middleware and initialize them
|
19
|
+
# all so they call the proper next middleware.
|
20
|
+
@kickoff = build_call_chain(stack)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Run the middleware stack with the given state bag.
|
24
|
+
#
|
25
|
+
# @param [Object] env The state to pass into as the initial
|
26
|
+
# environment data. This is usual a hash of some sort.
|
27
|
+
def call(*envs)
|
28
|
+
# We just call the kickoff middleware, which is responsible
|
29
|
+
# for properly calling the next middleware, and so on and so
|
30
|
+
# forth.
|
31
|
+
@kickoff.call(*envs)
|
32
|
+
end
|
33
|
+
|
34
|
+
protected
|
35
|
+
|
36
|
+
# This takes a stack of middlewares and initializes them in a way
|
37
|
+
# that each middleware properly calls the next middleware.
|
38
|
+
def build_call_chain(stack)
|
39
|
+
# We need to instantiate the middleware stack in reverse
|
40
|
+
# order so that each middleware can have a reference to
|
41
|
+
# the next middleware it has to call. The final middleware
|
42
|
+
# is always the empty middleware, which does nothing but return.
|
43
|
+
stack.reverse.inject(EMPTY_MIDDLEWARE) do |next_middleware, current_middleware|
|
44
|
+
# Unpack the actual item
|
45
|
+
klass, args, block = current_middleware
|
46
|
+
|
47
|
+
# Default the arguments to an empty array. Otherwise in Ruby 1.8
|
48
|
+
# a `nil` args will actually pass `nil` into the class. Not what
|
49
|
+
# we want!
|
50
|
+
args ||= []
|
51
|
+
|
52
|
+
if klass.is_a?(Class)
|
53
|
+
# If the klass actually is a class, then instantiate it with
|
54
|
+
# the app and any other arguments given.
|
55
|
+
klass.new(next_middleware, *args, &block)
|
56
|
+
elsif klass.respond_to?(:call)
|
57
|
+
# Make it a lambda which calls the item then forwards up
|
58
|
+
# the chain.
|
59
|
+
lambda do |*envs|
|
60
|
+
klass.call(*envs)
|
61
|
+
next_middleware.call(*envs)
|
62
|
+
end
|
63
|
+
else
|
64
|
+
raise "Invalid middleware, doesn't respond to `call`: #{action.inspect}"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
data/lib/midler.rb
ADDED
data/midler.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'midler/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "midler"
|
8
|
+
spec.version = Midler::VERSION
|
9
|
+
spec.authors = ["Garrett Thornburg"]
|
10
|
+
spec.email = ["garrett.thornburg@mx.com"]
|
11
|
+
spec.summary = "A variadic fork of the middleware gem"
|
12
|
+
spec.description = "A variadic fork of the middleware gem"
|
13
|
+
spec.homepage = "https://github.com/film42/midler"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
17
|
+
spec.require_paths = ["lib"]
|
18
|
+
|
19
|
+
spec.add_development_dependency "bundler", "~> 1.8"
|
20
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
21
|
+
spec.add_development_dependency "rspec-core", "~> 2.8.0"
|
22
|
+
spec.add_development_dependency "rspec-expectations", "~> 2.8.0"
|
23
|
+
spec.add_development_dependency "rspec-mocks", "~> 2.8.0"
|
24
|
+
end
|
data/midler.jpg
ADDED
Binary file
|
metadata
ADDED
@@ -0,0 +1,126 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: midler
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Garrett Thornburg
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-03-25 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.8'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.8'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec-core
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 2.8.0
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 2.8.0
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec-expectations
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 2.8.0
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 2.8.0
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec-mocks
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 2.8.0
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 2.8.0
|
83
|
+
description: A variadic fork of the middleware gem
|
84
|
+
email:
|
85
|
+
- garrett.thornburg@mx.com
|
86
|
+
executables: []
|
87
|
+
extensions: []
|
88
|
+
extra_rdoc_files: []
|
89
|
+
files:
|
90
|
+
- ".gitignore"
|
91
|
+
- ".rspec"
|
92
|
+
- ".travis.yml"
|
93
|
+
- Gemfile
|
94
|
+
- README.md
|
95
|
+
- Rakefile
|
96
|
+
- lib/midler.rb
|
97
|
+
- lib/midler/builder.rb
|
98
|
+
- lib/midler/runner.rb
|
99
|
+
- lib/midler/version.rb
|
100
|
+
- midler.gemspec
|
101
|
+
- midler.jpg
|
102
|
+
homepage: https://github.com/film42/midler
|
103
|
+
licenses:
|
104
|
+
- MIT
|
105
|
+
metadata: {}
|
106
|
+
post_install_message:
|
107
|
+
rdoc_options: []
|
108
|
+
require_paths:
|
109
|
+
- lib
|
110
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
111
|
+
requirements:
|
112
|
+
- - ">="
|
113
|
+
- !ruby/object:Gem::Version
|
114
|
+
version: '0'
|
115
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
116
|
+
requirements:
|
117
|
+
- - ">="
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
version: '0'
|
120
|
+
requirements: []
|
121
|
+
rubyforge_project:
|
122
|
+
rubygems_version: 2.4.3
|
123
|
+
signing_key:
|
124
|
+
specification_version: 4
|
125
|
+
summary: A variadic fork of the middleware gem
|
126
|
+
test_files: []
|