rutter 0.2.0 → 0.3.3
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/.rubocop.yml +5 -9
- data/.travis.yml +3 -8
- data/Gemfile +3 -3
- data/LICENSE.txt +1 -1
- data/README.md +2 -6
- data/bench/config.ru +1 -1
- data/lib/rutter.rb +8 -3
- data/lib/rutter/builder.rb +20 -10
- data/lib/rutter/mount.rb +24 -0
- data/lib/rutter/route.rb +3 -3
- data/lib/rutter/routes.rb +3 -2
- data/lib/rutter/scope.rb +6 -6
- data/lib/rutter/version.rb +1 -1
- data/rutter.gemspec +1 -1
- data/spec/integration/rack_spec.rb +1 -3
- data/spec/spec_helper.rb +5 -4
- data/spec/unit/builder_spec.rb +35 -0
- data/spec/unit/route_spec.rb +7 -0
- data/spec/unit/scope_spec.rb +14 -0
- metadata +4 -5
- data/lib/rutter/verbs.rb +0 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: aaf97ec12f6052df590a9a37d2979397122d416baffd31e60e18d12f932c6fff
|
4
|
+
data.tar.gz: 01ce145fe6f40151da57c92d4d7cf8acabb55e17c6b49ff82fdde2469f7838d2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: db521004f7e73d85d4c2f83482248a596dc3d4627bd1155c384c6d463c249547c1608053af0fdd8e9902c3ca168d822f33d9f84645f47ce349e049f24336d26c
|
7
|
+
data.tar.gz: a405208deab4e117809969d66d3e370d00fef1a505f8e53708d66f2f5ebb1d388d43cf46ed5a17bf03756f8cfe2965ec6070b1d39995c13132e850b4b48eae0e
|
data/.rubocop.yml
CHANGED
@@ -1,8 +1,7 @@
|
|
1
|
-
require:
|
2
|
-
- rubocop-performance
|
3
|
-
|
1
|
+
require: rubocop-performance
|
4
2
|
AllCops:
|
5
3
|
TargetRubyVersion: 2.5
|
4
|
+
NewCops: enable
|
6
5
|
DisplayCopNames: true
|
7
6
|
Exclude:
|
8
7
|
- "*.gemspec"
|
@@ -14,6 +13,9 @@ Performance:
|
|
14
13
|
Style/StringLiterals:
|
15
14
|
EnforcedStyle: double_quotes
|
16
15
|
|
16
|
+
Style/ClassAndModuleChildren:
|
17
|
+
Enabled: false
|
18
|
+
|
17
19
|
Layout/EmptyLineAfterGuardClause:
|
18
20
|
Enabled: false
|
19
21
|
|
@@ -27,9 +29,3 @@ Metrics/BlockLength:
|
|
27
29
|
Metrics/ModuleLength:
|
28
30
|
Exclude:
|
29
31
|
- "spec/**/*"
|
30
|
-
|
31
|
-
ClassAndModuleChildren:
|
32
|
-
Enabled: false
|
33
|
-
|
34
|
-
Naming/UncommunicativeMethodParamName:
|
35
|
-
MinNameLength: 2
|
data/.travis.yml
CHANGED
@@ -3,20 +3,15 @@ script: "bundle exec rake spec:coverage"
|
|
3
3
|
cache: bundler
|
4
4
|
env:
|
5
5
|
global:
|
6
|
-
-
|
6
|
+
- CODECOV_TOKEN="21653af2-874b-4597-942d-14ddc7c2f8fa"
|
7
7
|
before_install:
|
8
8
|
- "gem update --system"
|
9
|
-
before_script:
|
10
|
-
- curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
|
11
|
-
- chmod +x ./cc-test-reporter
|
12
|
-
- ./cc-test-reporter before-build
|
13
|
-
after_script:
|
14
|
-
- ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT
|
15
9
|
rvm:
|
10
|
+
- 2.7.0
|
16
11
|
- 2.6.0
|
17
12
|
- 2.5.0
|
18
|
-
- jruby-9.2.0.0
|
19
13
|
- ruby-head
|
14
|
+
- jruby
|
20
15
|
- jruby-head
|
21
16
|
- truffleruby
|
22
17
|
matrix:
|
data/Gemfile
CHANGED
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -1,13 +1,9 @@
|
|
1
1
|
# Rutter
|
2
2
|
|
3
|
-
HTTP router for Rack.
|
4
|
-
|
5
|
-
## Status
|
6
|
-
|
7
|
-
Under development, not ready for prime-time just yet.
|
3
|
+
HTTP router for Ramverk and Rack.
|
8
4
|
|
9
5
|
[](https://travis-ci.org/sandelius/rutter)
|
10
|
-
[](https://codecov.io/gh/sandelius/rutter)
|
11
7
|
[](http://inch-ci.org/github/sandelius/rutter)
|
12
8
|
|
13
9
|
## Installation
|
data/bench/config.ru
CHANGED
@@ -10,7 +10,7 @@ router = Rutter.new do
|
|
10
10
|
get "/", to: ->(_) { [200, {}, ["Hello World"]] }
|
11
11
|
|
12
12
|
# wrk -t 2 http://localhost:9292/ruby
|
13
|
-
get "/:lang", to: ->(env) { [200, {}, [env["
|
13
|
+
get "/:lang", to: ->(env) { [200, {}, [env["router.params"]["lang"]]] }
|
14
14
|
end.freeze
|
15
15
|
|
16
16
|
run router
|
data/lib/rutter.rb
CHANGED
@@ -1,10 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative "rutter/version"
|
4
|
-
require_relative "rutter/builder"
|
5
|
-
|
6
3
|
# HTTP router for Rack.
|
7
4
|
module Rutter
|
5
|
+
# Supported request verbs.
|
6
|
+
#
|
7
|
+
# @return [Array]
|
8
|
+
VERBS = %w[GET POST PUT PATCH DELETE OPTIONS].freeze
|
9
|
+
|
10
|
+
require_relative "rutter/version"
|
11
|
+
require_relative "rutter/builder"
|
12
|
+
|
8
13
|
# Factory method for creating a new builder object.
|
9
14
|
#
|
10
15
|
# @param base [String]
|
data/lib/rutter/builder.rb
CHANGED
@@ -3,7 +3,6 @@
|
|
3
3
|
require "uri"
|
4
4
|
|
5
5
|
require_relative "naming"
|
6
|
-
require_relative "verbs"
|
7
6
|
require_relative "route"
|
8
7
|
require_relative "mount"
|
9
8
|
require_relative "scope"
|
@@ -40,7 +39,7 @@ module Rutter
|
|
40
39
|
def initialize(base: "http://localhost:9292", &block)
|
41
40
|
@uri = URI(base).freeze
|
42
41
|
@flat_map = []
|
43
|
-
@verb_map =
|
42
|
+
@verb_map = VERBS.map { |v| [v, []] }.to_h
|
44
43
|
@named_map = {}
|
45
44
|
|
46
45
|
instance_eval(&block) if block_given?
|
@@ -91,10 +90,12 @@ module Rutter
|
|
91
90
|
# Application to mount.
|
92
91
|
# @param at [String]
|
93
92
|
# Path prefix to match.
|
93
|
+
# @param host [Regexp]
|
94
|
+
# Match the given host pattern.
|
94
95
|
#
|
95
96
|
# @return [Rutter::Mount]
|
96
|
-
def mount(app, at:)
|
97
|
-
route = Mount.new(at, app)
|
97
|
+
def mount(app, at:, host: nil)
|
98
|
+
route = Mount.new(at, app, host: host)
|
98
99
|
@flat_map << route
|
99
100
|
VERBS.each { |verb| @verb_map[verb] << route }
|
100
101
|
route
|
@@ -131,12 +132,12 @@ module Rutter
|
|
131
132
|
# # => "/login?return_to=/"
|
132
133
|
# router.path(:book, id: 82)
|
133
134
|
# # => "/books/82"
|
134
|
-
def path(name,
|
135
|
+
def path(name, **args)
|
135
136
|
unless (route = @named_map[name])
|
136
137
|
raise "No route called '#{name}' was found"
|
137
138
|
end
|
138
139
|
|
139
|
-
route.expand(
|
140
|
+
route.expand(**args)
|
140
141
|
end
|
141
142
|
|
142
143
|
# Generates a full URL from the given arguments.
|
@@ -178,7 +179,7 @@ module Rutter
|
|
178
179
|
host += "#{args.delete(:subdomain)}." if args.key?(:subdomain)
|
179
180
|
host += @uri.host
|
180
181
|
host += ":#{@uri.port}" if @uri.port != 80 && @uri.port != 443
|
181
|
-
host + path(name, args)
|
182
|
+
host + path(name, **args)
|
182
183
|
end
|
183
184
|
|
184
185
|
# Add a new, frozen, route to the map.
|
@@ -193,14 +194,23 @@ module Rutter
|
|
193
194
|
# Route name/identifier.
|
194
195
|
# @param constraints [Hash]
|
195
196
|
# Route segment constraints.
|
197
|
+
# @param &block [Proc]
|
198
|
+
# Endpoint as a block.
|
199
|
+
# @yieldparam env [Hash]
|
200
|
+
# Rack's environment hash.
|
196
201
|
#
|
197
202
|
# @return [Rutter::Route]
|
198
203
|
#
|
199
204
|
# @raise [ArgumentError]
|
200
205
|
# If verb is unsupported.
|
206
|
+
# @raise [ArgumentError]
|
207
|
+
# If endpoint is missing.
|
201
208
|
#
|
202
209
|
# @private
|
203
|
-
def add(verb, path, to
|
210
|
+
def add(verb, path, to: nil, as: nil, constraints: nil, &block)
|
211
|
+
to = block if block_given?
|
212
|
+
raise "Missing endpoint" unless to
|
213
|
+
|
204
214
|
verb = verb.to_s.upcase
|
205
215
|
|
206
216
|
unless VERBS.include?(verb)
|
@@ -229,8 +239,8 @@ module Rutter
|
|
229
239
|
|
230
240
|
# @see #add
|
231
241
|
VERBS.each do |verb|
|
232
|
-
define_method verb.downcase do |path, to
|
233
|
-
add verb, path, to: to, as: as, constraints: constraints
|
242
|
+
define_method verb.downcase do |path, to: nil, as: nil, constraints: nil, &block|
|
243
|
+
add verb, path, to: to, as: as, constraints: constraints, &block
|
234
244
|
end
|
235
245
|
end
|
236
246
|
|
data/lib/rutter/mount.rb
CHANGED
@@ -7,6 +7,15 @@ module Rutter
|
|
7
7
|
#
|
8
8
|
# @private
|
9
9
|
class Mount < Route
|
10
|
+
# @see Rutter::Route#initialize
|
11
|
+
#
|
12
|
+
# @private
|
13
|
+
def initialize(path, endpoint, constraints = nil, host: nil)
|
14
|
+
@host = host
|
15
|
+
|
16
|
+
super(path, endpoint, constraints)
|
17
|
+
end
|
18
|
+
|
10
19
|
# Matches the app pattern against environment.
|
11
20
|
#
|
12
21
|
# @param env [Hash]
|
@@ -15,7 +24,22 @@ module Rutter
|
|
15
24
|
# @return [nil, String]
|
16
25
|
# Returns the matching substring or nil on no match.
|
17
26
|
def match?(env)
|
27
|
+
return if @host && !@host.match?(host(env))
|
28
|
+
|
18
29
|
@pattern.peek(env["PATH_INFO"])
|
19
30
|
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
# @private
|
35
|
+
def host(env)
|
36
|
+
env["rutter.parsed_host"] ||= begin
|
37
|
+
if (forwarded = env["HTTP_X_FORWARDED_HOST"])
|
38
|
+
forwarded.split(/,\s?/).last
|
39
|
+
else
|
40
|
+
env["HTTP_HOST"] || env["SERVER_NAME"] || env["SERVER_ADDR"]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
20
44
|
end
|
21
45
|
end
|
data/lib/rutter/route.rb
CHANGED
@@ -71,7 +71,7 @@ module Rutter
|
|
71
71
|
#
|
72
72
|
# @return [Hash]
|
73
73
|
def params(path)
|
74
|
-
@pattern.params(path)
|
74
|
+
@pattern.params(path) || {}
|
75
75
|
end
|
76
76
|
|
77
77
|
# Calls the endpoint.
|
@@ -84,8 +84,8 @@ module Rutter
|
|
84
84
|
#
|
85
85
|
# @private
|
86
86
|
def call(env)
|
87
|
-
env["
|
88
|
-
env["
|
87
|
+
env["router.params"] ||= {}
|
88
|
+
env["router.params"].merge!(params(env["PATH_INFO"]))
|
89
89
|
env["rutter.action"] = @endpoint[:action]
|
90
90
|
|
91
91
|
ctrl = @endpoint[:controller]
|
data/lib/rutter/routes.rb
CHANGED
@@ -53,10 +53,11 @@ module Rutter
|
|
53
53
|
protected
|
54
54
|
|
55
55
|
# @private
|
56
|
-
def method_missing(method_name,
|
56
|
+
def method_missing(method_name, **args)
|
57
57
|
named_route, type = method_name.to_s.split(/\_(path|url)\z/)
|
58
58
|
return super unless type
|
59
|
-
|
59
|
+
|
60
|
+
@router.public_send(type, named_route.to_sym, **args)
|
60
61
|
end
|
61
62
|
|
62
63
|
# @private
|
data/lib/rutter/scope.rb
CHANGED
@@ -34,8 +34,8 @@ module Rutter
|
|
34
34
|
end
|
35
35
|
|
36
36
|
# @see Rutter::Builder#mount
|
37
|
-
def mount(app, at:)
|
38
|
-
@router.mount app, at: Naming.join(@path, at)
|
37
|
+
def mount(app, at:, host: nil)
|
38
|
+
@router.mount app, at: Naming.join(@path, at), host: host
|
39
39
|
end
|
40
40
|
|
41
41
|
# @see Rutter::Builder#scope
|
@@ -49,18 +49,18 @@ module Rutter
|
|
49
49
|
end
|
50
50
|
|
51
51
|
# @see Rutter::Builder#add
|
52
|
-
def add(verb, path, to
|
52
|
+
def add(verb, path, to: nil, as: nil, constraints: nil, &block)
|
53
53
|
path = Naming.join(@path, path)
|
54
54
|
to = Naming.join(@namespace, to) if to.is_a?(String)
|
55
55
|
as = Naming.join(@as, as) if as
|
56
56
|
|
57
|
-
@router.add verb, path, to: to, as: as, constraints: constraints
|
57
|
+
@router.add verb, path, to: to, as: as, constraints: constraints, &block
|
58
58
|
end
|
59
59
|
|
60
60
|
# @see Rutter::Builder#add
|
61
61
|
VERBS.each do |verb|
|
62
|
-
define_method verb.downcase do |path, to
|
63
|
-
add verb, path, to: to, as: as, constraints: constraints
|
62
|
+
define_method verb.downcase do |path, to: nil, as: nil, constraints: nil, &block|
|
63
|
+
add verb, path, to: to, as: as, constraints: constraints, &block
|
64
64
|
end
|
65
65
|
end
|
66
66
|
end
|
data/lib/rutter/version.rb
CHANGED
data/rutter.gemspec
CHANGED
@@ -20,7 +20,7 @@ Gem::Specification.new do |spec|
|
|
20
20
|
spec.test_files = spec.files.grep(%r{^(spec)/})
|
21
21
|
spec.require_paths = ["lib"]
|
22
22
|
|
23
|
-
spec.add_runtime_dependency "mustermann", "~> 1.
|
23
|
+
spec.add_runtime_dependency "mustermann", "~> 1.1"
|
24
24
|
spec.add_runtime_dependency "rack", "~> 2.0"
|
25
25
|
|
26
26
|
spec.add_development_dependency "bundler"
|
@@ -4,7 +4,7 @@ RSpec.describe "Rack compatible", type: :request do
|
|
4
4
|
let :router do
|
5
5
|
Rutter.new do
|
6
6
|
get "/say/:message", to: (lambda do |env|
|
7
|
-
[200, {}, ["I say, #{env['
|
7
|
+
[200, {}, ["I say, #{env['router.params']['message']}"]]
|
8
8
|
end)
|
9
9
|
end
|
10
10
|
end
|
@@ -21,8 +21,6 @@ RSpec.describe "Rack compatible", type: :request do
|
|
21
21
|
.to eq(200)
|
22
22
|
expect(last_response.body)
|
23
23
|
.to eq("I say, hello-world")
|
24
|
-
expect(last_response.headers["Content-Length"])
|
25
|
-
.to eq("18")
|
26
24
|
end
|
27
25
|
end
|
28
26
|
|
data/spec/spec_helper.rb
CHANGED
@@ -2,10 +2,6 @@
|
|
2
2
|
|
3
3
|
require "bundler/setup"
|
4
4
|
|
5
|
-
unless ENV["CI"]
|
6
|
-
require "byebug"
|
7
|
-
end
|
8
|
-
|
9
5
|
if ENV["COVERAGE"] == "true"
|
10
6
|
require "simplecov"
|
11
7
|
|
@@ -13,6 +9,11 @@ if ENV["COVERAGE"] == "true"
|
|
13
9
|
command_name "spec"
|
14
10
|
add_filter "spec"
|
15
11
|
end
|
12
|
+
|
13
|
+
if ENV["CODECOV_TOKEN"]
|
14
|
+
require "codecov"
|
15
|
+
SimpleCov.formatter = SimpleCov::Formatter::Codecov
|
16
|
+
end
|
16
17
|
end
|
17
18
|
|
18
19
|
# Require support (helper) modules
|
data/spec/unit/builder_spec.rb
CHANGED
@@ -18,6 +18,23 @@ module Rutter
|
|
18
18
|
expect(route.match?(env_for("/admin/books")))
|
19
19
|
.to eq("/admin")
|
20
20
|
end
|
21
|
+
|
22
|
+
it "matches host if given" do
|
23
|
+
route = router.mount endpoint, at: "/v1", host: /\Aapi\./
|
24
|
+
|
25
|
+
expect(route.match?(env_for("http://example.com/v1/books")))
|
26
|
+
.to be_nil
|
27
|
+
expect(route.match?(env_for("http://api.example.com/v1/books")))
|
28
|
+
.to eq("/v1")
|
29
|
+
end
|
30
|
+
|
31
|
+
it "HTTP_X_FORWARDED_HOST are supported" do
|
32
|
+
route = router.mount endpoint, at: "/v1", host: /\Aapi\./
|
33
|
+
env = env_for("/v1/books", "HTTP_X_FORWARDED_HOST" => "api.example.com")
|
34
|
+
|
35
|
+
expect(route.match?(env))
|
36
|
+
.to eq("/v1")
|
37
|
+
end
|
21
38
|
end
|
22
39
|
|
23
40
|
describe "#path" do
|
@@ -90,6 +107,24 @@ module Rutter
|
|
90
107
|
expect(route.match?(env_for("/books/pickaxe")))
|
91
108
|
.to be(false)
|
92
109
|
end
|
110
|
+
|
111
|
+
it "support block as endpoint" do
|
112
|
+
router.get "/" do |env|
|
113
|
+
[200, {}, [env["message"]]]
|
114
|
+
end
|
115
|
+
|
116
|
+
_, _, body = router.call("REQUEST_METHOD" => "GET",
|
117
|
+
"PATH_INFO" => "/",
|
118
|
+
"message" => "Hello World")
|
119
|
+
|
120
|
+
expect(body.join)
|
121
|
+
.to eq("Hello World")
|
122
|
+
end
|
123
|
+
|
124
|
+
it "raises an error if no endpoint is given" do
|
125
|
+
expect { router.get "/" }
|
126
|
+
.to raise_error("Missing endpoint")
|
127
|
+
end
|
93
128
|
end
|
94
129
|
|
95
130
|
describe "verbs" do
|
data/spec/unit/route_spec.rb
CHANGED
@@ -59,6 +59,13 @@ module Rutter
|
|
59
59
|
expect(route.params("/pages/54"))
|
60
60
|
.to eq("id" => "54", "title" => nil)
|
61
61
|
end
|
62
|
+
|
63
|
+
it "returns always return a hash" do
|
64
|
+
route = Route.new("/pages", endpoint)
|
65
|
+
|
66
|
+
expect(route.params("/pages"))
|
67
|
+
.to eq({})
|
68
|
+
end
|
62
69
|
end
|
63
70
|
end
|
64
71
|
end
|
data/spec/unit/scope_spec.rb
CHANGED
@@ -34,6 +34,20 @@ module Rutter
|
|
34
34
|
expect(route.match?(env_for("/books/pickaxe")))
|
35
35
|
.to be(false)
|
36
36
|
end
|
37
|
+
|
38
|
+
it "support block as endpoint" do
|
39
|
+
scope = router.scope path: "/books"
|
40
|
+
scope.get "/" do |env|
|
41
|
+
[200, {}, [env["message"]]]
|
42
|
+
end
|
43
|
+
|
44
|
+
_, _, body = router.call("REQUEST_METHOD" => "GET",
|
45
|
+
"PATH_INFO" => "/books",
|
46
|
+
"message" => "Hello World")
|
47
|
+
|
48
|
+
expect(body.join)
|
49
|
+
.to eq("Hello World")
|
50
|
+
end
|
37
51
|
end
|
38
52
|
|
39
53
|
describe "#mount" do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rutter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tobias Sandelius
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-07-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: mustermann
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '1.
|
19
|
+
version: '1.1'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '1.
|
26
|
+
version: '1.1'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rack
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -117,7 +117,6 @@ files:
|
|
117
117
|
- lib/rutter/route.rb
|
118
118
|
- lib/rutter/routes.rb
|
119
119
|
- lib/rutter/scope.rb
|
120
|
-
- lib/rutter/verbs.rb
|
121
120
|
- lib/rutter/version.rb
|
122
121
|
- rutter.gemspec
|
123
122
|
- spec/integration/rack_spec.rb
|