lux-fw 0.1.35 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.version +1 -1
- data/bin/cli/am +67 -41
- data/bin/cli/assets +1 -1
- data/bin/cli/console +3 -2
- data/bin/cli/eval +11 -2
- data/bin/cli/exceptions +1 -1
- data/bin/cli/generate +4 -0
- data/bin/cli/render +18 -0
- data/bin/cli/routes +3 -1
- data/bin/cli/server +4 -1
- data/bin/lux +10 -1
- data/bin/txt/nginx.conf +35 -18
- data/lib/common/class_attributes.rb +10 -10
- data/lib/common/{before_and_after.rb → class_callbacks.rb} +12 -21
- data/lib/common/crypt.rb +10 -6
- data/lib/common/dynamic_class.rb +12 -7
- data/lib/common/generic_model.rb +6 -6
- data/lib/common/hash_with_indifferent_access.rb +6 -284
- data/lib/{lux/helper/lib/html_tag.rb → common/html_tag_builder.rb} +1 -1
- data/lib/common/policy.rb +2 -2
- data/lib/common/url.rb +6 -4
- data/lib/lux-fw.rb +2 -13
- data/lib/lux/api/api.rb +34 -47
- data/lib/lux/api/lib/dsl.rb +2 -2
- data/lib/lux/api/lib/model_api.rb +40 -23
- data/lib/lux/api/lib/response.rb +30 -5
- data/lib/lux/application/application.rb +182 -0
- data/lib/lux/{controller → application}/lib/nav.rb +18 -21
- data/lib/lux/application/lib/plugs.rb +10 -0
- data/lib/lux/application/lib/render.rb +58 -0
- data/lib/lux/application/lib/route_test.rb +64 -0
- data/lib/lux/cache/cache.rb +27 -16
- data/lib/lux/cell/cell.rb +66 -54
- data/lib/lux/config/config.rb +51 -27
- data/lib/lux/current/current.rb +122 -0
- data/lib/lux/{page → current}/lib/encrypt_params.rb +2 -2
- data/lib/lux/{page → current}/lib/static_file.rb +29 -25
- data/lib/lux/delayed_job/delayed_job.rb +4 -4
- data/lib/lux/error/error.rb +31 -16
- data/lib/lux/helper/helper.rb +32 -37
- data/lib/lux/helper/helpers/application_helper.rb +3 -0
- data/lib/lux/helper/helpers/html_helper.rb +3 -0
- data/lib/lux/helper/helpers/mailer_helper.rb +11 -0
- data/lib/lux/lux.rb +40 -30
- data/lib/lux/mailer/mailer.rb +46 -29
- data/lib/lux/{page → response}/lib/flash.rb +1 -1
- data/lib/lux/response/lib/header.rb +21 -0
- data/lib/lux/response/response.rb +237 -0
- data/lib/lux/template/template.rb +20 -18
- data/lib/overload/array.rb +5 -0
- data/lib/overload/auto_loader.rb +27 -0
- data/lib/overload/blank.rb +8 -2
- data/lib/overload/float.rb +10 -0
- data/lib/overload/hash.rb +5 -12
- data/lib/overload/integer.rb +1 -5
- data/lib/overload/nil.rb +5 -0
- data/lib/overload/object.rb +1 -0
- data/lib/overload/r.rb +5 -0
- data/lib/overload/string.rb +4 -5
- data/lib/overload/{date.rb → time.rb} +23 -3
- metadata +37 -73
- data/bin/forever +0 -65
- data/bin/job_que +0 -39
- data/lib/lux/api/lib/application_api.rb +0 -38
- data/lib/lux/api/lib/doc_builder.rb +0 -19
- data/lib/lux/api/lib/rescue.rb +0 -8
- data/lib/lux/controller/controller.rb +0 -185
- data/lib/lux/controller/lib/plugs.rb +0 -10
- data/lib/lux/html/html.rb +0 -3
- data/lib/lux/html/lib/form.rb +0 -81
- data/lib/lux/html/lib/input.rb +0 -71
- data/lib/lux/html/lib/input_types.rb +0 -287
- data/lib/lux/lib/lux.rb +0 -51
- data/lib/lux/page/lib/response.rb +0 -178
- data/lib/lux/page/page.rb +0 -292
- data/lib/lux/rescue_from/rescue_from.rb +0 -63
- data/lib/plugins/assets/assets_plug.rb +0 -31
- data/lib/plugins/assets/helper_module_adapter.rb +0 -51
- data/lib/plugins/assets/init.rb +0 -4
- data/lib/plugins/db_helpers/array_and_hstore.rb +0 -64
- data/lib/plugins/db_helpers/arrays_and_tags.rb +0 -23
- data/lib/plugins/db_helpers/before_save.rb +0 -44
- data/lib/plugins/db_helpers/cached_find_by.rb +0 -45
- data/lib/plugins/db_helpers/class_and_instance.rb +0 -120
- data/lib/plugins/db_helpers/dataset_plugin.rb +0 -101
- data/lib/plugins/db_helpers/filter_wrappers.rb +0 -21
- data/lib/plugins/db_helpers/link_plugin.rb +0 -95
- data/lib/plugins/db_helpers/localize_plugin.rb +0 -57
- data/lib/plugins/db_helpers/primary_keys.rb +0 -36
- data/lib/plugins/db_helpers/typero_attributes.rb +0 -69
- data/lib/plugins/db_logger/init.rb +0 -18
- data/lib/plugins/db_logger/lux_response_adapter.rb +0 -9
- data/lib/plugins/paginate/helper.rb +0 -32
- data/lib/plugins/paginate/sequel_adapter.rb +0 -18
- data/lib/vendor/mini_assets/lib/asset.rb +0 -71
- data/lib/vendor/mini_assets/lib/asset/css.rb +0 -19
- data/lib/vendor/mini_assets/lib/asset/js.rb +0 -17
- data/lib/vendor/mini_assets/lib/base.rb +0 -69
- data/lib/vendor/mini_assets/lib/base/javascript.rb +0 -13
- data/lib/vendor/mini_assets/lib/base/stylesheet.rb +0 -5
- data/lib/vendor/mini_assets/lib/manifest.rb +0 -18
- data/lib/vendor/mini_assets/lib/opts.rb +0 -16
- data/lib/vendor/mini_assets/mini_assets.rb +0 -74
- data/lib/vendor/oauth/lib/facebook.rb +0 -35
- data/lib/vendor/oauth/lib/github.rb +0 -37
- data/lib/vendor/oauth/lib/google.rb +0 -41
- data/lib/vendor/oauth/lib/linkedin.rb +0 -41
- data/lib/vendor/oauth/lib/stackexchange.rb +0 -37
- data/lib/vendor/oauth/lib/twitter.rb +0 -41
- data/lib/vendor/oauth/oauth.rb +0 -46
data/lib/lux/helper/helper.rb
CHANGED
@@ -1,48 +1,44 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# plugins should extend this
|
4
|
-
module DefaultHelper
|
5
|
-
end
|
6
|
-
|
7
3
|
class Lux::Helper
|
8
4
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
"#{group}_helper".classify.constantize
|
13
|
-
elsif group
|
14
|
-
group
|
15
|
-
end
|
5
|
+
# create helper object that cah be used in template render
|
6
|
+
def initialize instance, *list
|
7
|
+
extend ApplicationHelper
|
16
8
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
# locals overide globals
|
22
|
-
for k, v in locals
|
23
|
-
helper.instance_variable_set("@#{k.to_s.sub('@','')}", v)
|
24
|
-
end
|
9
|
+
list.flatten.compact.each do |el|
|
10
|
+
el = el.to_s.classify+'Helper'
|
11
|
+
extend el.constantize
|
12
|
+
end
|
25
13
|
|
26
|
-
|
14
|
+
local_vars = instance.class == Hash ? instance : instance.instance_variables_hash
|
27
15
|
|
28
|
-
|
16
|
+
# locals overide globals
|
17
|
+
for k, v in local_vars
|
18
|
+
instance_variable_set("@#{k.to_s.sub('@','')}", v)
|
29
19
|
end
|
20
|
+
|
21
|
+
# helper.instance_exec &block if block
|
30
22
|
end
|
31
23
|
|
32
24
|
def no_white_space
|
33
25
|
yield.gsub(/>\s+</,'><')
|
34
26
|
end
|
35
27
|
|
36
|
-
def
|
37
|
-
Lux.
|
28
|
+
def current
|
29
|
+
Lux.current
|
38
30
|
end
|
39
31
|
|
40
32
|
def request
|
41
|
-
Lux.
|
33
|
+
Lux.current.request
|
42
34
|
end
|
43
35
|
|
44
36
|
def params
|
45
|
-
Lux.
|
37
|
+
Lux.current.params
|
38
|
+
end
|
39
|
+
|
40
|
+
def nav
|
41
|
+
Lux.current.nav
|
46
42
|
end
|
47
43
|
|
48
44
|
# renders just template but it is called
|
@@ -62,17 +58,16 @@ class Lux::Helper
|
|
62
58
|
name = "#{Thread.current[:lux][:last_template_path]}/#{name}" unless name.index('/')
|
63
59
|
end
|
64
60
|
|
65
|
-
ivh = instance_variables_hash
|
66
|
-
|
67
61
|
for k, v in locals
|
68
|
-
|
62
|
+
instance_variable_set("@_#{k}", v)
|
69
63
|
end
|
70
64
|
|
71
65
|
if block_given?
|
72
66
|
name = "#{name}/layout" unless name.index('/')
|
73
|
-
|
67
|
+
|
68
|
+
Lux::Template.new(name, self).render_part { yield }
|
74
69
|
else
|
75
|
-
Lux::Template.new(name,
|
70
|
+
Lux::Template.new(name, self).render_part
|
76
71
|
end
|
77
72
|
end
|
78
73
|
|
@@ -93,17 +88,17 @@ class Lux::Helper
|
|
93
88
|
klass.cell(action, *args) rescue error("#{klass}.#{action}()\n\n#{$!.message}")
|
94
89
|
end
|
95
90
|
|
96
|
-
# add locale prefix if using locale
|
97
|
-
def localize path
|
98
|
-
return Lux.config(:localize) ? "/#{Locale.current}#{path}" : path
|
99
|
-
end
|
100
|
-
|
101
91
|
# tag :div, { 'class'=>'iform' } do
|
102
92
|
def tag name=nil, opts={}, data=nil
|
103
|
-
return
|
93
|
+
return HtmlTagBuilder unless name
|
104
94
|
|
105
95
|
data = yield(opts) if block_given?
|
106
|
-
|
96
|
+
HtmlTagBuilder.tag name, opts, data
|
97
|
+
end
|
98
|
+
|
99
|
+
# helper(:main).method
|
100
|
+
def helper *names
|
101
|
+
Lux::Helper.new(self, *names)
|
107
102
|
end
|
108
103
|
|
109
104
|
end
|
data/lib/lux/lux.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative '../common/class_callbacks.rb'
|
4
|
+
|
3
5
|
module Lux
|
4
6
|
extend self
|
5
7
|
|
6
8
|
ENV_PROD = ENV['RACK_ENV'] == 'production'
|
7
9
|
ENV_DEV = ENV['RACK_ENV'] == 'development'
|
8
10
|
ENV_TEST = ENV['RACK_ENV'] == 'test'
|
9
|
-
LUX_LIVE = ENV['LUX_LIVE'] == 'true'
|
10
|
-
LUX_VERBOSE = ENV['LUX_VERBOSE'] == 'true'
|
11
11
|
LUX_CLI = $0 == 'pry' || $0.index('/run.rb') || ENV['RACK_ENV'] == 'test'
|
12
12
|
|
13
13
|
VERSION = File.read File.expand_path('../../../.version', __FILE__).chomp
|
@@ -17,39 +17,45 @@ module Lux
|
|
17
17
|
BACKGROUND_THREADS ||= []
|
18
18
|
Kernel.at_exit { BACKGROUND_THREADS.each { |t| t.join } }
|
19
19
|
|
20
|
-
define_method(:prod?)
|
21
|
-
define_method(:dev?)
|
22
|
-
define_method(:test?)
|
23
|
-
define_method(:
|
24
|
-
define_method(:
|
25
|
-
define_method(:
|
20
|
+
define_method(:prod?) { ENV_PROD }
|
21
|
+
define_method(:dev?) { ENV_DEV }
|
22
|
+
define_method(:test?) { ENV_TEST }
|
23
|
+
define_method(:cli?) { !!($0 =~ %r[/bin/lux$]) }
|
24
|
+
define_method(:thread) { Thread.current[:lux] }
|
25
|
+
define_method(:cache) { Lux::Cache }
|
26
|
+
|
27
|
+
# main rack response
|
28
|
+
def call env=nil
|
29
|
+
req = Lux::Current.new env
|
30
|
+
req.response.render
|
31
|
+
rescue
|
32
|
+
raise $! if Lux.config(:show_server_errors)
|
33
|
+
|
34
|
+
[500, {}, ['Lux server error']]
|
35
|
+
end
|
26
36
|
|
27
|
-
def env
|
37
|
+
def env key=nil
|
28
38
|
return ENV['RACK_ENV'] unless key
|
29
39
|
die "ENV['#{key}'] not found" if ENV[key].nil?
|
30
40
|
ENV[key]
|
31
41
|
end
|
32
42
|
|
33
|
-
def config
|
43
|
+
def config key=nil
|
34
44
|
return CONFIG unless key
|
35
45
|
die 'Lux.config.%s not found' % key if CONFIG[key].nil?
|
36
46
|
CONFIG[key].kind_of?(Proc) ? CONFIG[key].call() : CONFIG[key]
|
37
47
|
end
|
38
48
|
|
39
|
-
def
|
40
|
-
Thread.current[:lux]
|
49
|
+
def current
|
50
|
+
Thread.current[:lux][:page] ||= Lux::Current.new('/mock')
|
41
51
|
end
|
42
52
|
|
43
|
-
def
|
44
|
-
Thread.current[:lux][:page] ||= Lux::Page.prepare('/mock')
|
45
|
-
end
|
46
|
-
|
47
|
-
def page=(what)
|
53
|
+
def current=(what)
|
48
54
|
Thread.current[:lux][:page] = what
|
49
55
|
end
|
50
56
|
|
51
|
-
def
|
52
|
-
Lux::
|
57
|
+
def app &block
|
58
|
+
block ? Lux::Application.class_eval(&block) : Lux::Application
|
53
59
|
end
|
54
60
|
|
55
61
|
def root
|
@@ -61,7 +67,7 @@ module Lux
|
|
61
67
|
end
|
62
68
|
|
63
69
|
def error data
|
64
|
-
|
70
|
+
current.response.status 500
|
65
71
|
Lux::Error.show(data)
|
66
72
|
end
|
67
73
|
|
@@ -70,13 +76,9 @@ module Lux
|
|
70
76
|
puts what
|
71
77
|
end
|
72
78
|
|
73
|
-
def uid
|
74
|
-
Thread.current[:uid_cnt] ||= 0
|
75
|
-
"uid-#{Thread.current[:uid_cnt]+=1}"
|
76
|
-
end
|
77
|
-
|
78
79
|
def on name, ref=nil, &proc
|
79
80
|
EVENTS[name] ||= []
|
81
|
+
|
80
82
|
if block_given?
|
81
83
|
puts "* event: #{name} defined".white
|
82
84
|
EVENTS[name].push(proc)
|
@@ -102,15 +104,23 @@ module Lux
|
|
102
104
|
end
|
103
105
|
|
104
106
|
def speed loops=1
|
105
|
-
render_start = Time.
|
107
|
+
render_start = Time.monotonic
|
106
108
|
loops.times { yield }
|
107
|
-
num = (
|
108
|
-
num = "#{num} ms"
|
109
|
+
num = (Time.monotonic - render_start) * 1000
|
110
|
+
num = "#{num.round(1)} ms"
|
109
111
|
loops == 1 ? num : "Done #{loops.to_s.sub(/(\d)(\d{3})$/,'\1s \2')} loops in #{num}"
|
110
112
|
end
|
111
113
|
|
112
|
-
|
113
|
-
|
114
|
+
# load specific plugin
|
115
|
+
def plugin name
|
116
|
+
dir = '%s/plugins/%s' % [Lux.fw_root, name]
|
117
|
+
base = '%s/base.rb' % dir
|
118
|
+
|
119
|
+
if File.exist?(base)
|
120
|
+
load base
|
121
|
+
else
|
122
|
+
Lux::Config.require_all('%s/*' % dir)
|
123
|
+
end
|
114
124
|
end
|
115
125
|
end
|
116
126
|
|
data/lib/lux/mailer/mailer.rb
CHANGED
@@ -11,63 +11,80 @@
|
|
11
11
|
# Mailer.confirm_email('rejotl@gmailcom').body
|
12
12
|
|
13
13
|
class Lux::Mailer
|
14
|
+
ClassCallbacks.define self, :before, :after
|
15
|
+
class_attribute :helper
|
14
16
|
|
15
|
-
|
17
|
+
attr_reader :mail
|
16
18
|
|
17
|
-
|
19
|
+
class << self
|
20
|
+
# Mailer.prepare(:confirm_email, 'rejotl@gmailcom')
|
21
|
+
def prepare template, *args
|
22
|
+
obj = new
|
23
|
+
obj.instance_variable_set :@_template, template
|
18
24
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
obj.instance_variable_set :@_template, template
|
25
|
+
ClassCallbacks.execute obj, :before
|
26
|
+
obj.send template, *args
|
27
|
+
ClassCallbacks.execute obj, :after
|
23
28
|
|
24
|
-
|
25
|
-
|
26
|
-
BeforeAndAfter.execute(obj, :after)
|
29
|
+
obj
|
30
|
+
end
|
27
31
|
|
28
|
-
|
32
|
+
def render method_name, *args
|
33
|
+
send(method_name, *args).body
|
34
|
+
end
|
35
|
+
|
36
|
+
def method_missing method_sym, *args
|
37
|
+
prepare(method_sym, *args)
|
38
|
+
end
|
39
|
+
|
40
|
+
def deliver
|
41
|
+
send(method_name, *args).deliver
|
42
|
+
end
|
29
43
|
end
|
30
44
|
|
31
|
-
|
32
|
-
|
45
|
+
###
|
46
|
+
|
47
|
+
def initialize
|
48
|
+
@mail = DynamicClass.new subject: nil, body: nil, to: nil, cc: nil, from: nil
|
33
49
|
end
|
34
50
|
|
35
51
|
def deliver
|
36
|
-
raise "From in mailer not defined"
|
37
|
-
raise "To in mailer not defined"
|
38
|
-
raise "Subject in mailer not defined" unless @subject
|
52
|
+
raise "From in mailer not defined" unless @mail.from
|
53
|
+
raise "To in mailer not defined" unless @mail.to
|
54
|
+
raise "Subject in mailer not defined" unless @mail.subject
|
39
55
|
|
40
56
|
require 'mail'
|
41
57
|
|
42
58
|
Mail.defaults { delivery_method Lux.config(:mail).delivery, Lux.config(:mail).opts }
|
43
59
|
|
44
60
|
m = Mail.new
|
45
|
-
m[:from] = @from
|
46
|
-
m[:to] = @to
|
47
|
-
m[:subject] = @subject
|
48
|
-
m[:body] = body
|
61
|
+
m[:from] = @mail.from
|
62
|
+
m[:to] = @mail.to
|
63
|
+
m[:subject] = @mail.subject
|
64
|
+
m[:body] = @mail.body || body
|
49
65
|
m[:content_type] = 'text/html; charset=UTF-8'
|
50
|
-
m.deliver!
|
51
|
-
end
|
52
66
|
|
53
|
-
|
54
|
-
Lux.delay(self, :deliver)
|
67
|
+
Thread.new { m.deliver! }
|
55
68
|
end
|
56
69
|
|
57
|
-
def
|
58
|
-
|
70
|
+
def deliver_later
|
71
|
+
Lux.delay self, :deliver
|
59
72
|
end
|
60
73
|
|
61
74
|
def body
|
62
|
-
|
75
|
+
return @mail.body if @mail.body
|
76
|
+
|
77
|
+
helper = Lux::Helper.new self, self.class.helper
|
78
|
+
|
79
|
+
Lux::Template.render_with_layout "mailer/#{@_template}", helper
|
63
80
|
end
|
64
81
|
|
65
82
|
def subject
|
66
|
-
@subject
|
83
|
+
@mail.subject
|
67
84
|
end
|
68
85
|
|
69
|
-
def
|
70
|
-
|
86
|
+
def to
|
87
|
+
@mail.to
|
71
88
|
end
|
72
89
|
|
73
90
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
|
2
|
+
class Lux::Response::Header
|
3
|
+
attr_reader :data
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@data = {}
|
7
|
+
end
|
8
|
+
|
9
|
+
def [] key
|
10
|
+
@data[key.downcase]
|
11
|
+
end
|
12
|
+
|
13
|
+
def []= key, value
|
14
|
+
@data[key.downcase] = value
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_h
|
18
|
+
@data.to_h.sort.to_h
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,237 @@
|
|
1
|
+
# response.header 'x-blah', 123
|
2
|
+
# response.max_age = 10
|
3
|
+
# response.public = true
|
4
|
+
# response.status = 500
|
5
|
+
class Lux::Response
|
6
|
+
# define in seconds, how long should page be accessible in client cache
|
7
|
+
# if defined, cache becomes public and can be cache by proxies
|
8
|
+
# use with care.only for static resources and
|
9
|
+
attr_reader :max_age
|
10
|
+
|
11
|
+
attr_accessor :body, :headers, :cookies, :content_type, :status, :cookie_multidomain, :cookie_domain
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
@render_start = Time.monotonic
|
15
|
+
@headers = Lux::Response::Header.new
|
16
|
+
@max_age = 0
|
17
|
+
end
|
18
|
+
|
19
|
+
def current
|
20
|
+
Lux.current
|
21
|
+
end
|
22
|
+
|
23
|
+
def header name, value=:_
|
24
|
+
@headers[name] = value if value != :_
|
25
|
+
@headers[name]
|
26
|
+
end
|
27
|
+
|
28
|
+
def max_age= age
|
29
|
+
@max_age = age.to_i
|
30
|
+
end
|
31
|
+
|
32
|
+
def etag *args
|
33
|
+
unless @headers['etag']
|
34
|
+
args.push current.request.url
|
35
|
+
|
36
|
+
key = '"%s"' % Lux.cache.generate_key(args)
|
37
|
+
key = 'W/%s' % key unless max_age > 0
|
38
|
+
|
39
|
+
@headers['etag'] = key
|
40
|
+
end
|
41
|
+
|
42
|
+
if current.request.env['HTTP_IF_NONE_MATCH'] == @headers['etag']
|
43
|
+
@status = 304
|
44
|
+
@body = 'not-modified'
|
45
|
+
true
|
46
|
+
else
|
47
|
+
false
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def status num=nil
|
52
|
+
return @status unless num
|
53
|
+
raise 'Bad status value [%s]' % num unless num.is_numeric?
|
54
|
+
|
55
|
+
@status ||= num
|
56
|
+
@status
|
57
|
+
end
|
58
|
+
alias :status= :status
|
59
|
+
|
60
|
+
def halt status=nil, msg=nil
|
61
|
+
@status = status || 400
|
62
|
+
@body = msg if msg
|
63
|
+
|
64
|
+
throw :done
|
65
|
+
end
|
66
|
+
|
67
|
+
def body what=nil
|
68
|
+
@body ||= what
|
69
|
+
|
70
|
+
if @body && block_given?
|
71
|
+
@body = yield @body
|
72
|
+
Lux.error 'Lux.current.response.body is not a string (bad current.response.body filter)' unless @body.is_a?(String)
|
73
|
+
end
|
74
|
+
|
75
|
+
@body
|
76
|
+
end
|
77
|
+
alias :body= :body
|
78
|
+
|
79
|
+
def body! what
|
80
|
+
@body = what
|
81
|
+
end
|
82
|
+
|
83
|
+
def content_type type=nil
|
84
|
+
return @content_type unless type
|
85
|
+
|
86
|
+
# can be set only once
|
87
|
+
return @content_type if @content_type
|
88
|
+
|
89
|
+
type = 'application/json' if type == :json
|
90
|
+
type = 'text/plain' if type == :text
|
91
|
+
type = 'text/html' if type == :html
|
92
|
+
|
93
|
+
raise 'Invalid page content-type %s' % type if type === Symbol
|
94
|
+
|
95
|
+
@content_type = type
|
96
|
+
end
|
97
|
+
|
98
|
+
def content_type= type
|
99
|
+
content_type type
|
100
|
+
end
|
101
|
+
|
102
|
+
def flash message=nil
|
103
|
+
@flash ||= Flash.new current.session[:lux_flash]
|
104
|
+
|
105
|
+
message ? @flash.error(message) : @flash
|
106
|
+
end
|
107
|
+
|
108
|
+
def redirect where=nil, opts={}
|
109
|
+
return @headers['location'] unless where
|
110
|
+
|
111
|
+
@status = opts.delete(:status) || 302
|
112
|
+
opts.map { |k,v| flash.send(k, v) }
|
113
|
+
|
114
|
+
@headers['location'] = where.index('//') ? where : "#{current.host}#{where}"
|
115
|
+
@headers['access-control-expose-headers'] ||= 'Location'
|
116
|
+
|
117
|
+
@body = %[redirecting to #{@headers['location']}\n\n#{opts.values.join("\n")}]
|
118
|
+
|
119
|
+
throw :done
|
120
|
+
end
|
121
|
+
|
122
|
+
def permanent_redirect where
|
123
|
+
redirect where, status:301
|
124
|
+
end
|
125
|
+
|
126
|
+
# auth { |user, pass| [user, pass] == ['foo', 'bar'] }
|
127
|
+
def auth relam=nil
|
128
|
+
if auth = current.request.env['HTTP_AUTHORIZATION']
|
129
|
+
credentials = auth.to_s.split('Basic ', 2)[1].unpack("m*").first.split(':', 2)
|
130
|
+
return true if yield *credentials
|
131
|
+
end
|
132
|
+
|
133
|
+
status 401
|
134
|
+
header('WWW-Authenticate', 'Basic realm="%s"' % relam.or('default'))
|
135
|
+
body = ErrorCell.unauthorized('HTTP 401 Authorization needed')
|
136
|
+
|
137
|
+
false
|
138
|
+
end
|
139
|
+
|
140
|
+
def write_response_body
|
141
|
+
unless @body
|
142
|
+
@status = 404
|
143
|
+
@body = Lux.error 'Document not found'
|
144
|
+
end
|
145
|
+
|
146
|
+
# respond as JSON if we recive hash
|
147
|
+
if @body.kind_of?(Hash)
|
148
|
+
@body = Lux.dev? ? JSON.pretty_generate(@body) : JSON.generate(@body)
|
149
|
+
|
150
|
+
if current.request.params[:callback]
|
151
|
+
@body = "#{current.request.params[:callback]}(#{ret})"
|
152
|
+
@content_type ||= 'text/javascript'
|
153
|
+
else
|
154
|
+
@content_type ||= 'application/json'
|
155
|
+
end
|
156
|
+
|
157
|
+
@body += "\n"
|
158
|
+
else
|
159
|
+
# if somebody sets @content_type, respect that
|
160
|
+
@body = @body.to_s unless @body.kind_of?(String)
|
161
|
+
@content_type ||= 'text/plain' if @body[0,1] != '<'
|
162
|
+
@content_type ||= 'text/html'
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
def write_response_header
|
167
|
+
domain =
|
168
|
+
if cookie_domain
|
169
|
+
cookie_domain
|
170
|
+
elsif cookie_multidomain && current.domain.index('.')
|
171
|
+
".#{current.domain}"
|
172
|
+
else
|
173
|
+
current.request.host
|
174
|
+
end
|
175
|
+
|
176
|
+
# cache-control
|
177
|
+
@headers['cache-control'] ||= Proc.new do
|
178
|
+
cc = ['max-age=%d' % max_age]
|
179
|
+
|
180
|
+
if max_age > 0
|
181
|
+
cc.push 'public, no-cache'
|
182
|
+
else
|
183
|
+
cc.push 'private, must-revalidate'
|
184
|
+
end
|
185
|
+
|
186
|
+
cc.join(', ')
|
187
|
+
end.call
|
188
|
+
|
189
|
+
current.session[:lux_flash] = flash.to_h
|
190
|
+
|
191
|
+
# dont annd cookies to public pages (images, etc..)
|
192
|
+
add_cookies = true
|
193
|
+
add_cookies = false if @headers['cache-control'].index('public')
|
194
|
+
|
195
|
+
if add_cookies
|
196
|
+
encrypted = Crypt.encrypt(current.session.to_json)
|
197
|
+
|
198
|
+
if current.cookies[Lux.config.session_cookie_name] != encrypted
|
199
|
+
@headers['set-cookie'] = "#{Lux.config.session_cookie_name}=#{encrypted}; Expires=#{(Time.now+1.month).utc}; Path=/; Domain=#{domain};"
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
etag(@body) if current.request.request_method == 'GET'
|
204
|
+
|
205
|
+
@headers['x-lux-speed'] = "#{((Time.monotonic - @render_start)*1000).round(1)} ms"
|
206
|
+
@headers['content-type'] ||= "#{@content_type}; charset=utf-8"
|
207
|
+
@headers['content-length'] = @body.bytesize
|
208
|
+
# if "no-store" is present then HTTP_IF_NONE_MATCH is not sent from browser
|
209
|
+
end
|
210
|
+
|
211
|
+
def write_response
|
212
|
+
write_response_body
|
213
|
+
write_response_header
|
214
|
+
|
215
|
+
@status ||= 200
|
216
|
+
Lux.log " #{@status}, #{@headers['x-lux-speed']}"
|
217
|
+
|
218
|
+
if ENV['LUX_PRINT_ROUTES']
|
219
|
+
print '* Finished route print '
|
220
|
+
puts @status == 404 ? 'without a match'.red : 'with a match'.green
|
221
|
+
exit
|
222
|
+
end
|
223
|
+
|
224
|
+
[@status, @headers.to_h, [@body]]
|
225
|
+
end
|
226
|
+
|
227
|
+
def render
|
228
|
+
Lux.log "\n#{current.request.request_method.white} #{Lux.current.request.path.white}"
|
229
|
+
|
230
|
+
Lux::Config.live_require_check! if Lux.config(:auto_code_reload)
|
231
|
+
|
232
|
+
Lux::Application.new.main
|
233
|
+
|
234
|
+
write_response
|
235
|
+
end
|
236
|
+
|
237
|
+
end
|