waw 0.2.2
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.
- data/LICENCE.rdoc +25 -0
- data/README.rdoc +32 -0
- data/bin/waw +32 -0
- data/bin/waw-profile +26 -0
- data/bin/waw-start +26 -0
- data/bin/wspec +33 -0
- data/layouts/empty/Rakefile +14 -0
- data/layouts/empty/config.ru +5 -0
- data/layouts/empty/config/commons.cfg +31 -0
- data/layouts/empty/config/devel.cfg +21 -0
- data/layouts/empty/ignore +7 -0
- data/layouts/empty/logs/dontforgetme +0 -0
- data/layouts/empty/resources/messages.rs +1 -0
- data/layouts/empty/test/wspec/site_respond.wspec +3 -0
- data/layouts/empty/test/wspec/test_all.rb +13 -0
- data/layouts/empty/waw.deploy +1 -0
- data/layouts/empty/waw.routing +6 -0
- data/layouts/static/dependencies +1 -0
- data/layouts/static/public/.wawaccess +18 -0
- data/layouts/static/public/css/style.css +0 -0
- data/layouts/static/public/images/dontforgetme +0 -0
- data/layouts/static/public/js/project.js +0 -0
- data/layouts/static/public/pages/.wawaccess +30 -0
- data/layouts/static/public/pages/404.wtpl +1 -0
- data/layouts/static/public/pages/index.wtpl +5 -0
- data/layouts/static/public/templates/.wawaccess +9 -0
- data/layouts/static/public/templates/layout.wtpl +17 -0
- data/layouts/static/test/wspec/static_pages_are_served.wspec +21 -0
- data/layouts/static/waw.routing +8 -0
- data/lib/waw.rb +99 -0
- data/lib/waw/commands/command.rb +115 -0
- data/lib/waw/commands/profile_command.rb +66 -0
- data/lib/waw/commands/start_command.rb +59 -0
- data/lib/waw/config.rb +110 -0
- data/lib/waw/controller.rb +25 -0
- data/lib/waw/controllers/action/action.rb +91 -0
- data/lib/waw/controllers/action/action_utils.rb +30 -0
- data/lib/waw/controllers/action/js_generation.rb +116 -0
- data/lib/waw/controllers/action_controller.rb +133 -0
- data/lib/waw/controllers/error/backtrace.rb +54 -0
- data/lib/waw/controllers/error_handler.rb +62 -0
- data/lib/waw/controllers/json_controller.rb +31 -0
- data/lib/waw/controllers/no_cache.rb +22 -0
- data/lib/waw/controllers/static/match.rb +80 -0
- data/lib/waw/controllers/static/waw_access.rb +235 -0
- data/lib/waw/controllers/static/waw_access_dsl.rb +48 -0
- data/lib/waw/controllers/static_controller.rb +37 -0
- data/lib/waw/default_config.cfg +14 -0
- data/lib/waw/environment_utils.rb +57 -0
- data/lib/waw/errors.rb +4 -0
- data/lib/waw/ext.rb +3 -0
- data/lib/waw/ext/core.rb +4 -0
- data/lib/waw/ext/core/hash.rb +47 -0
- data/lib/waw/ext/core/logger.rb +10 -0
- data/lib/waw/ext/core/module.rb +20 -0
- data/lib/waw/ext/core/object.rb +29 -0
- data/lib/waw/ext/rack.rb +19 -0
- data/lib/waw/ext/rack/builder.rb +43 -0
- data/lib/waw/ext/rack/delegator.rb +51 -0
- data/lib/waw/ext/rack/urlmap.rb +55 -0
- data/lib/waw/ext/wlang.rb +1 -0
- data/lib/waw/ext/wlang/hosted_language.rb +21 -0
- data/lib/waw/fullstate.rb +8 -0
- data/lib/waw/fullstate/on_class.rb +37 -0
- data/lib/waw/fullstate/on_instance.rb +27 -0
- data/lib/waw/fullstate/variable.rb +36 -0
- data/lib/waw/kern.rb +6 -0
- data/lib/waw/kern/app.rb +48 -0
- data/lib/waw/kern/empty/waw.deploy +0 -0
- data/lib/waw/kern/empty/waw.routing +1 -0
- data/lib/waw/kern/freezed_state.rb +32 -0
- data/lib/waw/kern/hooks.rb +53 -0
- data/lib/waw/kern/lifecycle.rb +248 -0
- data/lib/waw/kern/living_state.rb +87 -0
- data/lib/waw/kern/utils.rb +27 -0
- data/lib/waw/resource_collection.rb +100 -0
- data/lib/waw/restart.rb +32 -0
- data/lib/waw/routing.rb +43 -0
- data/lib/waw/routing/action_routing.rb +78 -0
- data/lib/waw/routing/dsl.rb +45 -0
- data/lib/waw/routing/feedback.rb +23 -0
- data/lib/waw/routing/form_validation_feedback.rb +36 -0
- data/lib/waw/routing/javascript.rb +17 -0
- data/lib/waw/routing/redirect.rb +26 -0
- data/lib/waw/routing/refresh.rb +17 -0
- data/lib/waw/routing/routing_rule.rb +16 -0
- data/lib/waw/scope_utils.rb +69 -0
- data/lib/waw/session.rb +51 -0
- data/lib/waw/testing.rb +1 -0
- data/lib/waw/tools/mail.rb +4 -0
- data/lib/waw/tools/mail/mail.rb +119 -0
- data/lib/waw/tools/mail/mail_agent.rb +123 -0
- data/lib/waw/tools/mail/mailbox.rb +62 -0
- data/lib/waw/tools/mail/template.rb +38 -0
- data/lib/waw/utils/dsl_helper.rb +116 -0
- data/lib/waw/validation.rb +175 -0
- data/lib/waw/validation/and_validator.rb +27 -0
- data/lib/waw/validation/array_validations.rb +38 -0
- data/lib/waw/validation/boolean_validator.rb +32 -0
- data/lib/waw/validation/comparison_validations.rb +45 -0
- data/lib/waw/validation/date_validator.rb +31 -0
- data/lib/waw/validation/default_validator.rb +30 -0
- data/lib/waw/validation/dsl_ruby_extensions.rb +11 -0
- data/lib/waw/validation/errors.rb +17 -0
- data/lib/waw/validation/ext.rb +3 -0
- data/lib/waw/validation/file_validator.rb +30 -0
- data/lib/waw/validation/float_validator.rb +19 -0
- data/lib/waw/validation/helpers.rb +67 -0
- data/lib/waw/validation/integer_validator.rb +16 -0
- data/lib/waw/validation/isin_validator.rb +24 -0
- data/lib/waw/validation/mandatory_validator.rb +17 -0
- data/lib/waw/validation/missing_validator.rb +17 -0
- data/lib/waw/validation/not_validator.rb +20 -0
- data/lib/waw/validation/or_validator.rb +34 -0
- data/lib/waw/validation/regexp_validator.rb +29 -0
- data/lib/waw/validation/same_validator.rb +16 -0
- data/lib/waw/validation/signature.rb +157 -0
- data/lib/waw/validation/size_validations.rb +44 -0
- data/lib/waw/validation/string_validator.rb +15 -0
- data/lib/waw/validation/validator.rb +48 -0
- data/lib/waw/wawgen.rb +2 -0
- data/lib/waw/wawgen/create.rb +166 -0
- data/lib/waw/wawgen/project.rb +25 -0
- data/lib/waw/wspec.rb +5 -0
- data/lib/waw/wspec/browser.rb +240 -0
- data/lib/waw/wspec/dsl.rb +201 -0
- data/lib/waw/wspec/html_analysis.rb +136 -0
- data/lib/waw/wspec/html_analysis/tag.rb +56 -0
- data/lib/waw/wspec/runner.rb +70 -0
- data/lib/waw/wspec/scenario.rb +35 -0
- data/lib/waw/wspec/suite.rb +54 -0
- data/test/bricks/error_handler/config/test.cfg +2 -0
- data/test/bricks/error_handler/logs/webapp.log +1411 -0
- data/test/bricks/error_handler/test/error_handler.wspec +16 -0
- data/test/bricks/error_handler/waw.deploy +1 -0
- data/test/bricks/error_handler/waw.routing +27 -0
- data/test/integration/waw_create_integration_test.rb +24 -0
- data/test/spec/assumptions_spec.rb +30 -0
- data/test/spec/controllers/action_controller_spec.rb +14 -0
- data/test/spec/controllers/static/waw_access_spec.rb +112 -0
- data/test/spec/environment_utils_spec.rb +15 -0
- data/test/spec/ext/core/hash_spec.rb +58 -0
- data/test/spec/fixtures.rb +41 -0
- data/test/spec/fixtures/action/config/default.cfg +2 -0
- data/test/spec/fixtures/action/lib/action_controller_test.rb +12 -0
- data/test/spec/fixtures/action/waw.deploy +1 -0
- data/test/spec/fixtures/action/waw.routing +6 -0
- data/test/spec/fixtures/empty/waw.deploy +0 -0
- data/test/spec/fixtures/empty/waw.routing +0 -0
- data/test/spec/fullstate/on_class_spec.rb +59 -0
- data/test/spec/fullstate/on_instance_spec.rb +59 -0
- data/test/spec/fullstate/session_spec.rb +43 -0
- data/test/spec/fullstate/variable_spec.rb +55 -0
- data/test/spec/resource_collection_spec.rb +50 -0
- data/test/spec/test_all.rb +9 -0
- data/test/spec/tools/mail/mail_agent_spec.rb +116 -0
- data/test/spec/tools/mail/mail_spec.rb +56 -0
- data/test/spec/tools/mail/mailbox_spec.rb +57 -0
- data/test/spec/tools/mail/template_spec.rb +47 -0
- data/test/spec/validation/array_validation_spec.rb +63 -0
- data/test/spec/validation/array_validator_spec.rb +17 -0
- data/test/spec/validation/date_validation_spec.rb +35 -0
- data/test/spec/validation/default_validation_spec.rb +37 -0
- data/test/spec/validation/disjuctive_validation_spec.rb +33 -0
- data/test/spec/validation/errors_spec.rb +37 -0
- data/test/spec/validation/file_validator_spec.rb +34 -0
- data/test/spec/validation/mail_validation_spec.rb +51 -0
- data/test/spec/validation/missing_validation_spec.rb +43 -0
- data/test/spec/validation/same_validation_spec.rb +24 -0
- data/test/spec/validation/signature_intuition_spec.rb +37 -0
- data/test/spec/validation/signature_spec.rb +164 -0
- data/test/spec/validation/validation_spec.rb +28 -0
- data/test/spec/wspec/html_analysis/tag_spec.rb +38 -0
- data/test/spec/wspec/html_analysis_spec.rb +170 -0
- data/test/unit/test_all.rb +8 -0
- data/test/unit/waw/app_test.rb +126 -0
- data/test/unit/waw/app_test/config/commons.cfg +2 -0
- data/test/unit/waw/app_test/config/devel.cfg +1 -0
- data/test/unit/waw/config_test.rb +54 -0
- data/test/unit/waw/controllers/action_controller_test.rb +76 -0
- data/test/unit/waw/controllers/action_test.rb +35 -0
- data/test/unit/waw/controllers/example_action_controller_test.rb +24 -0
- data/test/unit/waw/controllers/multiple_action_controller_test.rb +78 -0
- data/test/unit/waw/controllers/static/example/css/example.css +1 -0
- data/test/unit/waw/controllers/static/example/index.html +1 -0
- data/test/unit/waw/controllers/static/example/js/example.js +1 -0
- data/test/unit/waw/controllers/static/example/pages/hello.wtpl +1 -0
- data/test/unit/waw/controllers/static/waw_access_test.rb +76 -0
- data/test/unit/waw/ext/rack_test.rb +74 -0
- data/test/unit/waw/resource_collection_test.rb +49 -0
- data/test/unit/waw/resources.txt +4 -0
- data/test/unit/waw/routing/routing_test.rb +26 -0
- data/test/unit/waw/utils/dsl_helper_test.rb +79 -0
- data/test/unit/waw/utils/dsl_helper_test_extensions1.rb +4 -0
- data/test/unit/waw/validation/signature_test.rb +193 -0
- data/test/unit/waw/validation_test.rb +319 -0
- data/test/unit/waw/wspec/html_analysis_test.html +81 -0
- data/test/unit/waw/wspec/html_analysis_test.rb +26 -0
- metadata +272 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
module Waw
|
|
2
|
+
class StaticController < ::Waw::Controller
|
|
3
|
+
class WawAccess
|
|
4
|
+
class Match
|
|
5
|
+
include Waw::ScopeUtils
|
|
6
|
+
|
|
7
|
+
# Served file
|
|
8
|
+
attr_reader :served_file
|
|
9
|
+
|
|
10
|
+
# Creates a match instance with a block a arguments
|
|
11
|
+
# to pass
|
|
12
|
+
def initialize(wawaccess, served_file, block, *args)
|
|
13
|
+
@wawaccess, @served_file = wawaccess, served_file
|
|
14
|
+
@block, @args = block, args
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Executes on a wawaccess instance
|
|
18
|
+
def __execute
|
|
19
|
+
instance_exec *@args, &@block
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Delegated to the wawaccess that created me
|
|
23
|
+
def root; @wawaccess.root; end
|
|
24
|
+
def folder; @wawaccess.folder; end
|
|
25
|
+
|
|
26
|
+
################################################### Callbacks proposed to .wawaccess rules
|
|
27
|
+
|
|
28
|
+
# Deny access to the file
|
|
29
|
+
def deny
|
|
30
|
+
body = "Forbidden\n"
|
|
31
|
+
[403, {"Content-Type" => "text/plain",
|
|
32
|
+
"Content-Length" => body.size.to_s,
|
|
33
|
+
"X-Cascade" => "pass"},
|
|
34
|
+
[body]]
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Serves a static file from a real path
|
|
38
|
+
def static
|
|
39
|
+
if rack_env
|
|
40
|
+
rack_env["PATH_INFO"] = served_file
|
|
41
|
+
@wawaccess.file_server.call(rack_env)
|
|
42
|
+
else
|
|
43
|
+
path = File.join(root.folder, served_file)
|
|
44
|
+
[200, {'Content-Type' => 'text/plain'}, [File.read(path)]]
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Run a rewriting
|
|
49
|
+
def apply(path, result_override = nil, headers_override = {})
|
|
50
|
+
result = root.do_path_serve(path)
|
|
51
|
+
[result_override || result[0],
|
|
52
|
+
result[1].merge(headers_override),
|
|
53
|
+
result[2]]
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Builds a default wlang contect
|
|
57
|
+
def default_wlang_context
|
|
58
|
+
context = {"css_files" => root.find_files('css'),
|
|
59
|
+
"js_files" => root.find_files('js'),
|
|
60
|
+
"served_file" => served_file}
|
|
61
|
+
context
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Instantiates wlang on the current file, with a given context
|
|
65
|
+
def wlang(template = nil, context = {}, result_override = nil, headers_override = {})
|
|
66
|
+
if template.nil?
|
|
67
|
+
template = File.join(root.folder, served_file)
|
|
68
|
+
else
|
|
69
|
+
template = File.join(folder, template)
|
|
70
|
+
end
|
|
71
|
+
context = default_wlang_context.merge(context || {})
|
|
72
|
+
[result_override || 200,
|
|
73
|
+
{'Content-Type' => 'text/html'}.merge(headers_override || {}),
|
|
74
|
+
[::WLang.file_instantiate(template, context.unsymbolize_keys).to_s]]
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
end # class Match
|
|
78
|
+
end # class WawAccess
|
|
79
|
+
end # class StaticController
|
|
80
|
+
end # module Waw
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
require 'uri'
|
|
2
|
+
require 'waw/controllers/static/match'
|
|
3
|
+
module Waw
|
|
4
|
+
class StaticController < ::Waw::Controller
|
|
5
|
+
# Waw version of .htaccess files
|
|
6
|
+
class WawAccess
|
|
7
|
+
|
|
8
|
+
# The folder which is served
|
|
9
|
+
attr_accessor :folder
|
|
10
|
+
|
|
11
|
+
# Strategy :allow_all or :deny_all
|
|
12
|
+
attr_accessor :strategy
|
|
13
|
+
|
|
14
|
+
# Does it inherits its parent configuration?
|
|
15
|
+
attr_accessor :inherits
|
|
16
|
+
|
|
17
|
+
# The parent wawaccess file
|
|
18
|
+
attr_accessor :parent
|
|
19
|
+
|
|
20
|
+
# Fake accessor that go to the top of the hierarchy
|
|
21
|
+
def file_server
|
|
22
|
+
@file_server || (parent && parent.file_server)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Creates a default WawAccess file
|
|
26
|
+
def initialize(parent = nil, folder = nil, read_file = nil)
|
|
27
|
+
@parent = parent
|
|
28
|
+
@folder = folder
|
|
29
|
+
@strategy = :deny_all
|
|
30
|
+
@inherits = true
|
|
31
|
+
@serve = []
|
|
32
|
+
@children = {}
|
|
33
|
+
@file_server = ::Rack::File.new(folder) if parent.nil?
|
|
34
|
+
dsl_merge_file(read_file) if read_file
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
################################################### About installation through DSL
|
|
38
|
+
|
|
39
|
+
# Returns a wawaccess tree for a given folder
|
|
40
|
+
def self.load_hierarchy(root_folder, parent = nil)
|
|
41
|
+
raise ArgumentError, "Invalid folder #{root_folder}" unless (root_folder and File.directory?(root_folder))
|
|
42
|
+
|
|
43
|
+
# Locate and load the .wawaccess file or provide a default one
|
|
44
|
+
wawaccess_file = File.join(root_folder, '.wawaccess')
|
|
45
|
+
if File.exists?(wawaccess_file)
|
|
46
|
+
wawaccess = WawAccess.new(parent, root_folder, wawaccess_file)
|
|
47
|
+
else
|
|
48
|
+
wawaccess = WawAccess.new(parent, root_folder)
|
|
49
|
+
wawaccess.strategy = :deny_all
|
|
50
|
+
wawaccess.inherits = true
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Install its children
|
|
54
|
+
Dir.new(root_folder).each do |file|
|
|
55
|
+
next if ['.', '..'].include?(file)
|
|
56
|
+
child_folder = File.join(root_folder, file)
|
|
57
|
+
next unless File.directory?(child_folder)
|
|
58
|
+
|
|
59
|
+
# Load the child and save it
|
|
60
|
+
wawaccess.add_child(file, WawAccess.load_hierarchy(child_folder, wawaccess))
|
|
61
|
+
end
|
|
62
|
+
wawaccess
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
################################################### About installation through DSL
|
|
66
|
+
|
|
67
|
+
def recognized_pattern?(pattern)
|
|
68
|
+
[FalseClass, TrueClass, String,
|
|
69
|
+
Regexp, Waw::Validation::Validator].any?{|c| c===pattern}
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Adds a child in the hierarchy
|
|
73
|
+
def add_child(folder, wawaccess)
|
|
74
|
+
@children[folder] = wawaccess
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Installs some pattern services
|
|
78
|
+
def add_serve(patterns, &block)
|
|
79
|
+
raise ArgumentError, "WawAccess.add_serve expects a block" unless block
|
|
80
|
+
patterns.each do |pattern|
|
|
81
|
+
raise WawError, "Invalid serving pattern #{pattern} (#{pattern.class})"\
|
|
82
|
+
unless recognized_pattern?(pattern)
|
|
83
|
+
@serve << [pattern, block]
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Merges a DSL string inside this waw access
|
|
88
|
+
def dsl_merge(dsl_str, read_file=nil)
|
|
89
|
+
begin
|
|
90
|
+
dsl = WawAccess::DSL.new(self)
|
|
91
|
+
dsl.instance_eval(dsl_str)
|
|
92
|
+
rescue WawError => ex
|
|
93
|
+
raise WawError, "Corrupted .wawaccess file #{read_file}: #{ex.message}", ex.backtrace
|
|
94
|
+
rescue Exception => ex
|
|
95
|
+
raise WawError, "Corrupted .wawaccess file #{read_file}: #{ex.message}", ex.backtrace
|
|
96
|
+
end
|
|
97
|
+
self
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# Merge with a .wawaccess file
|
|
101
|
+
def dsl_merge_file(read_file)
|
|
102
|
+
raise WawError, "Missing .wawaccess file #{readfile}" unless File.file?(read_file)
|
|
103
|
+
dsl_merge(File.read(read_file), read_file)
|
|
104
|
+
self
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
################################################### Utilites about paths
|
|
108
|
+
|
|
109
|
+
# Returns the real path of a file
|
|
110
|
+
def realpath(file)
|
|
111
|
+
File.expand_path(File.join(folder, file))
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# Locates the file that would be matched by a given normalized
|
|
115
|
+
# url.
|
|
116
|
+
def matching_file(path)
|
|
117
|
+
File.join(root.folder, path)
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# Relativize a path against a given folder
|
|
121
|
+
def relativize(file, folder = folder)
|
|
122
|
+
file, folder = File.expand_path(file), File.expand_path(folder)
|
|
123
|
+
file[(folder.length+1)..-1]
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# Helper to locate css and js files
|
|
127
|
+
def find_files(pattern)
|
|
128
|
+
Dir[File.join(folder, pattern, "*.#{pattern}")].sort{|f1, f2|
|
|
129
|
+
File.basename(f1) <=> File.basename(f2)
|
|
130
|
+
}.collect{|f|
|
|
131
|
+
File.join(pattern, File.basename(f))
|
|
132
|
+
}
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
################################################### Utilities about the hierarchy
|
|
136
|
+
|
|
137
|
+
# Returns an identifier for this wawaccess
|
|
138
|
+
def identifier(append = true)
|
|
139
|
+
if parent
|
|
140
|
+
parent.identifier(false) + (append ? "#{File.basename(@folder)}/.wawaccess" : File.basename(@folder))
|
|
141
|
+
else
|
|
142
|
+
(append ? ".wawaccess" : "")
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
# Returns the root waw access in the hierarchy
|
|
147
|
+
def root
|
|
148
|
+
@root ||= (parent ? parent.root : self)
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
# Finds the wawaccess instance for a given url
|
|
152
|
+
def find_wawaccess_for(url, url_array = url.split('/').reject{|k| k.empty?})
|
|
153
|
+
if url_array.empty?
|
|
154
|
+
self
|
|
155
|
+
else
|
|
156
|
+
if @children.has_key?(nextfolder = url_array.shift)
|
|
157
|
+
@children[nextfolder].find_wawaccess_for(url, url_array)
|
|
158
|
+
else
|
|
159
|
+
self
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
################################################### .waw access rules application!
|
|
165
|
+
|
|
166
|
+
# Finds the matching block inside this .wawaccess handler
|
|
167
|
+
def find_match(path)
|
|
168
|
+
@serve.each do |pattern, block|
|
|
169
|
+
case pattern
|
|
170
|
+
when FalseClass
|
|
171
|
+
when TrueClass
|
|
172
|
+
return Match.new(self, path, block)
|
|
173
|
+
when String
|
|
174
|
+
if pattern=='*'
|
|
175
|
+
return Match.new(self, path, block)
|
|
176
|
+
elsif /^\*?\.[a-z]+$/ =~ pattern
|
|
177
|
+
return Match.new(self, path, block) if File.extname(realpath(path))==pattern
|
|
178
|
+
else
|
|
179
|
+
return Match.new(self, path, block) if File.basename(realpath(path))==pattern
|
|
180
|
+
end
|
|
181
|
+
when Regexp
|
|
182
|
+
if matchdata = pattern.match(path)
|
|
183
|
+
return Match.new(self, path, block, *matchdata.to_a)
|
|
184
|
+
end
|
|
185
|
+
when Waw::Validation::Validator
|
|
186
|
+
if pattern.validate(matching_file(path))
|
|
187
|
+
return Match.new(self, path, block)
|
|
188
|
+
end
|
|
189
|
+
else
|
|
190
|
+
raise WawError, "Unrecognized wawaccess pattern #{pattern}"
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
nil
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
# Applies the rules defined here or delegate to the parent if allowed
|
|
197
|
+
def apply_rules(path)
|
|
198
|
+
if match = find_match(path)
|
|
199
|
+
match.__execute
|
|
200
|
+
elsif (parent and inherits)
|
|
201
|
+
parent.apply_rules(path)
|
|
202
|
+
else
|
|
203
|
+
body = "File not found: #{path}\n"
|
|
204
|
+
[404, {"Content-Type" => "text/plain",
|
|
205
|
+
"Content-Length" => body.size.to_s,
|
|
206
|
+
"X-Cascade" => "pass"},
|
|
207
|
+
[body]]
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
################################################### To be called on the tree root only!
|
|
212
|
+
|
|
213
|
+
# Normalizes a requested path, removing any .html, .htm suffix
|
|
214
|
+
def normalize_req_path(req_path)
|
|
215
|
+
# 1) Decode the req_path with URI::decode
|
|
216
|
+
req_path = URI::decode(req_path)
|
|
217
|
+
# 2) Strip first
|
|
218
|
+
req_path = req_path.strip
|
|
219
|
+
# 3) Remove first slash
|
|
220
|
+
req_path = req_path[1..-1] if req_path[0,1]=='/'
|
|
221
|
+
# 4) Remove last slash
|
|
222
|
+
req_path = req_path[0..-2] if req_path[req_path.length-1,1]=='/'
|
|
223
|
+
req_path
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
# Serves a path from a root waw access in the hierarchy
|
|
227
|
+
def do_path_serve(path)
|
|
228
|
+
path = normalize_req_path(path)
|
|
229
|
+
waw_access = (find_wawaccess_for(path) || self)
|
|
230
|
+
waw_access.apply_rules(path)
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
end # class WawAccess
|
|
234
|
+
end # class StaticController
|
|
235
|
+
end # module Waw
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
module Waw
|
|
2
|
+
class StaticController < ::Waw::Controller
|
|
3
|
+
class WawAccess
|
|
4
|
+
# Domain specific language for .wawaccess language
|
|
5
|
+
class DSL
|
|
6
|
+
include ::Waw::Validation
|
|
7
|
+
|
|
8
|
+
# Creates a new DSL instance
|
|
9
|
+
def initialize(wawaccess)
|
|
10
|
+
raise ArgumentError, "wawaccess cannot be nil" unless WawAccess===wawaccess
|
|
11
|
+
@wawaccess = wawaccess
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# Returns a validator that matches the root of the wawaccess tree
|
|
15
|
+
def root
|
|
16
|
+
Waw::Validation.validator{|served_file| File.expand_path(served_file) == File.expand_path(@wawaccess.root.folder)}
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Starts a wawaccess file
|
|
20
|
+
def wawaccess(&block)
|
|
21
|
+
raise WawError, "#{@wawaccess.identifier}: missing block in wawaccess call" unless block
|
|
22
|
+
self.instance_eval(&block)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Installs the default strategy
|
|
26
|
+
def strategy(which = :unknown)
|
|
27
|
+
raise WawError, "#{@wawaccess.identifier}: unrecognized wawaccess strategy #{which}" unless [:deny_all, :allow_all].include?(which)
|
|
28
|
+
@wawaccess.strategy = which
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Installs the inherits strategy
|
|
32
|
+
def inherits(which = "unknown")
|
|
33
|
+
raise WawError, "#{@wawaccess.identifier}: unrecognized wawaccess inherits #{which}" unless [true, false].include?(which)
|
|
34
|
+
@wawaccess.inherits = which
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Serve some patterns
|
|
38
|
+
def match(*patterns, &block)
|
|
39
|
+
patterns = patterns.compact
|
|
40
|
+
raise WawError, "#{@wawaccess.identifier}: missing patterns in wawaccess.match call" if patterns.empty?
|
|
41
|
+
raise WawError, "#{@wawaccess.identifier}: missing block in wawaccess.match call" if block.nil?
|
|
42
|
+
@wawaccess.add_serve(patterns, &block)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
end
|
|
46
|
+
end # class WawAccess
|
|
47
|
+
end # class StaticController
|
|
48
|
+
end # module Waw
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
require 'waw/controllers/static/waw_access'
|
|
2
|
+
require 'waw/controllers/static/waw_access_dsl'
|
|
3
|
+
module Waw
|
|
4
|
+
#
|
|
5
|
+
# A waw service that serves public pages expressed in wlang wtpl format
|
|
6
|
+
#
|
|
7
|
+
class StaticController < ::Waw::Controller
|
|
8
|
+
|
|
9
|
+
##############################################################################################
|
|
10
|
+
### About service creation and configuration
|
|
11
|
+
##############################################################################################
|
|
12
|
+
|
|
13
|
+
# Default options of this service
|
|
14
|
+
DEFAULT_OPTIONS = {:public => 'public'}
|
|
15
|
+
|
|
16
|
+
# Creates a service instance
|
|
17
|
+
def initialize(opts = {})
|
|
18
|
+
@options = DEFAULT_OPTIONS.merge(opts)
|
|
19
|
+
@wawaccess = ::Waw::StaticController::WawAccess.load_hierarchy(File.join(root_folder, public_folder))
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Returns the template folder
|
|
23
|
+
def public_folder
|
|
24
|
+
@options[:public] || @options[:root]
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
##############################################################################################
|
|
28
|
+
### Main service execution
|
|
29
|
+
##############################################################################################
|
|
30
|
+
|
|
31
|
+
# Executes the service
|
|
32
|
+
def execute(env, req, res)
|
|
33
|
+
@wawaccess.do_path_serve(env['PATH_INFO'])
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
end # class Controller
|
|
37
|
+
end # module Waw
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Logger configuration
|
|
2
|
+
log_dir 'logs'
|
|
3
|
+
log_file 'webapp.log'
|
|
4
|
+
log_frequency 'weekly'
|
|
5
|
+
log_level Logger::DEBUG
|
|
6
|
+
|
|
7
|
+
# Web configuration
|
|
8
|
+
web_domain '127.0.0.1'
|
|
9
|
+
web_port 9292
|
|
10
|
+
web_base 'http://127.0.0.1:9292/'
|
|
11
|
+
|
|
12
|
+
# About Rack
|
|
13
|
+
rack_session true
|
|
14
|
+
rack_session_expire 60 * 60 * 24
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
module Waw
|
|
2
|
+
# Provides environment utilities to get the current Rack environment,
|
|
3
|
+
# session and so on. Some of these utilities make the assumption that
|
|
4
|
+
# a session is installed in some Rack standard way (through Rack::Session::Pool)
|
|
5
|
+
# for example.
|
|
6
|
+
module EnvironmentUtils
|
|
7
|
+
include Waw::ScopeUtils
|
|
8
|
+
|
|
9
|
+
DEPRECATED_MSG = <<-EOF
|
|
10
|
+
Method ${method_name} is deprecated and will be removed in version 0.3.
|
|
11
|
+
Please include Waw::ScopeUtils module instead.
|
|
12
|
+
EOF
|
|
13
|
+
|
|
14
|
+
# Returns the current Rack env instance
|
|
15
|
+
deprecated DEPRECATED_MSG
|
|
16
|
+
def env
|
|
17
|
+
rack_env
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Checks if a session has a given key
|
|
21
|
+
deprecated <<-EOF
|
|
22
|
+
Method ${method_name} is deprecated and will be removed in version 0.3.
|
|
23
|
+
Please include Waw::ScopeUtils module and use session.has_key? instead.
|
|
24
|
+
EOF
|
|
25
|
+
def session_has_key?(key)
|
|
26
|
+
session.has_key?(key)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Sets a pair inside the session. Returns the value.
|
|
30
|
+
deprecated <<-EOF
|
|
31
|
+
Method ${method_name} is deprecated and will be removed in version 0.3.
|
|
32
|
+
Please include Waw::ScopeUtils module and use session.set instead.
|
|
33
|
+
EOF
|
|
34
|
+
def session_set(key, value)
|
|
35
|
+
session[key] = value
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Sets a pair inside the session
|
|
39
|
+
deprecated <<-EOF
|
|
40
|
+
Method ${method_name} is deprecated and will be removed in version 0.3.
|
|
41
|
+
Please include Waw::ScopeUtils module and use session.unset instead.
|
|
42
|
+
EOF
|
|
43
|
+
def session_unset(key)
|
|
44
|
+
session.delete(key)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Get a value from the current session
|
|
48
|
+
deprecated <<-EOF
|
|
49
|
+
Method ${method_name} is deprecated and will be removed in version 0.3.
|
|
50
|
+
Please include Waw::ScopeUtils module and use session.get instead.
|
|
51
|
+
EOF
|
|
52
|
+
def session_get(key)
|
|
53
|
+
session[key]
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
end # module EnvironmentUtils
|
|
57
|
+
end # module Waw
|