rackr 0.0.48 → 0.0.50
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/lib/rackr/action.rb +91 -46
- data/lib/rackr/html.rb +139 -0
- data/lib/rackr/router/errors/dev_html.rb +96 -0
- data/lib/rackr/router/errors.rb +10 -4
- data/lib/rackr/router/route.rb +6 -4
- data/lib/rackr/router.rb +64 -56
- data/lib/rackr.rb +9 -6
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 889c67a66431461f8ef941117b0195498135b5ee0c4b3b75c17f8c784f65678c
|
4
|
+
data.tar.gz: 5482a863b01cf4637824ed7a054da8ac7a339154c8dc2b19faf11576e7585b77
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1f0fb3862cb8f3e50b3aef24c99e0ee9ee2252542d026c4d7d078063d30ccbbd8bed3b0964814d82f95d929cdcb33c29bd639209842666c2af173f17f9d70160
|
7
|
+
data.tar.gz: f5a6835a8b80acd26e8e3ddf8cd38c84b23066319e65727688285c8b51ddcaccab401908e4dff64bcbabe3614ca45ab20a3cd3cc638b434c70cd94f76b33e321
|
data/lib/rackr/action.rb
CHANGED
@@ -16,11 +16,12 @@ class Rackr
|
|
16
16
|
@db = config[:db]
|
17
17
|
end
|
18
18
|
|
19
|
-
def view_response(a_path, a_view_params = {}, status: 200)
|
19
|
+
def view_response(a_path, a_view_params = {}, status: 200, headers: {})
|
20
20
|
Rackr::Action.view_response(
|
21
21
|
a_path,
|
22
22
|
a_view_params,
|
23
23
|
status: status,
|
24
|
+
headers: headers,
|
24
25
|
config: config,
|
25
26
|
routes: routes,
|
26
27
|
db: db
|
@@ -28,12 +29,13 @@ class Rackr
|
|
28
29
|
end
|
29
30
|
|
30
31
|
def view(
|
31
|
-
a_path, a_view_params = {}, status: 200, response_instance: false
|
32
|
+
a_path, a_view_params = {}, status: 200, response_instance: false, headers: {}
|
32
33
|
)
|
33
34
|
Rackr::Action.view(
|
34
35
|
a_path,
|
35
36
|
a_view_params,
|
36
37
|
status: status,
|
38
|
+
headers: headers,
|
37
39
|
config: config,
|
38
40
|
routes: routes,
|
39
41
|
db: db,
|
@@ -43,44 +45,66 @@ class Rackr
|
|
43
45
|
end
|
44
46
|
end
|
45
47
|
|
46
|
-
def
|
47
|
-
|
48
|
-
|
48
|
+
def html(content = '', status: 200, headers: {}, &block)
|
49
|
+
if block_given? && respond_to?(:html_slice)
|
50
|
+
if respond_to?(:layout)
|
51
|
+
content = layout(&block)
|
52
|
+
else
|
53
|
+
html_slice(:root, &block)
|
54
|
+
content = html_slice
|
55
|
+
end
|
56
|
+
end
|
49
57
|
|
50
|
-
|
51
|
-
Rackr::Action.html(content, status: status)
|
58
|
+
Rackr::Action.html(content, status: status, headers: headers, &block)
|
52
59
|
end
|
53
60
|
|
54
|
-
def html_response(content, status: 200)
|
55
|
-
|
61
|
+
def html_response(content = '', status: 200, headers: {} &block)
|
62
|
+
if block_given? && respond_to?(:html_slice)
|
63
|
+
if respond_to?(:layout)
|
64
|
+
content = layout(&block)
|
65
|
+
else
|
66
|
+
html_slice(:root, &block)
|
67
|
+
content = html_slice
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
Rackr::Action.html_response(content, status: status, headers: headers, &block)
|
56
72
|
end
|
57
73
|
|
58
|
-
def json(content = {}, status: 200)
|
59
|
-
Rackr::Action.json(content, status: status)
|
74
|
+
def json(content = {}, status: 200, headers: {})
|
75
|
+
Rackr::Action.json(content, status: status, headers: headers)
|
60
76
|
end
|
61
77
|
|
62
|
-
def json_response(content = {}, status: 200)
|
63
|
-
Rackr::Action.json_response(content, status: status)
|
78
|
+
def json_response(content = {}, status: 200, headers: {})
|
79
|
+
Rackr::Action.json_response(content, status: status, headers: headers)
|
64
80
|
end
|
65
81
|
|
66
|
-
def text(content, status: 200)
|
67
|
-
Rackr::Action.text(content, status: status)
|
82
|
+
def text(content, status: 200, headers: {})
|
83
|
+
Rackr::Action.text(content, status: status, headers: headers)
|
68
84
|
end
|
69
85
|
|
70
|
-
def text_response(content, status: 200)
|
71
|
-
Rackr::Action.text_response(content, status: status)
|
86
|
+
def text_response(content, status: 200, headers: {})
|
87
|
+
Rackr::Action.text_response(content, status: status, headers: headers)
|
72
88
|
end
|
73
89
|
|
74
90
|
def erb(content, view_params = {})
|
75
91
|
Rackr::Action.erb(content, view_params)
|
76
92
|
end
|
77
93
|
|
78
|
-
def
|
79
|
-
Rackr::Action.
|
94
|
+
def head(status, headers: {})
|
95
|
+
Rackr::Action.head(status, headers: headers)
|
96
|
+
end
|
97
|
+
|
98
|
+
def head_response(status, headers: {})
|
99
|
+
Rackr::Action.head_response(status, headers: headers)
|
100
|
+
end
|
101
|
+
|
102
|
+
def redirect_response(url, headers: {})
|
103
|
+
Rackr::Action.redirect_response(url, headers: headers)
|
80
104
|
end
|
81
105
|
|
82
|
-
def redirect_to(url)
|
83
|
-
Rackr::Action.redirect_to(url)
|
106
|
+
def redirect_to(url, headers: {})
|
107
|
+
Rackr::Action.redirect_to(url, headers: headers)
|
84
108
|
end
|
85
109
|
|
86
110
|
def response(body = nil, status = 200, headers = {})
|
@@ -92,6 +116,7 @@ class Rackr
|
|
92
116
|
paths,
|
93
117
|
view_params = {},
|
94
118
|
status: 200,
|
119
|
+
headers: {},
|
95
120
|
config: {},
|
96
121
|
routes: nil,
|
97
122
|
db: nil
|
@@ -102,6 +127,7 @@ class Rackr
|
|
102
127
|
status: status,
|
103
128
|
config: config,
|
104
129
|
routes: routes,
|
130
|
+
headers: headers,
|
105
131
|
db: db,
|
106
132
|
response_instance: true
|
107
133
|
)
|
@@ -111,6 +137,7 @@ class Rackr
|
|
111
137
|
paths,
|
112
138
|
view_params = {},
|
113
139
|
status: 200,
|
140
|
+
headers: {},
|
114
141
|
config: {},
|
115
142
|
routes: nil,
|
116
143
|
db: nil,
|
@@ -146,50 +173,60 @@ class Rackr
|
|
146
173
|
return Rack::Response.new(
|
147
174
|
erb,
|
148
175
|
status,
|
149
|
-
{ 'Content-Type' => 'text/html' }
|
176
|
+
{ 'Content-Type' => 'text/html' }.merge(headers)
|
150
177
|
)
|
151
178
|
end
|
152
179
|
|
153
|
-
[status, { 'Content-Type' => 'text/html' }, [erb]]
|
180
|
+
[status, { 'Content-Type' => 'text/html' }.merge(headers), [erb]]
|
154
181
|
end
|
155
182
|
|
156
|
-
def
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
183
|
+
def html(content = '', status: 200, headers: {}, &block)
|
184
|
+
if content == '' && block_given? && respond_to?(:html_slice)
|
185
|
+
if respond_to?(:layout)
|
186
|
+
content = layout(&block)
|
187
|
+
else
|
188
|
+
html_slice(:root, &block)
|
189
|
+
content = html_slice
|
190
|
+
end
|
191
|
+
end
|
163
192
|
|
164
|
-
|
165
|
-
[status, { 'Content-Type' => 'text/html' }, [content]]
|
193
|
+
[status, { 'Content-Type' => 'text/html' }.merge(headers), [content]]
|
166
194
|
end
|
167
195
|
|
168
|
-
def html_response(content, status: 200)
|
169
|
-
|
196
|
+
def html_response(content = '', status: 200, headers: {}, &block)
|
197
|
+
if content == '' && block_given? && respond_to?(:html_slice)
|
198
|
+
if respond_to?(:layout)
|
199
|
+
content = layout(&block)
|
200
|
+
else
|
201
|
+
html_slice(:root, &block)
|
202
|
+
content = html_slice
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
Rack::Response.new(content, status, { 'Content-Type' => 'text/html' }.merge(headers))
|
170
207
|
end
|
171
208
|
|
172
|
-
def json(content = {}, status: 200)
|
173
|
-
[status, { 'Content-Type' => 'application/json' }, [Oj.dump(content, mode: :compat)]]
|
209
|
+
def json(content = {}, status: 200, headers: {})
|
210
|
+
[status, { 'Content-Type' => 'application/json' }.merge(headers), [Oj.dump(content, mode: :compat)]]
|
174
211
|
end
|
175
212
|
|
176
|
-
def json_response(content = {}, status: 200)
|
213
|
+
def json_response(content = {}, status: 200, headers: {})
|
177
214
|
Rack::Response.new(
|
178
215
|
Oj.dump(content, mode: :compat),
|
179
216
|
status,
|
180
|
-
{ 'Content-Type' => 'application/json' }
|
217
|
+
{ 'Content-Type' => 'application/json' }.merge(headers)
|
181
218
|
)
|
182
219
|
end
|
183
220
|
|
184
|
-
def text(content, status: 200)
|
185
|
-
[status, { 'Content-Type' => 'text/plain' }, [content]]
|
221
|
+
def text(content, status: 200, headers: {})
|
222
|
+
[status, { 'Content-Type' => 'text/plain' }.merge(headers), [content]]
|
186
223
|
end
|
187
224
|
|
188
|
-
def text_response(content, status: 200)
|
225
|
+
def text_response(content, status: 200, headers: {})
|
189
226
|
Rack::Response.new(
|
190
227
|
content,
|
191
228
|
status,
|
192
|
-
{ 'Content-Type' => 'text/plain' }
|
229
|
+
{ 'Content-Type' => 'text/plain' }.merge(headers)
|
193
230
|
)
|
194
231
|
end
|
195
232
|
|
@@ -201,16 +238,24 @@ class Rackr
|
|
201
238
|
end
|
202
239
|
# rubocop:enable Lint/UnusedMethodArgument
|
203
240
|
|
204
|
-
def redirect_response(url)
|
241
|
+
def redirect_response(url, headers: {})
|
205
242
|
Rack::Response.new(
|
206
243
|
nil,
|
207
244
|
302,
|
208
|
-
{ 'Location' => url }
|
245
|
+
{ 'Location' => url }.merge(headers)
|
209
246
|
)
|
210
247
|
end
|
211
248
|
|
212
|
-
def redirect_to(url)
|
213
|
-
[302, { 'Location' => url }, []]
|
249
|
+
def redirect_to(url, headers: {})
|
250
|
+
[302, { 'Location' => url }.merge(headers), []]
|
251
|
+
end
|
252
|
+
|
253
|
+
def head(status, headers: {})
|
254
|
+
[status, headers, []]
|
255
|
+
end
|
256
|
+
|
257
|
+
def head_response(status, headers: {})
|
258
|
+
Rack::Response.new(nil, status, headers)
|
214
259
|
end
|
215
260
|
|
216
261
|
def response(body = nil, status = 200, headers = {})
|
data/lib/rackr/html.rb
ADDED
@@ -0,0 +1,139 @@
|
|
1
|
+
class Rackr
|
2
|
+
module HTML
|
3
|
+
# HTML as a first-class citizen in ruby code
|
4
|
+
# Faster than ERB.
|
5
|
+
|
6
|
+
TAGS = %i[
|
7
|
+
div
|
8
|
+
title
|
9
|
+
embed
|
10
|
+
meta
|
11
|
+
br
|
12
|
+
a
|
13
|
+
em
|
14
|
+
b
|
15
|
+
i
|
16
|
+
ul
|
17
|
+
ol
|
18
|
+
li
|
19
|
+
img
|
20
|
+
table
|
21
|
+
tbody
|
22
|
+
thead
|
23
|
+
tr
|
24
|
+
th
|
25
|
+
td
|
26
|
+
form
|
27
|
+
input
|
28
|
+
button
|
29
|
+
link
|
30
|
+
h1
|
31
|
+
h2
|
32
|
+
h3
|
33
|
+
h4
|
34
|
+
h5
|
35
|
+
h6
|
36
|
+
hr
|
37
|
+
span
|
38
|
+
label
|
39
|
+
iframe
|
40
|
+
template
|
41
|
+
main
|
42
|
+
footer
|
43
|
+
aside
|
44
|
+
source
|
45
|
+
section
|
46
|
+
small
|
47
|
+
script
|
48
|
+
nav
|
49
|
+
area
|
50
|
+
]
|
51
|
+
|
52
|
+
EMPTY_TAGS = %i[
|
53
|
+
area
|
54
|
+
br
|
55
|
+
embed
|
56
|
+
hr
|
57
|
+
img
|
58
|
+
input
|
59
|
+
link
|
60
|
+
meta
|
61
|
+
source
|
62
|
+
].freeze
|
63
|
+
|
64
|
+
def html_layout(&block)
|
65
|
+
html_slice(:root, &block)
|
66
|
+
end
|
67
|
+
|
68
|
+
def html_slice(type = nil, &block)
|
69
|
+
if block_given?
|
70
|
+
if type == :root
|
71
|
+
wrap = ['<!DOCTYPE html><html>', '</html>']
|
72
|
+
else
|
73
|
+
wrap = ['','']
|
74
|
+
end
|
75
|
+
@html_slice = wrap[0]
|
76
|
+
instance_eval(&block)
|
77
|
+
@html_slice << wrap[1]
|
78
|
+
else
|
79
|
+
@html_slice
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
TAGS.each do |name|
|
84
|
+
define_method name do |*args, &block|
|
85
|
+
tag(name, *args, &block)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def _(content)
|
90
|
+
@html_slice << content.to_s
|
91
|
+
end
|
92
|
+
|
93
|
+
def tag(tag_name, *args, &block)
|
94
|
+
content, attributes = parse_html_tag_arguments(args)
|
95
|
+
generate_and_append_html_tag(tag_name, content, attributes, &block)
|
96
|
+
end
|
97
|
+
|
98
|
+
private
|
99
|
+
|
100
|
+
def parse_html_tag_arguments(args)
|
101
|
+
content = ''
|
102
|
+
attributes = {}
|
103
|
+
|
104
|
+
first_argument = args.shift
|
105
|
+
if first_argument.is_a?(String)
|
106
|
+
content = CGI.escapeHTML(first_argument)
|
107
|
+
attributes = args.pop || {}
|
108
|
+
elsif first_argument.is_a?(Hash)
|
109
|
+
attributes = first_argument
|
110
|
+
end
|
111
|
+
|
112
|
+
[content, attributes]
|
113
|
+
end
|
114
|
+
|
115
|
+
def generate_and_append_html_tag(tag_name, content, attributes, &block)
|
116
|
+
open_tag = build_html_open_tag(tag_name, attributes)
|
117
|
+
|
118
|
+
if block_given?
|
119
|
+
@html_slice << open_tag << ">"
|
120
|
+
instance_eval(&block)
|
121
|
+
@html_slice << "</#{tag_name}>"
|
122
|
+
else
|
123
|
+
if content.empty? && EMPTY_TAGS.include?(tag_name)
|
124
|
+
@html_slice << open_tag << "/>"
|
125
|
+
else
|
126
|
+
@html_slice << open_tag << ">" << content << "</#{tag_name}>"
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def build_html_open_tag(tag_name, attributes)
|
132
|
+
open_tag = "<#{tag_name}"
|
133
|
+
attributes.each do |key, value|
|
134
|
+
open_tag << " #{key.to_s.gsub('_', '-')}='#{value}'"
|
135
|
+
end
|
136
|
+
open_tag
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
class Rackr
|
2
|
+
class Router
|
3
|
+
module Errors
|
4
|
+
class DevHtml
|
5
|
+
include Rackr::Action
|
6
|
+
include Rackr::HTML
|
7
|
+
|
8
|
+
def call(env)
|
9
|
+
html do
|
10
|
+
tag :head do
|
11
|
+
title 'Application error'
|
12
|
+
tag :style, %q(
|
13
|
+
body {
|
14
|
+
margin: 0 auto;
|
15
|
+
width: 98.5%;
|
16
|
+
font-size: 1.1em;
|
17
|
+
background-color: #666666;
|
18
|
+
font-family: monospace;
|
19
|
+
margin-top: 1em;
|
20
|
+
}
|
21
|
+
p {
|
22
|
+
background-color: #000000;
|
23
|
+
padding: 1em;
|
24
|
+
font-size: 1.3em;
|
25
|
+
}
|
26
|
+
div {
|
27
|
+
background-color: #191919;
|
28
|
+
color: white;
|
29
|
+
padding: 0em 2em;
|
30
|
+
border: 5px solid #ffffff;
|
31
|
+
border-radius: 1em;
|
32
|
+
}
|
33
|
+
h1 {
|
34
|
+
background-color: #464646;
|
35
|
+
padding: 1em;
|
36
|
+
border-radius: 0.2em;
|
37
|
+
}
|
38
|
+
)
|
39
|
+
end
|
40
|
+
tag :body do
|
41
|
+
div do
|
42
|
+
h1 env['error'].inspect
|
43
|
+
backtrace(env)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def backtrace(env)
|
50
|
+
first, *tail = env['error'].backtrace
|
51
|
+
|
52
|
+
tag :p, first, class: "first-p"
|
53
|
+
|
54
|
+
line_number = extract_line_number(first)
|
55
|
+
match = first.match(%r{^(\/[\w\/.-]+)})
|
56
|
+
file_path = (match ? match[1] : nil)
|
57
|
+
if file_path != nil
|
58
|
+
lines = []
|
59
|
+
File.open(file_path) do |file|
|
60
|
+
lines = file.readlines
|
61
|
+
end
|
62
|
+
|
63
|
+
lines.map!.with_index do |line, i|
|
64
|
+
"#{i+1}: #{line} \n"
|
65
|
+
end
|
66
|
+
|
67
|
+
tag :pre, slice_around_index(lines, line_number).join("")
|
68
|
+
end
|
69
|
+
|
70
|
+
hr
|
71
|
+
tag :p, tail.join("\n")
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
def extract_line_number(input)
|
76
|
+
if match = input.match(/:(\d+):in/)
|
77
|
+
match[1].to_i
|
78
|
+
else
|
79
|
+
nil
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def slice_around_index(array, index)
|
84
|
+
return array if index == nil || index < 1
|
85
|
+
|
86
|
+
index -= 1
|
87
|
+
start_index = [index - 2, 0].max
|
88
|
+
end_index = [index + 2, array.size - 1].min
|
89
|
+
|
90
|
+
# Slice the array
|
91
|
+
array[start_index..end_index]
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
data/lib/rackr/router/errors.rb
CHANGED
@@ -12,10 +12,16 @@ class Rackr
|
|
12
12
|
class InvalidBranchNameError < Error; end
|
13
13
|
|
14
14
|
class << self
|
15
|
-
def
|
16
|
-
return if path.is_a?(String) || path.is_a?(Symbol)
|
15
|
+
def check_scope_name(path)
|
16
|
+
return if path.is_a?(String) || path.is_a?(Symbol) || path == nil
|
17
17
|
|
18
|
-
raise(InvalidBranchNameError, "Route
|
18
|
+
raise(InvalidBranchNameError, "Route scope name must be a `string` or a `symbol`, got: '#{path}'")
|
19
|
+
end
|
20
|
+
|
21
|
+
def check_scope_slashes(path)
|
22
|
+
if path.is_a?(String) && path.include?('/')
|
23
|
+
raise(InvalidBranchNameError, "Avoid slashes in scope name, use nested scopes instead, got: '#{path}'")
|
24
|
+
end
|
19
25
|
end
|
20
26
|
|
21
27
|
def check_path(path)
|
@@ -28,7 +34,7 @@ class Rackr
|
|
28
34
|
return if as.is_a?(String) || as.is_a?(Symbol) || as.nil?
|
29
35
|
|
30
36
|
raise(InvalidNamedRouteError,
|
31
|
-
"as: argument in routes and
|
37
|
+
"as: argument in routes and scopes must be a `string` or a `symbol`, got: '#{as}' for '#{path}'")
|
32
38
|
end
|
33
39
|
|
34
40
|
def check_callbacks(callbacks, path)
|
data/lib/rackr/router/route.rb
CHANGED
@@ -9,7 +9,7 @@ class Rackr
|
|
9
9
|
:has_afters,
|
10
10
|
:afters
|
11
11
|
|
12
|
-
def initialize(path, endpoint, befores: [], afters: [])
|
12
|
+
def initialize(path, endpoint, befores: [], afters: [], wildcard: false)
|
13
13
|
@path = path
|
14
14
|
@splitted_path = @path.split('/')
|
15
15
|
@endpoint = endpoint
|
@@ -20,12 +20,14 @@ class Rackr
|
|
20
20
|
@afters = afters
|
21
21
|
@has_afters = afters != []
|
22
22
|
@path_regex = /\A#{path.gsub(/(:\w+)/, '([^/]+)')}\z/
|
23
|
+
@wildcard = wildcard
|
23
24
|
end
|
24
25
|
|
25
|
-
def match?(
|
26
|
-
return
|
26
|
+
def match?(path_info)
|
27
|
+
return path_info.match?(@path_regex) if @has_params
|
28
|
+
return true if @wildcard
|
27
29
|
|
28
|
-
|
30
|
+
path_info == @path
|
29
31
|
end
|
30
32
|
|
31
33
|
private
|
data/lib/rackr/router.rb
CHANGED
@@ -21,27 +21,29 @@ class Rackr
|
|
21
21
|
raise(Errors::UndefinedNamedRouteError, "Undefined named route: '#{key}'")
|
22
22
|
end)
|
23
23
|
end
|
24
|
-
|
24
|
+
@dev_mode = ENV['RACK_ENV'] == 'development'
|
25
25
|
@config = config
|
26
|
-
@
|
26
|
+
@scopes = []
|
27
27
|
@befores = ensure_array(before)
|
28
|
-
@
|
28
|
+
@scopes_befores = {}
|
29
29
|
@afters = ensure_array(after)
|
30
|
-
@
|
30
|
+
@scopes_afters = {}
|
31
31
|
@error = proc { |_req, e| raise e }
|
32
32
|
@not_found = proc { [404, {}, ['Not found']] }
|
33
|
-
@
|
33
|
+
@splitted_request_path_info = []
|
34
|
+
@current_request_path_info = nil
|
34
35
|
end
|
35
36
|
|
36
37
|
def call(env)
|
37
|
-
@
|
38
|
+
@splitted_request_path_info = env['PATH_INFO'].split('/')
|
39
|
+
@current_request_path_info =
|
40
|
+
(env['PATH_INFO'] == '/') ? env['PATH_INFO'] : env['PATH_INFO'].sub(/\/\z/, '') # remove trailing "/"
|
38
41
|
|
39
|
-
request_builder = BuildRequest.new(env, @
|
42
|
+
request_builder = BuildRequest.new(env, @splitted_request_path_info)
|
40
43
|
env['REQUEST_METHOD'] = 'GET' if env['REQUEST_METHOD'] == 'HEAD'
|
41
44
|
|
42
45
|
route_instance = match_route(env)
|
43
|
-
|
44
|
-
return render_not_found(request_builder.call) if route_instance.nil?
|
46
|
+
return call_endpoint(@not_found, request_builder.call) if route_instance.nil?
|
45
47
|
|
46
48
|
rack_request = request_builder.call(route_instance)
|
47
49
|
|
@@ -68,9 +70,11 @@ class Rackr
|
|
68
70
|
|
69
71
|
endpoint_result
|
70
72
|
rescue Rackr::NotFound
|
71
|
-
|
73
|
+
call_endpoint(@not_found, request_builder.call)
|
72
74
|
rescue Exception => e
|
73
|
-
@error.call(request_builder.call, e)
|
75
|
+
return @error.call(request_builder.call, e) unless @dev_mode
|
76
|
+
|
77
|
+
call_endpoint(Errors::DevHtml, env.merge({'error' => e}))
|
74
78
|
end
|
75
79
|
|
76
80
|
def add(method, path, endpoint, as: nil, route_befores: [], route_afters: [])
|
@@ -82,18 +86,21 @@ class Rackr
|
|
82
86
|
|
83
87
|
method = :get if method == :head
|
84
88
|
|
85
|
-
|
86
|
-
|
89
|
+
wildcard = (path == '*') ? true : false
|
90
|
+
path = path.sub(/\A\//, '')
|
91
|
+
path_with_scopes = "/#{not_empty_scopes.join('/')}#{put_path_slash(path)}"
|
92
|
+
add_named_route(method, path_with_scopes, as)
|
87
93
|
|
88
94
|
route_instance =
|
89
95
|
Route.new(
|
90
|
-
|
96
|
+
path_with_scopes,
|
91
97
|
endpoint,
|
92
98
|
befores: @befores + ensure_array(route_befores),
|
93
|
-
afters: @afters + ensure_array(route_afters)
|
99
|
+
afters: @afters + ensure_array(route_afters),
|
100
|
+
wildcard: wildcard
|
94
101
|
)
|
95
102
|
|
96
|
-
return
|
103
|
+
return push_to_scope(method.to_s.upcase, route_instance) if @scopes.size >= 1
|
97
104
|
|
98
105
|
@instance_routes[method.to_s.upcase][:__instances].push(route_instance)
|
99
106
|
end
|
@@ -110,28 +117,29 @@ class Rackr
|
|
110
117
|
@error = endpoint
|
111
118
|
end
|
112
119
|
|
113
|
-
def
|
114
|
-
Errors.
|
115
|
-
Errors.
|
116
|
-
Errors.check_callbacks(
|
120
|
+
def append_scope(name, scope_befores: [], scope_afters: [])
|
121
|
+
Errors.check_scope_name(name)
|
122
|
+
Errors.check_scope_slashes(name)
|
123
|
+
Errors.check_callbacks(scope_befores, name)
|
124
|
+
Errors.check_callbacks(scope_afters, name)
|
117
125
|
|
118
126
|
name = ":#{name}" if name.is_a? Symbol
|
119
127
|
|
120
|
-
@
|
128
|
+
@scopes.push(name)
|
121
129
|
|
122
|
-
|
123
|
-
@befores.concat(
|
124
|
-
@
|
130
|
+
scope_befores = ensure_array(scope_befores)
|
131
|
+
@befores.concat(scope_befores)
|
132
|
+
@scopes_befores[name] = scope_befores
|
125
133
|
|
126
|
-
|
127
|
-
@afters.concat(
|
128
|
-
@
|
134
|
+
scope_afters = ensure_array(scope_afters)
|
135
|
+
@afters.concat(scope_afters)
|
136
|
+
@scopes_afters[name] = scope_afters
|
129
137
|
end
|
130
138
|
|
131
|
-
def
|
132
|
-
@befores -= @
|
133
|
-
@afters -= @
|
134
|
-
@
|
139
|
+
def clear_last_scope
|
140
|
+
@befores -= @scopes_befores[@scopes.last]
|
141
|
+
@afters -= @scopes_afters[@scopes.last]
|
142
|
+
@scopes = @scopes.first(@scopes.size - 1)
|
135
143
|
end
|
136
144
|
|
137
145
|
private
|
@@ -153,17 +161,17 @@ class Rackr
|
|
153
161
|
[list]
|
154
162
|
end
|
155
163
|
|
156
|
-
def add_named_route(method,
|
157
|
-
return @routes.send(method.downcase)[:root] =
|
158
|
-
return @routes.send(method.downcase)[as] =
|
164
|
+
def add_named_route(method, path_with_scopes, as)
|
165
|
+
return @routes.send(method.downcase)[:root] = path_with_scopes if path_with_scopes == '/'
|
166
|
+
return @routes.send(method.downcase)[as] = path_with_scopes unless as.nil?
|
159
167
|
|
160
|
-
key =
|
161
|
-
@routes.send(method.downcase)["#{key}".to_sym] =
|
168
|
+
key = path_with_scopes.sub("/","").gsub(":","").gsub("/","_")
|
169
|
+
@routes.send(method.downcase)["#{key}".to_sym] = path_with_scopes
|
162
170
|
end
|
163
171
|
|
164
|
-
def
|
165
|
-
|
166
|
-
push_it(@instance_routes[method], *
|
172
|
+
def push_to_scope(method, route_instance)
|
173
|
+
scopes_with_slash = not_empty_scopes + %i[__instances]
|
174
|
+
push_it(@instance_routes[method], *scopes_with_slash, route_instance)
|
167
175
|
end
|
168
176
|
|
169
177
|
def push_it(hash, first_key, *rest_keys, val)
|
@@ -176,47 +184,47 @@ class Rackr
|
|
176
184
|
end
|
177
185
|
|
178
186
|
def put_path_slash(path)
|
179
|
-
|
180
|
-
|
187
|
+
if not_empty_scopes != []
|
188
|
+
return '' if ['/', ''].include?(path)
|
189
|
+
return "/#{path}"
|
190
|
+
end
|
181
191
|
|
182
192
|
path
|
183
193
|
end
|
184
194
|
|
185
|
-
def
|
186
|
-
|
187
|
-
|
188
|
-
@not_found.new.call(env)
|
195
|
+
def not_empty_scopes
|
196
|
+
@scopes.reject { |v| (v == '') }
|
189
197
|
end
|
190
198
|
|
191
|
-
def match_route(env, last_tail = nil,
|
199
|
+
def match_route(env, last_tail = nil, found_scopes = [])
|
192
200
|
instance_routes =
|
193
201
|
if last_tail.nil?
|
194
|
-
last_tail = @
|
202
|
+
last_tail = @splitted_request_path_info.drop(1)
|
195
203
|
|
196
204
|
@instance_routes[env['REQUEST_METHOD']]
|
197
205
|
else
|
198
|
-
@instance_routes[env['REQUEST_METHOD']].dig(*
|
206
|
+
@instance_routes[env['REQUEST_METHOD']].dig(*found_scopes)
|
199
207
|
end
|
200
208
|
|
201
209
|
segment, *tail = last_tail
|
202
210
|
|
203
|
-
instance_routes.each do |
|
204
|
-
next if
|
211
|
+
instance_routes.each do |scope, _v|
|
212
|
+
next if scope == :__instances
|
205
213
|
|
206
|
-
if segment ==
|
207
|
-
|
214
|
+
if segment == scope || scope.start_with?(':')
|
215
|
+
found_scopes.push(scope)
|
208
216
|
break
|
209
217
|
end
|
210
218
|
end
|
211
219
|
|
212
|
-
if tail.empty? ||
|
220
|
+
if tail.empty? || found_scopes == []
|
213
221
|
return @instance_routes[env['REQUEST_METHOD']].dig(
|
214
|
-
*(
|
222
|
+
*(found_scopes << :__instances)
|
215
223
|
)
|
216
|
-
&.detect { |route_instance| route_instance.match?(
|
224
|
+
&.detect { |route_instance| route_instance.match?(@current_request_path_info) }
|
217
225
|
end
|
218
226
|
|
219
|
-
match_route(env, tail,
|
227
|
+
match_route(env, tail, found_scopes)
|
220
228
|
end
|
221
229
|
end
|
222
230
|
end
|
data/lib/rackr.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative 'rackr/router'
|
4
3
|
require_relative 'rackr/action'
|
5
4
|
require_relative 'rackr/callback'
|
5
|
+
require_relative 'rackr/html'
|
6
|
+
require_relative 'rackr/router/errors/dev_html'
|
7
|
+
require_relative 'rackr/router'
|
6
8
|
|
7
9
|
class Rackr
|
8
10
|
class NotFound < StandardError; end
|
@@ -10,6 +12,7 @@ class Rackr
|
|
10
12
|
HTTP_METHODS = %w[GET POST DELETE PUT TRACE OPTIONS PATCH]
|
11
13
|
|
12
14
|
include Action
|
15
|
+
include HTML
|
13
16
|
|
14
17
|
def initialize(config = {}, before: [], after: [])
|
15
18
|
@router = Router.new(config, before: before, after: after)
|
@@ -33,15 +36,15 @@ class Rackr
|
|
33
36
|
@router.config[:db]
|
34
37
|
end
|
35
38
|
|
36
|
-
def
|
37
|
-
@router.
|
39
|
+
def scope(name = '', before: [], after: [], &block)
|
40
|
+
@router.append_scope(
|
38
41
|
name,
|
39
|
-
|
40
|
-
|
42
|
+
scope_befores: before,
|
43
|
+
scope_afters: after,
|
41
44
|
)
|
42
45
|
instance_eval(&block)
|
43
46
|
|
44
|
-
@router.
|
47
|
+
@router.clear_last_scope
|
45
48
|
end
|
46
49
|
|
47
50
|
def not_found(endpoint = -> {}, &block)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rackr
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.50
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Henrique F. Teixeira
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-12-
|
11
|
+
date: 2024-12-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: erubi
|
@@ -67,9 +67,11 @@ files:
|
|
67
67
|
- lib/rackr.rb
|
68
68
|
- lib/rackr/action.rb
|
69
69
|
- lib/rackr/callback.rb
|
70
|
+
- lib/rackr/html.rb
|
70
71
|
- lib/rackr/router.rb
|
71
72
|
- lib/rackr/router/build_request.rb
|
72
73
|
- lib/rackr/router/errors.rb
|
74
|
+
- lib/rackr/router/errors/dev_html.rb
|
73
75
|
- lib/rackr/router/route.rb
|
74
76
|
homepage: https://github.com/henrique-ft/rackr
|
75
77
|
licenses:
|