pendragon 0.6.2 → 1.0.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 +4 -4
- data/.travis.yml +4 -2
- data/Gemfile +7 -0
- data/Gemfile.lock +27 -83
- data/README.md +69 -192
- data/Rakefile +3 -18
- data/benchmark.rb +31 -0
- data/lib/pendragon.rb +60 -44
- data/lib/pendragon/constants.rb +27 -0
- data/lib/pendragon/errors.rb +72 -0
- data/lib/pendragon/linear.rb +9 -0
- data/lib/pendragon/realism.rb +49 -0
- data/lib/pendragon/router.rb +295 -142
- data/lib/pendragon/version.rb +1 -1
- data/pendragon.gemspec +1 -6
- data/test/helper.rb +9 -84
- data/test/router/test_linear.rb +6 -0
- data/test/router/test_realism.rb +6 -0
- data/test/supports/shared_examples_for_routing.rb +277 -0
- data/test/test_router.rb +40 -0
- metadata +22 -101
- data/lib/pendragon/configuration.rb +0 -42
- data/lib/pendragon/engine/compiler.rb +0 -74
- data/lib/pendragon/engine/recognizer.rb +0 -72
- data/lib/pendragon/error.rb +0 -71
- data/lib/pendragon/matcher.rb +0 -93
- data/lib/pendragon/padrino.rb +0 -15
- data/lib/pendragon/padrino/ext/class_methods.rb +0 -318
- data/lib/pendragon/padrino/ext/instance_methods.rb +0 -63
- data/lib/pendragon/padrino/route.rb +0 -50
- data/lib/pendragon/padrino/router.rb +0 -34
- data/lib/pendragon/route.rb +0 -124
- data/test/compile_helper.rb +0 -3
- data/test/padrino_test.rb +0 -2113
- data/test/pendragon_configuration.rb +0 -32
- data/test/pendragon_test.rb +0 -229
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cd0edab5d92da0e54a220b00f8f7d494b4db1e3b
|
4
|
+
data.tar.gz: 543fc628f35ff975c0a24812ea09a3fa6d21c8b1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2bc2a1c2b90272591d3b1c3c1447f2f1502636ac741406bb3b2fa3ae2e106fae188876147e4235857a7f9ff6b5cbe900b3da9f561bc6d65fc5f695b9c117add6
|
7
|
+
data.tar.gz: d65be58e80f6ba365a8d11a5523426e83bca18929417874e199a072e13c1509bba27720e9e9775cd9314cf9db8f00aa111b090a077743b0ab153e3725b358015
|
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,104 +1,48 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
pendragon (0.6.
|
5
|
-
|
4
|
+
pendragon (0.6.2)
|
5
|
+
mustermann
|
6
6
|
rack (>= 1.3.0)
|
7
7
|
|
8
8
|
GEM
|
9
9
|
remote: https://rubygems.org/
|
10
10
|
specs:
|
11
|
-
activesupport (4.1.6)
|
12
|
-
i18n (~> 0.6, >= 0.6.9)
|
13
|
-
json (~> 1.7, >= 1.7.7)
|
14
|
-
minitest (~> 5.1)
|
15
|
-
thread_safe (~> 0.1)
|
16
|
-
tzinfo (~> 1.1)
|
17
|
-
enumerable-lazy (0.0.1)
|
18
|
-
haml (4.0.5)
|
19
|
-
tilt
|
20
|
-
http_router (0.11.1)
|
21
|
-
rack (>= 1.0.0)
|
22
|
-
url_mount (~> 0.2.1)
|
23
|
-
i18n (0.6.11)
|
24
|
-
json (1.8.1)
|
25
|
-
json (1.8.1-java)
|
26
|
-
mail (2.5.4)
|
27
|
-
mime-types (~> 1.16)
|
28
|
-
treetop (~> 1.4.8)
|
29
11
|
metaclass (0.0.4)
|
30
|
-
mime-types (1.25.1)
|
31
|
-
minitest (5.4.2)
|
32
12
|
mocha (1.1.0)
|
33
13
|
metaclass (~> 0.0.1)
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
padrino-cache (= 0.12.4)
|
40
|
-
padrino-core (= 0.12.4)
|
41
|
-
padrino-gen (= 0.12.4)
|
42
|
-
padrino-helpers (= 0.12.4)
|
43
|
-
padrino-mailer (= 0.12.4)
|
44
|
-
padrino-support (= 0.12.4)
|
45
|
-
padrino-admin (0.12.4)
|
46
|
-
padrino-core (= 0.12.4)
|
47
|
-
padrino-helpers (= 0.12.4)
|
48
|
-
padrino-cache (0.12.4)
|
49
|
-
moneta (~> 0.7.0)
|
50
|
-
padrino-core (= 0.12.4)
|
51
|
-
padrino-helpers (= 0.12.4)
|
52
|
-
padrino-core (0.12.4)
|
53
|
-
activesupport (>= 3.1)
|
54
|
-
http_router (~> 0.11.0)
|
55
|
-
padrino-support (= 0.12.4)
|
56
|
-
rack-protection (>= 1.5.0)
|
57
|
-
sinatra (~> 1.4.2)
|
58
|
-
thor (~> 0.18)
|
59
|
-
padrino-gen (0.12.4)
|
60
|
-
bundler (~> 1.0)
|
61
|
-
padrino-core (= 0.12.4)
|
62
|
-
padrino-helpers (0.12.4)
|
63
|
-
i18n (~> 0.6, >= 0.6.7)
|
64
|
-
padrino-support (= 0.12.4)
|
65
|
-
tilt (~> 1.4.1)
|
66
|
-
padrino-mailer (0.12.4)
|
67
|
-
mail (~> 2.5.3)
|
68
|
-
padrino-core (= 0.12.4)
|
69
|
-
padrino-support (0.12.4)
|
70
|
-
activesupport (>= 3.1)
|
71
|
-
polyglot (0.3.5)
|
72
|
-
rack (1.5.2)
|
14
|
+
modulla (0.1.1)
|
15
|
+
mustermann (0.4.0)
|
16
|
+
tool (~> 0.2)
|
17
|
+
power_assert (0.3.0)
|
18
|
+
rack (1.5.5)
|
73
19
|
rack-protection (1.5.3)
|
74
20
|
rack
|
75
|
-
rack-test (0.6.
|
21
|
+
rack-test (0.6.3)
|
76
22
|
rack (>= 1.0)
|
77
|
-
rake (
|
78
|
-
sinatra (1.4.
|
79
|
-
rack (~> 1.
|
23
|
+
rake (11.3.0)
|
24
|
+
sinatra (1.4.7)
|
25
|
+
rack (~> 1.5)
|
80
26
|
rack-protection (~> 1.4)
|
81
|
-
tilt (
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
polyglot
|
88
|
-
polyglot (>= 0.3.1)
|
89
|
-
tzinfo (1.2.2)
|
90
|
-
thread_safe (~> 0.1)
|
91
|
-
url_mount (0.2.1)
|
92
|
-
rack
|
27
|
+
tilt (>= 1.3, < 3)
|
28
|
+
test-unit (3.2.1)
|
29
|
+
power_assert
|
30
|
+
tilt (2.0.5)
|
31
|
+
tool (0.2.3)
|
32
|
+
yard (0.9.5)
|
93
33
|
|
94
34
|
PLATFORMS
|
95
|
-
java
|
96
35
|
ruby
|
97
36
|
|
98
37
|
DEPENDENCIES
|
99
|
-
|
100
|
-
|
101
|
-
padrino (~> 0.12.2)
|
38
|
+
mocha
|
39
|
+
modulla
|
102
40
|
pendragon!
|
103
|
-
rack-test
|
104
|
-
rake
|
41
|
+
rack-test
|
42
|
+
rake
|
43
|
+
sinatra
|
44
|
+
test-unit
|
45
|
+
yard
|
46
|
+
|
47
|
+
BUNDLED WITH
|
48
|
+
1.12.5
|
data/README.md
CHANGED
@@ -2,268 +2,145 @@
|
|
2
2
|
|
3
3
|
[](https://travis-ci.org/namusyaka/pendragon) [](http://badge.fury.io/rb/pendragon)
|
4
4
|
|
5
|
-
Pendragon provides an HTTP router for use in Rack
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
Pendragon provides an HTTP router and its toolkit for use in Rack. As a Rack application, it makes it easy to define complicated routing.
|
6
|
+
Algorithms of the router are used in [Padrino](https://github.com/padrino/padrino-framework) and [Grape](https://github.com/ruby-grape/grape), it's fast, flexible and robust.
|
7
|
+
|
8
|
+
*If you want to use in Ruby-1.9, you can do it by using [mustermann19](https://github.com/namusyaka/mustermann19).*
|
9
9
|
|
10
|
-
*If you want to use in Ruby1.9, you can do it by using [mustermann/1.9-support branch](https://github.com/rkh/mustermann/tree/1.9-support).*
|
11
10
|
|
12
11
|
```ruby
|
13
12
|
Pendragon.new do
|
14
|
-
get(
|
15
|
-
|
16
|
-
|
13
|
+
get('/') { [200, {}, ['hello world']] }
|
14
|
+
namespace :users do
|
15
|
+
get('/', to: -> { [200, {}, ['User page index']] })
|
16
|
+
get('/:id', to: -> (id) { [200, {}, [id]] })
|
17
|
+
get('/:id/comments') { |id| [200, {}, [User.find_by(id: id).comments.to_json]] }
|
17
18
|
end
|
18
19
|
end
|
19
20
|
```
|
20
21
|
|
21
|
-
##
|
22
|
-
|
23
|
-
Depends on [rack](https://github.com/rack/rack) and [mustermann](https://github.com/rkh/mustermann).
|
22
|
+
## Router Patterns
|
24
23
|
|
25
|
-
|
26
|
-
|
27
|
-
|
24
|
+
|Type |Description |Note |
|
25
|
+
|---|---|---|
|
26
|
+
|[liner](https://github.com/namusyaka/pendragon/blob/master/lib/pendragon/liner.rb) |Linear search, Optimized Mustermann patterns | |
|
27
|
+
|[realism](https://github.com/namusyaka/pendragon/blob/master/lib/pendragon/realism.rb) |First route is detected by union regexps (Actually, O(1) in ruby level), routes since the first time will be retected by linear search | this algorithm is using in Grape |
|
28
|
+
|[radix](https://github.com/namusyaka/pendragon-radix) |Radix Tree, not using Mustermann and regexp| requires C++11 |
|
28
29
|
|
29
|
-
|
30
|
-
|
31
|
-
|name |types |default|description |
|
32
|
-
|:---------------|:------|:------|:-------------------------|
|
33
|
-
|enable_compiler |boolean|false|The performance will be improved. However, it will increase the first load time.|
|
34
|
-
|auto_rack_format|boolean|true|If disable this param, the block of route should return the response of valid rack format.|
|
35
|
-
|lock |boolean|false|If you enable this option, all requests to synchronize on a mutex lock|
|
30
|
+
## Installation
|
36
31
|
|
37
|
-
|
32
|
+
Add this line to your application's Gemfile:
|
38
33
|
|
39
34
|
```ruby
|
40
|
-
|
41
|
-
Pendragon.new do |config|
|
42
|
-
config.enable_compiler = true
|
43
|
-
end
|
35
|
+
gem 'pendragon'
|
44
36
|
```
|
45
37
|
|
46
|
-
|
38
|
+
And then execute:
|
47
39
|
|
48
|
-
|
40
|
+
$ bundle
|
49
41
|
|
50
|
-
|
51
|
-
# Enable the param (default)
|
52
|
-
Pendragon.new do
|
53
|
-
get("/"){ "hey" }
|
54
|
-
end
|
42
|
+
Or install it yourself as:
|
55
43
|
|
56
|
-
|
57
|
-
config.auto_rack_format = false
|
58
|
-
end
|
59
|
-
# Disable the param
|
60
|
-
pendragon.get("/"){ [200, {"Content-Type" => "text/html;charset=utf-8"}, ["hey"]] }
|
61
|
-
```
|
44
|
+
$ gem install pendragon
|
62
45
|
|
63
|
-
#### `lock`
|
64
46
|
|
65
|
-
|
66
|
-
pendragon = Pendragon.new do |config|
|
67
|
-
config.lock = true
|
68
|
-
end
|
69
|
-
```
|
47
|
+
## Usage
|
70
48
|
|
71
|
-
|
49
|
+
### Selects router pattern
|
72
50
|
|
73
|
-
|
51
|
+
You can select router pattern as following code.
|
74
52
|
|
75
53
|
```ruby
|
76
|
-
#
|
77
|
-
Pendragon
|
78
|
-
config.enable_compiler = true
|
79
|
-
end
|
54
|
+
# Gets Linear router class by passing type in `Pendragon.[]`
|
55
|
+
Pendragon[:linear] #=> Pendragon::Linear
|
80
56
|
|
81
|
-
#
|
82
|
-
|
83
|
-
config.enable_compiler = true
|
84
|
-
end
|
57
|
+
# Specify :type to construction of Pendragon.
|
58
|
+
Pendragon.new(type: :linear) { ... }
|
85
59
|
```
|
86
60
|
|
87
|
-
###
|
61
|
+
### Registers a route
|
88
62
|
|
89
63
|
It has some methods to register a route. For example, `#get`, `#post` and `#delete` are so.
|
90
64
|
This section introduces all those methods.
|
91
65
|
|
92
|
-
#### `
|
66
|
+
#### `route(method, path, **options, &block)`
|
67
|
+
|
93
68
|
|
94
69
|
The method is the basis of the registration method of all.
|
95
70
|
In comparison with other registration methods, one argument is increased.
|
96
71
|
|
97
72
|
```ruby
|
98
73
|
Pendragon.new do
|
99
|
-
|
100
|
-
add(:get, "/"){ "hello world" }
|
101
|
-
get("/"){ "hello world" }
|
74
|
+
route('GET', ?/){ [200, {}, ['hello']] }
|
102
75
|
end
|
103
76
|
```
|
104
77
|
|
105
|
-
#### `get(path,
|
78
|
+
#### `get(path, **options, &block)`, `post`, `delete`, `put` and `head`
|
106
79
|
|
107
|
-
Basically the usage is the same with `#
|
108
|
-
You may as well use those methods instead of `#
|
80
|
+
Basically the usage is the same with `#route`.
|
81
|
+
You may as well use those methods instead of `#route` because those methods are easy to understand.
|
109
82
|
|
110
83
|
```ruby
|
111
84
|
Pendragon.new do
|
112
|
-
get(
|
113
|
-
post(
|
114
|
-
delete(
|
115
|
-
put(
|
116
|
-
head(
|
85
|
+
get (?/) { [200, {}, ['hello']] }
|
86
|
+
post (?/) { [200, {}, ['hello']] }
|
87
|
+
delete(?/) { [200, {}, ['hello']] }
|
88
|
+
put (?/) { [200, {}, ['hello']] }
|
89
|
+
head (?/) { [200, {}, ['hello']] }
|
117
90
|
end
|
118
91
|
```
|
119
92
|
|
120
|
-
|
121
|
-
|
122
|
-
The path must be an instance of String (this must be complied with the Mustermann::Sinatra's rule) or Regexp.
|
123
|
-
|
124
|
-
##### Route options
|
125
|
-
|
126
|
-
|name|types |description |
|
127
|
-
|:----|:------|:-------------------------|
|
128
|
-
|name |symbol |specify the name of route for `Pendragon::Router#path` method.|
|
129
|
-
|order|integer|specify the order for the prioritized routes.|
|
130
|
-
|capture|hash|specify the capture for matching condition. [more information here](https://github.com/rkh/mustermann)|
|
131
|
-
|status|integer|specify the status code of response|
|
132
|
-
|header|hash|specify the header of response|
|
133
|
-
|
134
|
-
##### Block Parameters
|
135
|
-
|
136
|
-
The block is allowed to pass a parameter.
|
137
|
-
It will be an instance of Hash.
|
138
|
-
|
139
|
-
```ruby
|
140
|
-
pendragon = Pendragon.new do
|
141
|
-
get("/:id/:foo/:bar"){|params| params.inspect }
|
142
|
-
end
|
143
|
-
|
144
|
-
request = Rack::MockRequest.env_for("/123/hey/ho")
|
145
|
-
pendragon.recognize(request).first.call #=> '{id: "123", foo: "hey", bar: "ho"}'
|
146
|
-
```
|
147
|
-
|
148
|
-
### Recognize the route
|
149
|
-
|
150
|
-
The route registered can be recognized by several methods.
|
151
|
-
|
152
|
-
#### `recognize(request)`
|
153
|
-
|
154
|
-
This method returns all the routes that match the conditions.
|
155
|
-
The format of returns will be such as `[[Pendragon::Route, params], ...]`.
|
156
|
-
The request must be an instance of `Rack::Request` or Hash created by `Rack::MockRequest.env_for`.
|
93
|
+
### Mounts Rack Application
|
157
94
|
|
158
|
-
|
159
|
-
pendragon = Pendragon.new
|
160
|
-
index = pendragon.get("/"){ "hello world" }
|
161
|
-
foo = pendragon.get("/foo/:bar"){ "foo is bar" }
|
162
|
-
|
163
|
-
mock_request = Rack::MockRequest.env_for("/")
|
164
|
-
route, params = pendragon.recognize(mock_request).first
|
165
|
-
|
166
|
-
route.path == index.path #=> true
|
167
|
-
params #=> {}
|
95
|
+
You can easily mount your rack application onto Pendragon.
|
168
96
|
|
169
|
-
|
170
|
-
route, params = pendragon.recognize(mock_request).first
|
171
|
-
|
172
|
-
route.path == foo.path #=> true
|
173
|
-
params #=> {bar: "baz"}
|
174
|
-
```
|
175
|
-
|
176
|
-
#### `recognize_path(path_info)`
|
177
|
-
|
178
|
-
Recognizes a route from `path_info`.
|
179
|
-
The method uses `#recognize`, but return value is not same with it.
|
180
|
-
Maybe this is useful if you set the name to the route.
|
97
|
+
*Please note that pendragon distinguishes between processing Proc and Rack Application.*
|
181
98
|
|
182
99
|
```ruby
|
183
|
-
|
184
|
-
|
185
|
-
|
100
|
+
class RackApp
|
101
|
+
def call(env)
|
102
|
+
puts env #=> rack default env
|
103
|
+
[200, {}, ['hello']]
|
104
|
+
end
|
186
105
|
end
|
187
106
|
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
#### `path(name, *args)`
|
193
|
-
|
194
|
-
Recognizes a route from route's name, and expands the path from parameters.
|
195
|
-
If you pass a name that does not exist, Pendragon raises `InvalidRouteException`.
|
196
|
-
The parameters that is not required to expand will be treated as query.
|
197
|
-
|
198
|
-
```ruby
|
199
|
-
pendragon = Pendragon.new do
|
200
|
-
get("/", name: :index){ "hello world" }
|
201
|
-
get("/:id", name: :foo){ "fooooo" }
|
107
|
+
Pendragon.new do
|
108
|
+
get '/ids/:id', to: -> (id) { p id } # Block parameters are available
|
109
|
+
get '/rack/:id', to: RackApp.new # RackApp#call will be called, `id` is not passed and `env` is passed instead.
|
202
110
|
end
|
203
|
-
|
204
|
-
pendragon.path(:index) #=> "/"
|
205
|
-
pendragon.path(:foo, id: "123") #=> "/123"
|
206
|
-
pendragon.path(:foo, id: "123", bar: "hey") #=> "/123?bar=hey"
|
207
111
|
```
|
208
112
|
|
209
|
-
###
|
113
|
+
### Halt
|
210
114
|
|
211
|
-
|
212
|
-
If you want to use this, you should pass the `:order` option to the registration method.
|
115
|
+
You can halt to processing by calling `throw :halt` inside your route.
|
213
116
|
|
214
117
|
```ruby
|
215
|
-
|
216
|
-
get
|
217
|
-
|
218
|
-
|
118
|
+
Pendragon.new do
|
119
|
+
get ?/ do
|
120
|
+
throw :halt, [404, {}, ['not found']]
|
121
|
+
[200, {}, ['failed to halt']]
|
122
|
+
end
|
219
123
|
end
|
220
|
-
|
221
|
-
request = Rack::MockRequest.env_for("/")
|
222
|
-
pendragon.recognize(request).map{|route, _| route.call } #=> ["one", "two", "three"]
|
223
124
|
```
|
224
125
|
|
225
|
-
###
|
126
|
+
### Cascading
|
226
127
|
|
227
|
-
A route can punt
|
128
|
+
A route can punt to the next matching route by using `X-Cascade` header.
|
228
129
|
|
229
130
|
```ruby
|
230
131
|
pendragon = Pendragon.new do
|
231
|
-
foo =
|
232
|
-
get
|
233
|
-
|
234
|
-
end
|
235
|
-
|
236
|
-
request = Rack::MockRequest.env_for("/")
|
237
|
-
pendragon.call(request) #=> [200, {"Content-Type"=>"text/html;charset=utf-8"}, ["yay"]]
|
238
|
-
```
|
239
|
-
|
240
|
-
### With Padrino
|
241
|
-
|
242
|
-
Add `register Pendragon::Padrino` to your padrino application.
|
243
|
-
Of course, Pendragon has compatibility with Padrino Routing.
|
244
|
-
|
245
|
-
|
246
|
-
```ruby
|
247
|
-
require 'pendragon/padrino'
|
248
|
-
|
249
|
-
class App < Padrino::Application
|
250
|
-
register Pendragon::Padrino
|
251
|
-
|
252
|
-
# Also, your app's performance will be improved by using compiler mode.
|
253
|
-
set :pendragon, enable_compiler: true
|
254
|
-
|
255
|
-
get :index do
|
256
|
-
"hello pendragon!"
|
257
|
-
end
|
258
|
-
|
259
|
-
get :users, :map => "/users/:user_id/", :user_id => /\d+/ do |user_id|
|
260
|
-
params.inspect
|
132
|
+
foo = 1
|
133
|
+
get ?/ do
|
134
|
+
[200, { 'X-Cascade' => 'pass' }, ['']]
|
261
135
|
end
|
262
136
|
|
263
|
-
get
|
264
|
-
|
137
|
+
get ?/ do
|
138
|
+
[200, {}, ['goal!']]
|
265
139
|
end
|
266
140
|
end
|
141
|
+
|
142
|
+
env = Rack::MockRequest.env_for(?/)
|
143
|
+
pendragon.call(env) #=> [200, {}, ['goal!']]
|
267
144
|
```
|
268
145
|
|
269
146
|
## Contributing
|