rutter 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 2abaca05bb6b82020f84e94bad340f3b36b878f8
4
+ data.tar.gz: a9ef1e6084c8ed5ac55b4fc531ddb5a72ee2ad90
5
+ SHA512:
6
+ metadata.gz: 36fe83976abbe7c9b8e1f2a19af118ad6d3f261b2c48d0bae3bfaf63888ffc45ecf27ea83f9b5d859a1ff2722a4cd027fa32ef24af777d6e169f0fa43636ba5c
7
+ data.tar.gz: cac8e0f2e0f2797f91f92309a69214f6e3023fd3773f6636f17188efefae64cdaef3da82b4d77c1f0c09a45f1cdf21304eaee99976f329752663fbf7efcaa313
data/.gitignore ADDED
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+ .DS_Store
10
+ /doc
data/.rubocop.yml ADDED
@@ -0,0 +1,24 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.4
3
+ DisplayCopNames: true
4
+ Exclude: []
5
+
6
+ Style/StringLiterals:
7
+ EnforcedStyle: double_quotes
8
+
9
+ Lint/EndAlignment:
10
+ EnforcedStyleAlignWith: variable
11
+
12
+ Metrics/MethodLength:
13
+ Max: 15
14
+
15
+ Metrics/BlockLength:
16
+ Exclude:
17
+ - "spec/**/*"
18
+
19
+ Metrics/ModuleLength:
20
+ Exclude:
21
+ - "spec/**/*"
22
+
23
+ ClassAndModuleChildren:
24
+ Enabled: false
data/.travis.yml ADDED
@@ -0,0 +1,22 @@
1
+ language: ruby
2
+ script: "bundle exec rake spec:coverage"
3
+ cache: bundler
4
+ before_install:
5
+ - rvm @global do gem uninstall bundler -a -x
6
+ - rvm @global do gem install bundler -v 1.15.0
7
+ after_script:
8
+ - "CODECLIMATE_REPO_TOKEN=d8f51b92273019156d95fcf54adf51bee10c42f9419101eae0d638f1c94075aa bundle exec codeclimate-test-reporter"
9
+ rvm:
10
+ - 2.4.2
11
+ - 2.4.0
12
+ - ruby-head
13
+ - jruby-9.1.13.0
14
+ - jruby-head
15
+ matrix:
16
+ allow_failures:
17
+ - rvm: jruby-head
18
+ - rvm: jruby-9.1.13.0
19
+ - rvm: ruby-head
20
+ branches:
21
+ only:
22
+ - master
data/.yardopts ADDED
@@ -0,0 +1,2 @@
1
+ --no-private
2
+ -m markdown
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+ gemspec
5
+
6
+ gem "codeclimate-test-reporter"
7
+ gem "simplecov"
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 Tobias Sandelius
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,140 @@
1
+ # Rutter
2
+
3
+ HTTP router for Rack.
4
+
5
+ ## Status
6
+
7
+ [![Build Status](https://travis-ci.org/sandelius/rutter.svg?branch=master)](https://travis-ci.org/sandelius/rutter)
8
+ [![Test Coverage](https://codeclimate.com/github/sandelius/rutter/badges/coverage.svg)](https://codeclimate.com/github/sandelius/rutter/coverage)
9
+
10
+ ## Installation
11
+
12
+ Add this line to your application's Gemfile:
13
+
14
+ ```ruby
15
+ gem "rutter"
16
+ ```
17
+
18
+ And then execute:
19
+
20
+ $ bundle
21
+
22
+ Or install it yourself as:
23
+
24
+ $ gem install rutter
25
+
26
+ ## Usage
27
+
28
+ Basic usage
29
+
30
+ ```ruby
31
+ require "rutter"
32
+
33
+ router = Rutter.new do
34
+ get "/", to: ->(env) { [200, {}, ["Hello World"]] }
35
+ end
36
+
37
+ run router.freeze
38
+ ```
39
+
40
+ ### HTTP verbs
41
+
42
+ The router supports most of the verbs available.
43
+
44
+ ```ruby
45
+ require "rutter"
46
+
47
+ Rutter.new do
48
+ get "/", to: ->(env) {}
49
+ post "/", to: ->(env) {}
50
+ put "/", to: ->(env) {}
51
+ patch "/", to: ->(env) {}
52
+ delete "/", to: ->(env) {}
53
+ options "/", to: ->(env) {}
54
+ head "/", to: ->(env) {}
55
+ trace "/", to: ->(env) {}
56
+ end
57
+ ```
58
+
59
+ ### Named parameters
60
+
61
+ In the example `:title` is a *named parameter*. The values are accessible via `env["rutter.params"]` and it contains a `Hash<String => String>`.
62
+
63
+ ```ruby
64
+ require "rutter"
65
+
66
+ Rutter.new do
67
+ get "/books/:title", to: ->(env) {}
68
+ end
69
+ ```
70
+
71
+ Named parameters only match a single path segment:
72
+
73
+ ```
74
+ /books/eloquent-ruby match
75
+ /books/confident-ruby match
76
+ /books/confident-ruby.rb no match
77
+ /books/eloquent-ruby/reviews no match
78
+ /books/ no match
79
+ ```
80
+
81
+ ### Catch-All parameters
82
+
83
+ *catch-all* parameters have the form `*title`. Like the name suggests, they match everything, event new `/` segments. Therefore they must always be at the end of the pattern.
84
+
85
+ ```ruby
86
+ require "rutter"
87
+
88
+ Rutter.new do
89
+ get "/books/*title", to: ->(env) {}
90
+ end
91
+ ```
92
+
93
+ ```
94
+ /books/eloquent-ruby match
95
+ /books/confident-ruby match
96
+ /books/confident-ruby.rb match
97
+ /books/eloquent-ruby/reviews match
98
+ /books/ no match
99
+ ```
100
+
101
+ ### Optional segments
102
+
103
+ Support for optional segments have the form `(i-am-optional)`.
104
+
105
+ ```ruby
106
+ require "rutter"
107
+
108
+ Rutter.new do
109
+ get "/books(/:title)", to: ->(env) {}
110
+ end
111
+ ```
112
+
113
+ ```
114
+ /books/eloquent-ruby match
115
+ /books/confident-ruby match
116
+ /books/confident-ruby.rb no match
117
+ /books/eloquent-ruby/reviews no match
118
+ /books match
119
+ ```
120
+
121
+ ### Redirects
122
+
123
+ Make legacy paths point to a new destination.
124
+
125
+ ```ruby
126
+ require "rutter"
127
+
128
+ Rutter.new do
129
+ get "/legacy-path", to: redirect("/new_path")
130
+ end
131
+ ```
132
+
133
+ ## Contributing
134
+
135
+ Bug reports and pull requests are welcome on GitHub at https://github.com/sandelius/skeletor. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
136
+
137
+
138
+ ## License
139
+
140
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rake/testtask"
5
+
6
+ Rake::TestTask.new(:spec) do |t|
7
+ t.pattern = "spec/**/*_spec.rb"
8
+ t.libs.push "spec"
9
+ end
10
+
11
+ namespace :spec do
12
+ task :coverage do
13
+ ENV["COVERAGE"] = "true"
14
+ Rake::Task["spec"].invoke
15
+ end
16
+ end
17
+
18
+ task default: :spec
data/bench/config.ru ADDED
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ # $ puma -e production -t 16:16
4
+ # $ wrk -t 2 http://localhost:9292/
5
+
6
+ require "rack"
7
+ require_relative "../lib/rutter"
8
+
9
+ router = Rutter.new do
10
+ root to: lambda { |env|
11
+ [200, { "Content-Type" => "text/html" }, ["Hello World"]]
12
+ }
13
+ end
14
+
15
+ run router.freeze
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env ruby -W0
2
+
3
+ require_relative "helper"
4
+
5
+ router = Rutter.new
6
+ app = Rack::MockRequest.new(router)
7
+
8
+ Benchmark.bm(50) do |b|
9
+ b.report "generating routes" do
10
+ DICT.each do |route|
11
+ router.get "#{route}/:id", to: $endpoint
12
+ end
13
+ end
14
+
15
+ b.report "recognizing routes" do
16
+ TIMES.times do
17
+ app.get("#{DICT.sample}/54")
18
+ end
19
+ end
20
+ end
data/bench/expand ADDED
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env ruby -W0
2
+
3
+ require_relative "helper"
4
+
5
+ router = Rutter.new
6
+
7
+ Benchmark.bm(50) do |b|
8
+ b.report "generating routes" do
9
+ DICT.each do |route|
10
+ router.get "#{route}/:id", to: $endpoint, as: route
11
+ end
12
+ end
13
+
14
+ b.report "expand routes" do
15
+ TIMES.times do
16
+ router.path(DICT.sample.to_sym, id: 54, key: "value")
17
+ end
18
+ end
19
+ end
data/bench/helper.rb ADDED
@@ -0,0 +1,19 @@
1
+ require "benchmark"
2
+ require "rack"
3
+ require_relative "../lib/rutter"
4
+
5
+ BATCH_SIZE = 1000
6
+ TIMES = 100000
7
+ DICT = IO.foreach("/usr/share/dict/words")
8
+ .lazy
9
+ .map { |word| word.chomp.downcase }
10
+ .uniq
11
+ .take(BATCH_SIZE)
12
+ .sort_by(&:length)
13
+ .reverse
14
+
15
+ $endpoint = ->(env) { [200, {}, ["Hello World"]] }
16
+
17
+ puts "Loading #{BATCH_SIZE} routes, calling them #{TIMES} times...\n"
18
+
19
+ GC.disable
data/bench/mount ADDED
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env ruby -W0
2
+
3
+ require_relative "helper"
4
+
5
+ router = Rutter.new
6
+ app = Rack::MockRequest.new(router)
7
+
8
+ DICT.each do |route|
9
+ router.mount $endpoint, at: route
10
+ end
11
+
12
+ builder = Rack::Builder.app do
13
+ DICT.each do |route|
14
+ map("/#{route}") { run $endpoint }
15
+ end
16
+ end
17
+
18
+ rack_app = Rack::MockRequest.new(builder)
19
+
20
+ Benchmark.bm(50) do |b|
21
+ b.report "recognizing mounts" do
22
+ TIMES.times do
23
+ app.get("/#{DICT.sample}/sub/path")
24
+ end
25
+ end
26
+
27
+ b.report "recognizing rack map" do
28
+ TIMES.times do
29
+ rack_app.get("/#{DICT.sample}/sub/path")
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env ruby -W0
2
+
3
+ require_relative "helper"
4
+
5
+ router = Rutter.new
6
+ routes = Rutter::Routes.new(router)
7
+
8
+ DICT.each do |route|
9
+ router.get "#{route}/:id", to: $endpoint, as: route
10
+ end
11
+
12
+ Benchmark.bm(50) do |b|
13
+ b.report "dynamic *_path" do
14
+ TIMES.times do
15
+ routes.public_send "#{DICT.sample}_path", id: 54, key: "value"
16
+ end
17
+ end
18
+
19
+ b.report "dynamic *_url" do
20
+ TIMES.times do
21
+ routes.public_send "#{DICT.sample}_url", id: 54, key: "value"
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env ruby -W0
2
+
3
+ require_relative "helper"
4
+
5
+ router = Rutter.new
6
+ app = Rack::MockRequest.new(router)
7
+
8
+ Benchmark.bm(50) do |b|
9
+ b.report "generating routes" do
10
+ DICT.each do |route|
11
+ router.get route, to: $endpoint
12
+ end
13
+ end
14
+
15
+ b.report "recognizing routes" do
16
+ TIMES.times do
17
+ app.get(DICT.sample)
18
+ end
19
+ end
20
+ end