gloo-web 1.5 → 1.6
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/objs/element.rb +7 -3
- data/lib/objs/field.rb +1 -1
- data/lib/objs/form.rb +2 -2
- data/lib/objs/page.rb +20 -4
- data/lib/objs/partial.rb +6 -3
- data/lib/objs/svr.rb +54 -27
- data/lib/web_svr/embedded_renderer.rb +6 -4
- data/lib/web_svr/handler.rb +32 -17
- data/lib/web_svr/request_params.rb +4 -2
- data/lib/web_svr/response.rb +2 -1
- data/lib/web_svr/server.rb +54 -13
- data/lib/web_svr/session.rb +8 -3
- metadata +15 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 76804bbf747238b84d964890005f32e2a6d801b3926169120da712ff542d52b1
|
|
4
|
+
data.tar.gz: 907cac263a2583f2c8fa6d1a9b59a5aa2f4542c4e5bad0a7f9a025fb2c153029
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ef2ae150df15c224c1106a5ef35a0f5ad38b498f5791f36add563a90655b2428ca0ba5ee4710938821287a887a2baa663fed53a84e53aaa8a8085c179d489930
|
|
7
|
+
data.tar.gz: d5e7582e24bf8b1a0418dbe9c9c20cf02a73acebbf61bd70215f971a0353faf8bf53a2017f368f125f2df19b768b4231ff4cc8e572c0b0cc96ca5f17b3e0878a
|
data/lib/objs/element.rb
CHANGED
|
@@ -169,7 +169,7 @@ module Objs
|
|
|
169
169
|
end
|
|
170
170
|
|
|
171
171
|
#
|
|
172
|
-
#
|
|
172
|
+
# Render the element as HTML and put it in it.
|
|
173
173
|
#
|
|
174
174
|
def msg_render
|
|
175
175
|
content = self.render_html
|
|
@@ -239,11 +239,15 @@ module Objs
|
|
|
239
239
|
return rendered_obj_content
|
|
240
240
|
end
|
|
241
241
|
|
|
242
|
+
#
|
|
243
|
+
# Render a string or other object; an unexpected failure is
|
|
244
|
+
# handled and renders as blank.
|
|
245
|
+
#
|
|
242
246
|
def self.render_thing e, render_ƒ, engine
|
|
243
247
|
begin
|
|
244
248
|
return e.render( render_ƒ )
|
|
245
249
|
rescue => e
|
|
246
|
-
engine.
|
|
250
|
+
engine.handle_exception e
|
|
247
251
|
return ''
|
|
248
252
|
end
|
|
249
253
|
end
|
|
@@ -265,7 +269,7 @@ module Objs
|
|
|
265
269
|
'content (container) — The element contents.'
|
|
266
270
|
],
|
|
267
271
|
:messages => [
|
|
268
|
-
'render — Manually render the HTML element. Normally the render is called by the web server when the page containing the element is requested.'
|
|
272
|
+
'render — Manually render the HTML element; the HTML is put in it. Normally the render is called by the web server when the page containing the element is requested.'
|
|
269
273
|
],
|
|
270
274
|
:examples => <<~EXAMPLES.strip
|
|
271
275
|
div_sub [e] :
|
data/lib/objs/field.rb
CHANGED
|
@@ -453,7 +453,7 @@ module Objs
|
|
|
453
453
|
'checked (boolean) — Optional; only used for checkbox fields. Whether the checkbox field is checked.'
|
|
454
454
|
],
|
|
455
455
|
:messages => [
|
|
456
|
-
'render — Manually render the HTML field. Normally the render is called by the web server when the page containing the element is requested.'
|
|
456
|
+
'render — Manually render the HTML field; the HTML is put in it. Normally the render is called by the web server when the page containing the element is requested.'
|
|
457
457
|
],
|
|
458
458
|
:examples => <<~EXAMPLES.strip
|
|
459
459
|
f [form] :
|
data/lib/objs/form.rb
CHANGED
|
@@ -260,7 +260,7 @@ module Objs
|
|
|
260
260
|
begin
|
|
261
261
|
return e.render( 'render_html' )
|
|
262
262
|
rescue => e
|
|
263
|
-
@engine.
|
|
263
|
+
@engine.handle_exception e
|
|
264
264
|
return ''
|
|
265
265
|
end
|
|
266
266
|
end
|
|
@@ -286,7 +286,7 @@ module Objs
|
|
|
286
286
|
'content (container) — The collection of form fields. Other elements can also be included here, for formatting or extra buttons.'
|
|
287
287
|
],
|
|
288
288
|
:messages => [
|
|
289
|
-
'render — Manually render the HTML form. Normally the render is called by the web server when the page containing the element is requested.'
|
|
289
|
+
'render — Manually render the HTML form; the HTML is put in it. Normally the render is called by the web server when the page containing the element is requested.'
|
|
290
290
|
],
|
|
291
291
|
:examples => <<~EXAMPLES.strip
|
|
292
292
|
page [can] :
|
data/lib/objs/page.rb
CHANGED
|
@@ -314,14 +314,30 @@ module Objs
|
|
|
314
314
|
end
|
|
315
315
|
|
|
316
316
|
#
|
|
317
|
-
#
|
|
317
|
+
# Render the page and put the content (HTML, JSON or text) in it,
|
|
318
|
+
# or false if it can't render. Only works inside a running web app.
|
|
318
319
|
#
|
|
319
320
|
def msg_render
|
|
320
|
-
|
|
321
|
-
|
|
321
|
+
return nil unless Page.can_render?( @engine, self )
|
|
322
|
+
|
|
323
|
+
response = self.render
|
|
324
|
+
content = response&.data
|
|
325
|
+
@engine.heap.it.set_to( content.nil? ? false : content )
|
|
322
326
|
return content
|
|
323
327
|
end
|
|
324
328
|
|
|
329
|
+
#
|
|
330
|
+
# Is a web app running, so the object can render? If not, report
|
|
331
|
+
# it and put false in it. Shared with partial.
|
|
332
|
+
#
|
|
333
|
+
def self.can_render?( engine, obj )
|
|
334
|
+
return true if engine.app_running?
|
|
335
|
+
|
|
336
|
+
engine.err "#{obj.type_display} '#{obj.name}' can only render inside a web app (gloo-web)."
|
|
337
|
+
engine.heap.it.set_to false
|
|
338
|
+
return false
|
|
339
|
+
end
|
|
340
|
+
|
|
325
341
|
|
|
326
342
|
# ---------------------------------------------------------------------
|
|
327
343
|
# Render
|
|
@@ -584,7 +600,7 @@ module Objs
|
|
|
584
600
|
'download_file (boolean) — Optional, default false. If true, the browser is instructed to download the file instead of rendering it.'
|
|
585
601
|
],
|
|
586
602
|
:messages => [
|
|
587
|
-
'render — Manually render the content of the page. Normally the render is called by the web server when the page is requested.'
|
|
603
|
+
'render — Manually render the content of the page; the content (HTML, JSON or text) is put in it, or false if it can\'t render. Only works inside a running web app (it is an error otherwise). Normally the render is called by the web server when the page is requested.'
|
|
588
604
|
],
|
|
589
605
|
:examples => <<~EXAMPLES.strip
|
|
590
606
|
page [can] :
|
data/lib/objs/partial.rb
CHANGED
|
@@ -140,11 +140,14 @@ module Objs
|
|
|
140
140
|
end
|
|
141
141
|
|
|
142
142
|
#
|
|
143
|
-
#
|
|
143
|
+
# Render the partial and put the HTML in it, or false if it can't
|
|
144
|
+
# render. Only works inside a running web app.
|
|
144
145
|
#
|
|
145
146
|
def msg_render
|
|
147
|
+
return nil unless Page.can_render?( @engine, self )
|
|
148
|
+
|
|
146
149
|
part_content = self.render
|
|
147
|
-
@engine.heap.it.set_to part_content
|
|
150
|
+
@engine.heap.it.set_to( part_content.nil? ? false : part_content )
|
|
148
151
|
return part_content
|
|
149
152
|
end
|
|
150
153
|
|
|
@@ -226,7 +229,7 @@ module Objs
|
|
|
226
229
|
'content (element) — The contents of the partial page.'
|
|
227
230
|
],
|
|
228
231
|
:messages => [
|
|
229
|
-
'render — Manually render the content of the partial page. Normally the render is called by the web server when the page containing the partial is requested.'
|
|
232
|
+
'render — Manually render the content of the partial page; the HTML is put in it, or false if it can\'t render. Only works inside a running web app (it is an error otherwise). Normally the render is called by the web server when the page containing the partial is requested.'
|
|
230
233
|
],
|
|
231
234
|
:examples => <<~EXAMPLES.strip
|
|
232
235
|
shared [can] :
|
data/lib/objs/svr.rb
CHANGED
|
@@ -58,9 +58,10 @@ module Objs
|
|
|
58
58
|
# Default layout for pages.
|
|
59
59
|
LAYOUT = 'layout'.freeze
|
|
60
60
|
|
|
61
|
-
# Alias to the home and
|
|
61
|
+
# Alias to the home, error and not found pages
|
|
62
62
|
HOME = 'home'.freeze
|
|
63
63
|
ERR_PAGE = 'error'.freeze
|
|
64
|
+
NOT_FOUND_PAGE = 'not_found'.freeze
|
|
64
65
|
|
|
65
66
|
# Session
|
|
66
67
|
SESSION = 'session'.freeze
|
|
@@ -68,6 +69,7 @@ module Objs
|
|
|
68
69
|
|
|
69
70
|
# Messages
|
|
70
71
|
SERVER_NOT_RUNNING = 'The web server is not running!'.freeze
|
|
72
|
+
SERVER_ALREADY_RUNNING = 'The web server is already running!'.freeze
|
|
71
73
|
|
|
72
74
|
#
|
|
73
75
|
# Should the current request be redirected?
|
|
@@ -123,13 +125,20 @@ module Objs
|
|
|
123
125
|
# Configuration
|
|
124
126
|
# ---------------------------------------------------------------------
|
|
125
127
|
|
|
128
|
+
#
|
|
129
|
+
# Get the config child with the given name.
|
|
130
|
+
# Returns nil if there is none, or no config container.
|
|
131
|
+
#
|
|
132
|
+
def config_child( name )
|
|
133
|
+
return find_child( CONFIG )&.find_child( name )
|
|
134
|
+
end
|
|
135
|
+
|
|
126
136
|
#
|
|
127
137
|
# Get the Scheme (http or https) from the child object.
|
|
128
138
|
# Returns nil if there is none.
|
|
129
139
|
#
|
|
130
140
|
def scheme_value
|
|
131
|
-
|
|
132
|
-
scheme = config.find_child SCHEME
|
|
141
|
+
scheme = config_child SCHEME
|
|
133
142
|
return nil unless scheme
|
|
134
143
|
|
|
135
144
|
return scheme.value
|
|
@@ -140,8 +149,7 @@ module Objs
|
|
|
140
149
|
# Returns nil if there is none.
|
|
141
150
|
#
|
|
142
151
|
def host_value
|
|
143
|
-
|
|
144
|
-
host = config.find_child HOST
|
|
152
|
+
host = config_child HOST
|
|
145
153
|
return nil unless host
|
|
146
154
|
|
|
147
155
|
return host.value
|
|
@@ -152,8 +160,7 @@ module Objs
|
|
|
152
160
|
# Returns nil if there is none.
|
|
153
161
|
#
|
|
154
162
|
def port_value
|
|
155
|
-
|
|
156
|
-
port = config.find_child PORT
|
|
163
|
+
port = config_child PORT
|
|
157
164
|
return nil unless port
|
|
158
165
|
|
|
159
166
|
return port.value
|
|
@@ -171,8 +178,7 @@ module Objs
|
|
|
171
178
|
# Get the session cookie name.
|
|
172
179
|
#
|
|
173
180
|
def session_name
|
|
174
|
-
|
|
175
|
-
session_name = config.find_child SESSION_NAME
|
|
181
|
+
session_name = config_child SESSION_NAME
|
|
176
182
|
return nil unless session_name
|
|
177
183
|
|
|
178
184
|
name = session_name.value
|
|
@@ -185,8 +191,7 @@ module Objs
|
|
|
185
191
|
# Get the key for the encryption cipher.
|
|
186
192
|
#
|
|
187
193
|
def encryption_key
|
|
188
|
-
|
|
189
|
-
o = config.find_child ENCRYPT_KEY
|
|
194
|
+
o = config_child ENCRYPT_KEY
|
|
190
195
|
return nil unless o
|
|
191
196
|
|
|
192
197
|
o = Gloo::Objs::Alias.resolve_alias( @engine, o )
|
|
@@ -197,8 +202,7 @@ module Objs
|
|
|
197
202
|
# Get the initialization vector for the cipher.
|
|
198
203
|
#
|
|
199
204
|
def encryption_iv
|
|
200
|
-
|
|
201
|
-
o = config.find_child ENCRYPT_IV
|
|
205
|
+
o = config_child ENCRYPT_IV
|
|
202
206
|
return nil unless o
|
|
203
207
|
|
|
204
208
|
o = Gloo::Objs::Alias.resolve_alias( @engine, o )
|
|
@@ -210,8 +214,7 @@ module Objs
|
|
|
210
214
|
# If not specified, use the root path.
|
|
211
215
|
#
|
|
212
216
|
def session_cookie_path
|
|
213
|
-
|
|
214
|
-
o = config.find_child COOKIE_PATH
|
|
217
|
+
o = config_child COOKIE_PATH
|
|
215
218
|
if o
|
|
216
219
|
return o.value
|
|
217
220
|
else
|
|
@@ -224,8 +227,7 @@ module Objs
|
|
|
224
227
|
# If not specified, use one week from now.
|
|
225
228
|
#
|
|
226
229
|
def session_cookie_expires
|
|
227
|
-
|
|
228
|
-
o = config.find_child COOKIE_EXPIRES
|
|
230
|
+
o = config_child COOKIE_EXPIRES
|
|
229
231
|
if o
|
|
230
232
|
dt = Chronic.parse( o.value )
|
|
231
233
|
return dt
|
|
@@ -239,7 +241,7 @@ module Objs
|
|
|
239
241
|
# Get the value from the scheme settings/config.
|
|
240
242
|
#
|
|
241
243
|
def session_cookie_secure
|
|
242
|
-
return scheme_value
|
|
244
|
+
return scheme_value&.downcase == HTTPS
|
|
243
245
|
end
|
|
244
246
|
|
|
245
247
|
|
|
@@ -392,6 +394,7 @@ module Objs
|
|
|
392
394
|
fac.create_alias LAYOUT, nil, self
|
|
393
395
|
fac.create_alias HOME, nil, self
|
|
394
396
|
fac.create_alias ERR_PAGE, nil, self
|
|
397
|
+
fac.create_alias NOT_FOUND_PAGE, nil, self
|
|
395
398
|
|
|
396
399
|
fac.create_can PAGES, self
|
|
397
400
|
end
|
|
@@ -415,6 +418,11 @@ module Objs
|
|
|
415
418
|
# Start the gloo web server.
|
|
416
419
|
#
|
|
417
420
|
def msg_start
|
|
421
|
+
if @engine.app_running?
|
|
422
|
+
@engine.err SERVER_ALREADY_RUNNING
|
|
423
|
+
return
|
|
424
|
+
end
|
|
425
|
+
|
|
418
426
|
@engine.log.debug "Starting web server…"
|
|
419
427
|
# @engine.log.quiet = true
|
|
420
428
|
|
|
@@ -522,12 +530,14 @@ module Objs
|
|
|
522
530
|
# Start running the web server.
|
|
523
531
|
#
|
|
524
532
|
def start
|
|
525
|
-
|
|
533
|
+
# Settings that aren't given use the defaults.
|
|
534
|
+
config = WebSvr::Config.new( scheme_value || WebSvr::Config::HTTP,
|
|
535
|
+
host_value || WebSvr::Config::LOCALHOST,
|
|
536
|
+
port_value || WebSvr::Config::PORT_DEFAULT )
|
|
526
537
|
@engine.log.info "Web Server URL: #{config.base_url}"
|
|
527
538
|
|
|
528
539
|
handler = WebSvr::Handler.new( @engine, self )
|
|
529
540
|
@web_server = WebSvr::Server.new( @engine, handler, config, ssl_config )
|
|
530
|
-
@web_server.start
|
|
531
541
|
|
|
532
542
|
@router = Routing::Router.new( @engine, self )
|
|
533
543
|
@router.add_page_routes
|
|
@@ -540,6 +550,10 @@ module Objs
|
|
|
540
550
|
@session = WebSvr::Session.new( @engine, self )
|
|
541
551
|
|
|
542
552
|
run_on_start
|
|
553
|
+
|
|
554
|
+
# Listen last: if the server can't start, it stops the running
|
|
555
|
+
# app from its own thread, so everything else must be done.
|
|
556
|
+
@web_server.start
|
|
543
557
|
@engine.log.info "Web server started and listening…"
|
|
544
558
|
end
|
|
545
559
|
|
|
@@ -658,7 +672,7 @@ module Objs
|
|
|
658
672
|
data.find_child( PAGE )&.set_value( page_obj.pn )
|
|
659
673
|
end
|
|
660
674
|
rescue => e
|
|
661
|
-
@engine.
|
|
675
|
+
@engine.handle_exception e
|
|
662
676
|
end
|
|
663
677
|
end
|
|
664
678
|
|
|
@@ -696,6 +710,17 @@ module Objs
|
|
|
696
710
|
return o
|
|
697
711
|
end
|
|
698
712
|
|
|
713
|
+
#
|
|
714
|
+
# Get the application not found page.
|
|
715
|
+
#
|
|
716
|
+
def not_found_page
|
|
717
|
+
o = find_child NOT_FOUND_PAGE
|
|
718
|
+
return nil unless o
|
|
719
|
+
|
|
720
|
+
o = Gloo::Objs::Alias.resolve_alias( @engine, o )
|
|
721
|
+
return o
|
|
722
|
+
end
|
|
723
|
+
|
|
699
724
|
#
|
|
700
725
|
# Get the default layout for pages.
|
|
701
726
|
#
|
|
@@ -720,12 +745,13 @@ module Objs
|
|
|
720
745
|
:shortcut => KEYWORD_SHORT,
|
|
721
746
|
:description => 'A web server running inside gloo.',
|
|
722
747
|
:children => [
|
|
723
|
-
'config (container) — Configuration and settings for the server. See below for its children.',
|
|
748
|
+
'config (container) — Configuration and settings for the server. See below for its children. Settings left out use the defaults.',
|
|
724
749
|
'on_start (script) — Run when the web server is started.',
|
|
725
750
|
'on_stop (script) — Run when the web server is stopped.',
|
|
726
751
|
"layout (partial) — By convention an alias pointing to the layout used for all pages (layouts live in the layout root-level folder).",
|
|
727
752
|
'home (page) — By convention an alias pointing to the home page object (pages live in the page root-level folder).',
|
|
728
|
-
'error (page) — By convention an alias pointing to the default error page object.',
|
|
753
|
+
'error (page) — By convention an alias pointing to the default error page object. Sent with a 500 when a request fails; without one, a plain "Server error!" is sent.',
|
|
754
|
+
'not_found (page) — By convention an alias pointing to the page sent with a 404 when no route or file matches the request; without one, a plain "Not found" is sent.',
|
|
729
755
|
'pages (container) — Routes. By convention, aliases pointing to pages in the page root-level folder.',
|
|
730
756
|
'config.scheme (string) — \'http\' or \'https\'.',
|
|
731
757
|
"config.host (string) — Default: 'localhost'.",
|
|
@@ -735,16 +761,16 @@ module Objs
|
|
|
735
761
|
'config.encryption_iv (string) — Optional. Initialization vector for the session cookie encryption key.',
|
|
736
762
|
"config.cookie_expires (string) — Optional, default 'in 1 week'. When the session expires.",
|
|
737
763
|
"config.cookie_path (string) — Optional, default '/'. The path for the session cookie.",
|
|
738
|
-
'
|
|
739
|
-
'
|
|
764
|
+
'ssl_cert (string or file) — Optional, required for SSL; a child of the server, not of config. Path to certificate.pem. May be an alias.',
|
|
765
|
+
'ssl_key (string or file) — Optional, required for SSL; a child of the server, not of config. Path to key.pem. May be an alias.',
|
|
740
766
|
'on_request (script) — Optional. Run when the web server receives a request.',
|
|
741
767
|
'request_data (container) — Optional. Data available for use in on_request or elsewhere in the page rendering life-cycle: method, host, path, query, ip (all string, all optional, populated only if present).',
|
|
742
768
|
'on_response (script) — Optional. Run when the web server is done rendering and about to return a response.',
|
|
743
769
|
'response_data (container) — Optional. Data available for use in on_response (request_data is also available at this point): page, type, code, elapsed, db (all string, all optional, populated only if present).'
|
|
744
770
|
],
|
|
745
771
|
:messages => [
|
|
746
|
-
'start — Start the web server.',
|
|
747
|
-
'stop — Stop the web server.',
|
|
772
|
+
'start — Start the web server. It is an error if a web server is already running. If it can\'t listen on its port (in use, or needs root privileges), that is reported as an error and the server stops.',
|
|
773
|
+
'stop — Stop the web server. It is an error if it is not running.',
|
|
748
774
|
'list_routes — Show the routing table. A debugging tool.',
|
|
749
775
|
'list_assets — Show the list of assets. A debugging tool.',
|
|
750
776
|
'list_asset_img — Show the list of image assets. A debugging tool.',
|
|
@@ -773,6 +799,7 @@ module Objs
|
|
|
773
799
|
layout [alias] : layout.primary
|
|
774
800
|
home [alias] : page.home
|
|
775
801
|
error [alias] : page.err
|
|
802
|
+
not_found [alias] : page.not_found
|
|
776
803
|
|
|
777
804
|
# Routes for the web server.
|
|
778
805
|
pages [container] :
|
|
@@ -98,7 +98,7 @@ module WebSvr
|
|
|
98
98
|
#
|
|
99
99
|
# Handle a missing method by looking for a helper function.
|
|
100
100
|
# If there is one, then call it and return the result.
|
|
101
|
-
# If not,
|
|
101
|
+
# If not, report an error and return nil (it renders as blank).
|
|
102
102
|
#
|
|
103
103
|
def method_missing( method_name, *args )
|
|
104
104
|
@log.debug "missing method '#{method_name}' with args #{args}"
|
|
@@ -108,11 +108,13 @@ module WebSvr
|
|
|
108
108
|
|
|
109
109
|
pn = Gloo::Core::Pn.new( @engine, helper_pn )
|
|
110
110
|
obj = pn.resolve
|
|
111
|
-
if obj
|
|
111
|
+
if obj.nil?
|
|
112
|
+
@engine.err "Helper function '#{method_name}' was not found; add it as #{helper_pn}."
|
|
113
|
+
elsif !obj.respond_to?( :invoke )
|
|
114
|
+
@engine.err "'#{helper_pn}' is not a function."
|
|
115
|
+
else
|
|
112
116
|
@log.debug "found obj: #{obj.pn}"
|
|
113
117
|
return obj.invoke args
|
|
114
|
-
else
|
|
115
|
-
@log.error "Function not found: #{helper_pn}"
|
|
116
118
|
end
|
|
117
119
|
|
|
118
120
|
return nil
|
data/lib/web_svr/handler.rb
CHANGED
|
@@ -7,7 +7,10 @@
|
|
|
7
7
|
|
|
8
8
|
module WebSvr
|
|
9
9
|
class Handler
|
|
10
|
-
|
|
10
|
+
|
|
11
|
+
SERVER_ERR_MSG = 'Server error!'.freeze
|
|
12
|
+
NOT_FOUND_MSG = 'Not found'.freeze
|
|
13
|
+
|
|
11
14
|
attr_reader :server_obj
|
|
12
15
|
|
|
13
16
|
|
|
@@ -55,7 +58,7 @@ module WebSvr
|
|
|
55
58
|
page_obj = page
|
|
56
59
|
end
|
|
57
60
|
else
|
|
58
|
-
result =
|
|
61
|
+
result = not_found_result
|
|
59
62
|
end
|
|
60
63
|
|
|
61
64
|
return result, page_obj
|
|
@@ -87,7 +90,7 @@ module WebSvr
|
|
|
87
90
|
|
|
88
91
|
# Check to make sure it is a valid file
|
|
89
92
|
# return error if it is not
|
|
90
|
-
return
|
|
93
|
+
return not_found_result unless File.exist? pn
|
|
91
94
|
|
|
92
95
|
return @server_obj.asset.render_file pn
|
|
93
96
|
end
|
|
@@ -98,25 +101,37 @@ module WebSvr
|
|
|
98
101
|
# ---------------------------------------------------------------------
|
|
99
102
|
|
|
100
103
|
#
|
|
101
|
-
# Return a server error result
|
|
102
|
-
#
|
|
104
|
+
# Return a server error result: the app's error page, or a generic
|
|
105
|
+
# message, sent as a 500.
|
|
103
106
|
#
|
|
104
107
|
def server_error_result
|
|
105
|
-
|
|
106
|
-
|
|
108
|
+
return page_or_text_result( @server_obj.err_page,
|
|
109
|
+
SERVER_ERR_MSG, WebSvr::ResponseCode::SERVER_ERR )
|
|
110
|
+
end
|
|
107
111
|
|
|
108
|
-
# Last resort, just return a generic error message.
|
|
109
|
-
return WebSvr::Response.text_response( @engine,
|
|
110
|
-
"Server error!", WebSvr::ResponseCode::SERVER_ERR )
|
|
111
|
-
end
|
|
112
|
-
|
|
113
112
|
#
|
|
114
|
-
#
|
|
113
|
+
# Return a not found result: the app's not found page, or a generic
|
|
114
|
+
# message, sent as a 404.
|
|
115
115
|
#
|
|
116
|
-
def
|
|
117
|
-
return
|
|
118
|
-
|
|
119
|
-
end
|
|
116
|
+
def not_found_result
|
|
117
|
+
return page_or_text_result( @server_obj.not_found_page,
|
|
118
|
+
NOT_FOUND_MSG, WebSvr::ResponseCode::NOT_FOUND )
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
#
|
|
122
|
+
# Render the given page with the given status code, whatever the
|
|
123
|
+
# page's own return code. Without a page, or if it doesn't render,
|
|
124
|
+
# send the message as text.
|
|
125
|
+
#
|
|
126
|
+
def page_or_text_result( page, msg, code )
|
|
127
|
+
result = page.render if page.is_a?( Objs::Page )
|
|
128
|
+
if result
|
|
129
|
+
result.code = code
|
|
130
|
+
return result
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
return WebSvr::Response.text_response( @engine, msg, code )
|
|
134
|
+
end
|
|
120
135
|
|
|
121
136
|
|
|
122
137
|
# ---------------------------------------------------------------------
|
|
@@ -53,6 +53,9 @@ module WebSvr
|
|
|
53
53
|
begin
|
|
54
54
|
@body_params = Rack::Utils.parse_query body
|
|
55
55
|
rescue => exception
|
|
56
|
+
# A binary body (a file upload) isn't a query string and
|
|
57
|
+
# fails to parse; read it as multipart instead. Any problem
|
|
58
|
+
# with that is reported there.
|
|
56
59
|
init_multipart body
|
|
57
60
|
end
|
|
58
61
|
else
|
|
@@ -101,8 +104,7 @@ module WebSvr
|
|
|
101
104
|
@body_params[ 'file_size' ] = binary_data.length
|
|
102
105
|
@body_params[ 'file_data' ] = binary_data
|
|
103
106
|
rescue => ex
|
|
104
|
-
@engine.
|
|
105
|
-
# @log.error "Error parsing multipart request", ex
|
|
107
|
+
@engine.err "Could not read the uploaded file: #{ex.message}"
|
|
106
108
|
end
|
|
107
109
|
end
|
|
108
110
|
|
data/lib/web_svr/response.rb
CHANGED
data/lib/web_svr/server.rb
CHANGED
|
@@ -25,7 +25,11 @@ require 'rack'
|
|
|
25
25
|
|
|
26
26
|
module WebSvr
|
|
27
27
|
class Server
|
|
28
|
-
|
|
28
|
+
|
|
29
|
+
# EventMachine (under Thin) raises a RuntimeError starting with this
|
|
30
|
+
# when it can't listen: the port is in use or needs root.
|
|
31
|
+
NO_ACCEPTOR = 'no acceptor'.freeze
|
|
32
|
+
|
|
29
33
|
# ---------------------------------------------------------------------
|
|
30
34
|
# Initialization
|
|
31
35
|
# ---------------------------------------------------------------------
|
|
@@ -52,20 +56,34 @@ module WebSvr
|
|
|
52
56
|
# Start the web server.
|
|
53
57
|
#
|
|
54
58
|
def start
|
|
59
|
+
@server_thread = Thread.new { run_server }
|
|
60
|
+
@log.debug 'Web server has started.'
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
#
|
|
64
|
+
# Run the web server. This doesn't return while the server is
|
|
65
|
+
# running, so it runs in its own thread. If the server fails, it is
|
|
66
|
+
# reported here and the running app is stopped.
|
|
67
|
+
#
|
|
68
|
+
def run_server
|
|
55
69
|
opts = {
|
|
56
70
|
:Port => @config.port,
|
|
57
71
|
:Host => @config.host
|
|
58
72
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
server.ssl = true
|
|
64
|
-
server.ssl_options = @ssl_config
|
|
65
|
-
end
|
|
73
|
+
Rack::Handler::Thin.run( self, **opts ) do |server|
|
|
74
|
+
if @ssl_config
|
|
75
|
+
server.ssl = true
|
|
76
|
+
server.ssl_options = @ssl_config
|
|
66
77
|
end
|
|
67
|
-
|
|
68
|
-
|
|
78
|
+
end
|
|
79
|
+
rescue => e
|
|
80
|
+
if e.message.start_with?( NO_ACCEPTOR )
|
|
81
|
+
@engine.err "Could not start the web server on #{@config.host}:#{@config.port}: " \
|
|
82
|
+
'the port is in use or needs root privileges.'
|
|
83
|
+
else
|
|
84
|
+
@engine.handle_exception e
|
|
85
|
+
end
|
|
86
|
+
@engine.stop_running_app
|
|
69
87
|
end
|
|
70
88
|
|
|
71
89
|
#
|
|
@@ -74,7 +92,8 @@ module WebSvr
|
|
|
74
92
|
def stop
|
|
75
93
|
@log.debug 'Stopping the web server…'
|
|
76
94
|
|
|
77
|
-
|
|
95
|
+
# When the server thread itself failed, it is ending already.
|
|
96
|
+
@server_thread.kill unless Thread.current == @server_thread
|
|
78
97
|
|
|
79
98
|
@log.debug 'The web server has been stopped.'
|
|
80
99
|
end
|
|
@@ -92,9 +111,31 @@ module WebSvr
|
|
|
92
111
|
request.log
|
|
93
112
|
|
|
94
113
|
response = request.process
|
|
95
|
-
response.log if response
|
|
96
114
|
|
|
97
|
-
|
|
115
|
+
# A page that failed to render gives no response.
|
|
116
|
+
response ||= @handler.server_error_result
|
|
117
|
+
response.log
|
|
118
|
+
|
|
119
|
+
return response.result
|
|
120
|
+
rescue => e
|
|
121
|
+
# A bug in gloo-web's own code. Errors in gloo statements are
|
|
122
|
+
# handled where they happen, so this is the unexpected case:
|
|
123
|
+
# report it and send the error page.
|
|
124
|
+
@engine.handle_exception e
|
|
125
|
+
return error_result
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
#
|
|
129
|
+
# The result for a request that failed: the app's error page, or a
|
|
130
|
+
# plain 500 if that fails too.
|
|
131
|
+
#
|
|
132
|
+
def error_result
|
|
133
|
+
return @handler.server_error_result.result
|
|
134
|
+
rescue => e
|
|
135
|
+
@engine.handle_exception e
|
|
136
|
+
return [ WebSvr::ResponseCode::SERVER_ERR,
|
|
137
|
+
{ WebSvr::Response::CONTENT_TYPE => WebSvr::Response::TEXT_TYPE },
|
|
138
|
+
WebSvr::Handler::SERVER_ERR_MSG ]
|
|
98
139
|
end
|
|
99
140
|
|
|
100
141
|
|
data/lib/web_svr/session.rb
CHANGED
|
@@ -9,12 +9,14 @@
|
|
|
9
9
|
# https://en.wikipedia.org/wiki/HTTP_cookie
|
|
10
10
|
#
|
|
11
11
|
require 'base64'
|
|
12
|
+
require 'openssl'
|
|
12
13
|
|
|
13
14
|
module WebSvr
|
|
14
15
|
class Session
|
|
15
16
|
|
|
16
17
|
SESSION_CONTAINER = 'session'.freeze
|
|
17
18
|
SESSION_ID_NAME = 'session_id'.freeze
|
|
19
|
+
SESSION_UNREADABLE = 'Session cookie could not be read; starting a new session.'.freeze
|
|
18
20
|
|
|
19
21
|
|
|
20
22
|
# ---------------------------------------------------------------------
|
|
@@ -64,7 +66,8 @@ module WebSvr
|
|
|
64
66
|
end
|
|
65
67
|
end
|
|
66
68
|
rescue => e
|
|
67
|
-
|
|
69
|
+
# Not expected: a bad cookie is handled in decode_decrypt.
|
|
70
|
+
@engine.handle_exception e
|
|
68
71
|
end
|
|
69
72
|
end
|
|
70
73
|
|
|
@@ -166,8 +169,10 @@ module WebSvr
|
|
|
166
169
|
begin
|
|
167
170
|
data = Gloo::Objs::Cipher.decrypt( data, key, iv )
|
|
168
171
|
return JSON.parse( data )
|
|
169
|
-
rescue
|
|
170
|
-
|
|
172
|
+
rescue OpenSSL::Cipher::CipherError, JSON::ParserError
|
|
173
|
+
# The cookie was made with another key, or has been changed.
|
|
174
|
+
# Not the app's error: the visitor gets a new session.
|
|
175
|
+
@engine.warn SESSION_UNREADABLE
|
|
171
176
|
return nil
|
|
172
177
|
end
|
|
173
178
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: gloo-web
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: '1.
|
|
4
|
+
version: '1.6'
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Eric Crane
|
|
@@ -9,6 +9,20 @@ bindir: bin
|
|
|
9
9
|
cert_chain: []
|
|
10
10
|
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: gloo
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '7.0'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '7.0'
|
|
12
26
|
- !ruby/object:Gem::Dependency
|
|
13
27
|
name: thin
|
|
14
28
|
requirement: !ruby/object:Gem::Requirement
|