rack-server-pages 0.2.0 → 0.3.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/CHANGES.md +22 -0
- data/README.md +222 -78
- data/RELEASING.md +79 -0
- data/UPGRADING.md +23 -0
- data/lib/rack/server_pages.rb +84 -7
- data/lib/rack-server-pages/version.rb +1 -1
- data/rack-server-pages.gemspec +3 -6
- metadata +8 -63
- data/.github/workflows/lint.yml +0 -15
- data/.github/workflows/test.yml +0 -37
- data/.gitignore +0 -11
- data/.rspec +0 -2
- data/.rubocop.yml +0 -10
- data/.rubocop_todo.yml +0 -372
- data/Gemfile +0 -46
- data/Guardfile +0 -16
- data/Rakefile +0 -12
- data/config.ru +0 -49
- data/public/CHANGES.erb +0 -3
- data/public/README.erb +0 -3
- data/public/_layout.html.erb +0 -9
- data/public/folder/sample.erb +0 -14
- data/public/folder/special-sub.folder-@/sample.erb +0 -14
- data/public/folder/subfolder/(sub-folder)/sample-in-sub-folder.extension.erb +0 -14
- data/public/folder/subfolder/sample.erb +0 -14
- data/public/folder//320/277/320/276-/321/200/321/203/321/201/321/201/320/272/320/270//320/277/321/200/320/270/320/274/320/265/321/200.erb +0 -14
- data/public/index.html +0 -23
- data/public/info.php +0 -89
- data/public/rack_logo.png +0 -0
- data/public/rack_logo@2x.png +0 -0
- data/public/sample.erb +0 -14
- data/public/style.css.sass +0 -99
- data/views/about.html.slim +0 -11
- data/views/article.html.md +0 -16
- data/views/betty.css.sass +0 -11
- data/views/contact.xml.builder +0 -5
- data/views/examples/_layout.html.erb +0 -14
- data/views/examples/_time.html.erb +0 -4
- data/views/examples/builder.xml.builder +0 -2
- data/views/examples/coffee.js.coffee +0 -0
- data/views/examples/erb.html.erb +0 -2
- data/views/examples/haml.html.haml +0 -6
- data/views/examples/html.html +0 -1
- data/views/examples/index.html.erb +0 -9
- data/views/examples/less.css.less +0 -0
- data/views/examples/liquid.html.liquid +0 -0
- data/views/examples/markaby.html.mab +0 -0
- data/views/examples/markdown.html.markdown +0 -6
- data/views/examples/nokogiri.xml.nokogiri +0 -1
- data/views/examples/radius.html.radius +0 -0
- data/views/examples/rdoc.html.rdoc +0 -0
- data/views/examples/robots.txt +0 -1
- data/views/examples/sass.css.sass +0 -11
- data/views/examples/scss.css.scss +0 -0
- data/views/examples/slim.html.slim +0 -2
- data/views/examples/source.html.slim +0 -9
- data/views/examples/textile.html.textile +0 -0
- data/views/examples/wiki.html.wiki +0 -0
- data/views/examples/yajl.json.yajl +0 -0
- data/views/script.js.coffee +0 -13
data/lib/rack/server_pages.rb
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
require 'rack'
|
|
3
3
|
require 'rack/utils'
|
|
4
4
|
require 'rack/mime'
|
|
5
|
-
require 'rack/logger'
|
|
6
5
|
require 'time'
|
|
7
6
|
require 'forwardable'
|
|
7
|
+
require 'digest/sha2'
|
|
8
8
|
|
|
9
9
|
module Rack
|
|
10
10
|
class ServerPages
|
|
@@ -40,10 +40,49 @@ module Rack
|
|
|
40
40
|
@app
|
|
41
41
|
else
|
|
42
42
|
file = select_template_file(files)
|
|
43
|
-
(tpl = Template[file]) ? server_page(tpl) :
|
|
43
|
+
(tpl = Template[file]) ? server_page(tpl) : static_file(file, path_info)
|
|
44
44
|
end.call(env)
|
|
45
45
|
end
|
|
46
46
|
|
|
47
|
+
module StaticFiles
|
|
48
|
+
def static_file(file, path_info)
|
|
49
|
+
root = file.split(path_info).first
|
|
50
|
+
return Rack::Files.new(root) unless ::File.file?(file) && ::File.readable?(file)
|
|
51
|
+
|
|
52
|
+
headers = static_headers(file)
|
|
53
|
+
files = Rack::Files.new(root, headers)
|
|
54
|
+
lambda do |env|
|
|
55
|
+
if @config.static_etags && %w[GET HEAD].include?(env['REQUEST_METHOD']) && matching_etag?(env['HTTP_IF_NONE_MATCH'], headers[Rack::ETAG])
|
|
56
|
+
[304, headers.dup, []]
|
|
57
|
+
else
|
|
58
|
+
files.call(static_request_env(env))
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
private
|
|
64
|
+
|
|
65
|
+
def static_request_env(env)
|
|
66
|
+
# If-None-Match takes precedence over If-Modified-Since.
|
|
67
|
+
ignore_modified_since = !@config.static_timestamps || (@config.static_etags && env.key?('HTTP_IF_NONE_MATCH'))
|
|
68
|
+
ignore_modified_since ? env.merge('HTTP_IF_MODIFIED_SINCE' => nil) : env
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def static_headers(file)
|
|
72
|
+
headers = @config.static_etags ? { Rack::ETAG => %("#{Digest::SHA256.file(file).hexdigest}") } : {}
|
|
73
|
+
@config.static_cache_control ? headers.merge(Rack::CACHE_CONTROL => @config.static_cache_control) : headers
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def matching_etag?(condition, etag)
|
|
77
|
+
condition.to_s.split(',').any? do |candidate|
|
|
78
|
+
candidate = candidate.strip.sub(%r{\AW/}, '')
|
|
79
|
+
candidate == '*' || candidate == etag
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
include StaticFiles
|
|
85
|
+
|
|
47
86
|
def find_template_files(path_info)
|
|
48
87
|
if m = path_info.match(@path_regex)
|
|
49
88
|
@config.view_paths.inject([]) do |files, path|
|
|
@@ -67,7 +106,7 @@ module Rack
|
|
|
67
106
|
|
|
68
107
|
def server_page(template)
|
|
69
108
|
lambda do |env|
|
|
70
|
-
@binding.new(env).tap do |scope|
|
|
109
|
+
@binding.new(env, self).tap do |scope|
|
|
71
110
|
catch(:halt) do
|
|
72
111
|
begin
|
|
73
112
|
@config.filter.invoke(scope, :before)
|
|
@@ -88,6 +127,36 @@ module Rack
|
|
|
88
127
|
end
|
|
89
128
|
end
|
|
90
129
|
|
|
130
|
+
module AssetPaths
|
|
131
|
+
def asset_path(path)
|
|
132
|
+
path, fragment = path.to_s.split('#', 2)
|
|
133
|
+
path, query = path.to_s.split('?', 2)
|
|
134
|
+
path, file = asset_file(path.to_s)
|
|
135
|
+
query = Rack::Utils.parse_query(query)
|
|
136
|
+
query['v'] = Digest::SHA256.file(file).hexdigest
|
|
137
|
+
"#{path}?#{Rack::Utils.build_query(query)}#{fragment && "##{fragment}"}"
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
private
|
|
141
|
+
|
|
142
|
+
def asset_file(path)
|
|
143
|
+
raise ArgumentError, 'asset_path requires a local asset path without parent-directory traversal' unless valid_asset_path?(CGI.unescape(path))
|
|
144
|
+
|
|
145
|
+
path = "#{@config.effective_path}/#{path.sub(%r{\A/}, '')}"
|
|
146
|
+
file = select_template_file(find_template_files(CGI.unescape(path)) || [])
|
|
147
|
+
raise Errno::ENOENT, path unless file && ::File.file?(file)
|
|
148
|
+
|
|
149
|
+
[path, file]
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def valid_asset_path?(path)
|
|
153
|
+
!path.empty? && (path !~ %r{\A(?:[a-z][a-z0-9+.-]*:|//)}i) &&
|
|
154
|
+
!path.split('/').include?('..') && !path.include?("\0")
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
include AssetPaths
|
|
159
|
+
|
|
91
160
|
class Filter
|
|
92
161
|
TYPES = [:before, :after, :on_error].freeze
|
|
93
162
|
TYPES.each do |type|
|
|
@@ -144,7 +213,8 @@ module Rack
|
|
|
144
213
|
end
|
|
145
214
|
end
|
|
146
215
|
|
|
147
|
-
hash_accessor :view_path, :effective_path, :cache_control, :
|
|
216
|
+
hash_accessor :view_path, :effective_path, :cache_control, :static_cache_control, :static_etags, :static_timestamps,
|
|
217
|
+
:default_charset, :failure_app, :show_exceptions
|
|
148
218
|
|
|
149
219
|
attr_reader :filter
|
|
150
220
|
|
|
@@ -154,6 +224,8 @@ module Rack
|
|
|
154
224
|
super
|
|
155
225
|
self[:default_charset] ||= 'utf-8'
|
|
156
226
|
self[:view_path] ||= %w(views public)
|
|
227
|
+
self[:static_etags] = true
|
|
228
|
+
self[:static_timestamps] = true
|
|
157
229
|
@helpers = []
|
|
158
230
|
@filter = Filter.new
|
|
159
231
|
end
|
|
@@ -188,7 +260,7 @@ module Rack
|
|
|
188
260
|
end
|
|
189
261
|
|
|
190
262
|
def tilt?
|
|
191
|
-
@use_tilt
|
|
263
|
+
@use_tilt != false && !!defined?(Tilt) && Tilt.respond_to?(:[])
|
|
192
264
|
end
|
|
193
265
|
|
|
194
266
|
def use_tilt(bool = true)
|
|
@@ -274,6 +346,10 @@ module Rack
|
|
|
274
346
|
end
|
|
275
347
|
|
|
276
348
|
module CoreHelper
|
|
349
|
+
def asset_path(path)
|
|
350
|
+
url(@server_pages.asset_path(path))
|
|
351
|
+
end
|
|
352
|
+
|
|
277
353
|
def redirect(target, status = 302)
|
|
278
354
|
response.redirect(target, status)
|
|
279
355
|
halt
|
|
@@ -315,7 +391,7 @@ module Rack
|
|
|
315
391
|
|
|
316
392
|
attr_reader :request, :response
|
|
317
393
|
|
|
318
|
-
def_delegators :request, :env, :params, :session, :cookies
|
|
394
|
+
def_delegators :request, :env, :params, :session, :cookies
|
|
319
395
|
def_delegators :response, :headers, :set_cookies, :delete_cookie
|
|
320
396
|
|
|
321
397
|
class << self
|
|
@@ -330,9 +406,10 @@ module Rack
|
|
|
330
406
|
end
|
|
331
407
|
end
|
|
332
408
|
|
|
333
|
-
def initialize(env)
|
|
409
|
+
def initialize(env, server_pages = nil)
|
|
334
410
|
@request = Rack::Request.new(env)
|
|
335
411
|
@response = Rack::Response.new
|
|
412
|
+
@server_pages = server_pages
|
|
336
413
|
# @response['Content-Type'] = nil
|
|
337
414
|
end
|
|
338
415
|
|
data/rack-server-pages.gemspec
CHANGED
|
@@ -9,13 +9,10 @@ Gem::Specification.new do |s|
|
|
|
9
9
|
s.email = ['m@igrs.jp']
|
|
10
10
|
s.homepage = 'http://github.com/migrs/rack-server-pages'
|
|
11
11
|
s.licenses = ['MIT']
|
|
12
|
-
s.summary = 'Rack middleware and appilcation for serving dynamic pages
|
|
13
|
-
s.description = 'Rack middleware and appilcation for serving dynamic pages in very simple way.
|
|
14
|
-
There are no controllers and no models, just only views like a asp, jsp and php!'
|
|
12
|
+
s.summary = 'Rack middleware and appilcation for serving dynamic pages.'
|
|
13
|
+
s.description = 'Rack middleware and appilcation for serving dynamic pages in very simple way, without controllers or models, only views similar to ASP, JSP and PHP.'
|
|
15
14
|
|
|
16
|
-
s.files =
|
|
17
|
-
f.match(%r{^(spec)/})
|
|
18
|
-
end
|
|
15
|
+
s.files = Dir['lib/**/*', 'CHANGES.md', 'README.md', 'UPGRADING.md', 'RELEASING.md', 'LICENSE.md', 'rack-server-pages.gemspec']
|
|
19
16
|
|
|
20
17
|
s.require_paths = ['lib']
|
|
21
18
|
|
metadata
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rack-server-pages
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Masato Igarashi
|
|
8
8
|
- Daniel Doubrovkine
|
|
9
|
-
autorequire:
|
|
10
9
|
bindir: bin
|
|
11
10
|
cert_chain: []
|
|
12
|
-
date:
|
|
11
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
13
12
|
dependencies:
|
|
14
13
|
- !ruby/object:Gem::Dependency
|
|
15
14
|
name: rack
|
|
@@ -25,79 +24,27 @@ dependencies:
|
|
|
25
24
|
- - ">="
|
|
26
25
|
- !ruby/object:Gem::Version
|
|
27
26
|
version: '0'
|
|
28
|
-
description:
|
|
29
|
-
|
|
30
|
-
There are no controllers and no models, just only views like a asp, jsp and php!
|
|
27
|
+
description: Rack middleware and appilcation for serving dynamic pages in very simple
|
|
28
|
+
way, without controllers or models, only views similar to ASP, JSP and PHP.
|
|
31
29
|
email:
|
|
32
30
|
- m@igrs.jp
|
|
33
31
|
executables: []
|
|
34
32
|
extensions: []
|
|
35
33
|
extra_rdoc_files: []
|
|
36
34
|
files:
|
|
37
|
-
- ".github/workflows/lint.yml"
|
|
38
|
-
- ".github/workflows/test.yml"
|
|
39
|
-
- ".gitignore"
|
|
40
|
-
- ".rspec"
|
|
41
|
-
- ".rubocop.yml"
|
|
42
|
-
- ".rubocop_todo.yml"
|
|
43
35
|
- CHANGES.md
|
|
44
|
-
- Gemfile
|
|
45
|
-
- Guardfile
|
|
46
36
|
- LICENSE.md
|
|
47
37
|
- README.md
|
|
48
|
-
-
|
|
49
|
-
-
|
|
38
|
+
- RELEASING.md
|
|
39
|
+
- UPGRADING.md
|
|
50
40
|
- lib/rack-server-pages.rb
|
|
51
41
|
- lib/rack-server-pages/version.rb
|
|
52
42
|
- lib/rack/server_pages.rb
|
|
53
|
-
- public/CHANGES.erb
|
|
54
|
-
- public/README.erb
|
|
55
|
-
- public/_layout.html.erb
|
|
56
|
-
- public/folder/sample.erb
|
|
57
|
-
- public/folder/special-sub.folder-@/sample.erb
|
|
58
|
-
- public/folder/subfolder/(sub-folder)/sample-in-sub-folder.extension.erb
|
|
59
|
-
- public/folder/subfolder/sample.erb
|
|
60
|
-
- public/folder/по-русски/пример.erb
|
|
61
|
-
- public/index.html
|
|
62
|
-
- public/info.php
|
|
63
|
-
- public/rack_logo.png
|
|
64
|
-
- public/rack_logo@2x.png
|
|
65
|
-
- public/sample.erb
|
|
66
|
-
- public/style.css.sass
|
|
67
43
|
- rack-server-pages.gemspec
|
|
68
|
-
- views/about.html.slim
|
|
69
|
-
- views/article.html.md
|
|
70
|
-
- views/betty.css.sass
|
|
71
|
-
- views/contact.xml.builder
|
|
72
|
-
- views/examples/_layout.html.erb
|
|
73
|
-
- views/examples/_time.html.erb
|
|
74
|
-
- views/examples/builder.xml.builder
|
|
75
|
-
- views/examples/coffee.js.coffee
|
|
76
|
-
- views/examples/erb.html.erb
|
|
77
|
-
- views/examples/haml.html.haml
|
|
78
|
-
- views/examples/html.html
|
|
79
|
-
- views/examples/index.html.erb
|
|
80
|
-
- views/examples/less.css.less
|
|
81
|
-
- views/examples/liquid.html.liquid
|
|
82
|
-
- views/examples/markaby.html.mab
|
|
83
|
-
- views/examples/markdown.html.markdown
|
|
84
|
-
- views/examples/nokogiri.xml.nokogiri
|
|
85
|
-
- views/examples/radius.html.radius
|
|
86
|
-
- views/examples/rdoc.html.rdoc
|
|
87
|
-
- views/examples/robots.txt
|
|
88
|
-
- views/examples/sass.css.sass
|
|
89
|
-
- views/examples/scss.css.scss
|
|
90
|
-
- views/examples/slim.html.slim
|
|
91
|
-
- views/examples/source.html.slim
|
|
92
|
-
- views/examples/textile.html.textile
|
|
93
|
-
- views/examples/wiki.html.wiki
|
|
94
|
-
- views/examples/yajl.json.yajl
|
|
95
|
-
- views/script.js.coffee
|
|
96
44
|
homepage: http://github.com/migrs/rack-server-pages
|
|
97
45
|
licenses:
|
|
98
46
|
- MIT
|
|
99
47
|
metadata: {}
|
|
100
|
-
post_install_message:
|
|
101
48
|
rdoc_options: []
|
|
102
49
|
require_paths:
|
|
103
50
|
- lib
|
|
@@ -112,9 +59,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
112
59
|
- !ruby/object:Gem::Version
|
|
113
60
|
version: '0'
|
|
114
61
|
requirements: []
|
|
115
|
-
rubygems_version:
|
|
116
|
-
signing_key:
|
|
62
|
+
rubygems_version: 4.0.20
|
|
117
63
|
specification_version: 4
|
|
118
|
-
summary: Rack middleware and appilcation for serving dynamic pages
|
|
119
|
-
way.
|
|
64
|
+
summary: Rack middleware and appilcation for serving dynamic pages.
|
|
120
65
|
test_files: []
|
data/.github/workflows/lint.yml
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
name: lint
|
|
2
|
-
on: [push, pull_request]
|
|
3
|
-
jobs:
|
|
4
|
-
rubocop:
|
|
5
|
-
name: RuboCop
|
|
6
|
-
runs-on: ubuntu-latest
|
|
7
|
-
steps:
|
|
8
|
-
- name: Checkout
|
|
9
|
-
uses: actions/checkout@v3
|
|
10
|
-
- name: Set up Ruby
|
|
11
|
-
uses: ruby/setup-ruby@v1
|
|
12
|
-
with:
|
|
13
|
-
ruby-version: "3.2"
|
|
14
|
-
bundler-cache: true
|
|
15
|
-
- run: bundle exec rubocop
|
data/.github/workflows/test.yml
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: test
|
|
3
|
-
on: [push, pull_request]
|
|
4
|
-
jobs:
|
|
5
|
-
test:
|
|
6
|
-
runs-on: ubuntu-latest
|
|
7
|
-
name: test (ruby=${{ matrix.ruby-version }}, rack=${{ matrix.rack-version }})
|
|
8
|
-
strategy:
|
|
9
|
-
fail-fast: false
|
|
10
|
-
matrix:
|
|
11
|
-
rack-version:
|
|
12
|
-
- "~> 2"
|
|
13
|
-
- "~> 3"
|
|
14
|
-
ruby-version:
|
|
15
|
-
- "3.3"
|
|
16
|
-
- "3.2"
|
|
17
|
-
- "3.1"
|
|
18
|
-
- "3.0"
|
|
19
|
-
env:
|
|
20
|
-
RACK_VERSION: ${{ matrix.rack-version }}
|
|
21
|
-
steps:
|
|
22
|
-
- uses: actions/checkout@v4
|
|
23
|
-
- uses: ruby/setup-ruby@v1
|
|
24
|
-
with:
|
|
25
|
-
ruby-version: ${{ matrix.ruby-version }}
|
|
26
|
-
bundler-cache: true
|
|
27
|
-
- run: bundle show | grep rack
|
|
28
|
-
- uses: browser-actions/setup-firefox@latest
|
|
29
|
-
with:
|
|
30
|
-
firefox-version: "108.0"
|
|
31
|
-
- uses: browser-actions/setup-geckodriver@latest
|
|
32
|
-
with:
|
|
33
|
-
geckodriver-version: "0.34.0"
|
|
34
|
-
- uses: GabrielBB/xvfb-action@v1
|
|
35
|
-
with:
|
|
36
|
-
run: |
|
|
37
|
-
bundle exec rake spec
|
data/.gitignore
DELETED
data/.rspec
DELETED