gloo-web 1.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 +7 -0
- data/lib/gloo-web.rb +48 -0
- data/lib/objs/element.rb +252 -0
- data/lib/objs/field.rb +428 -0
- data/lib/objs/form.rb +269 -0
- data/lib/objs/page.rb +560 -0
- data/lib/objs/partial.rb +208 -0
- data/lib/objs/svr.rb +711 -0
- data/lib/routing/resource_router.rb +43 -0
- data/lib/routing/router.rb +228 -0
- data/lib/routing/show_routes.rb +90 -0
- data/lib/web_svr/asset.rb +405 -0
- data/lib/web_svr/asset_info.rb +114 -0
- data/lib/web_svr/config.rb +55 -0
- data/lib/web_svr/embedded_renderer.rb +152 -0
- data/lib/web_svr/handler.rb +152 -0
- data/lib/web_svr/request.rb +141 -0
- data/lib/web_svr/request_params.rb +179 -0
- data/lib/web_svr/response.rb +175 -0
- data/lib/web_svr/response_code.rb +67 -0
- data/lib/web_svr/server.rb +102 -0
- data/lib/web_svr/session.rb +213 -0
- data/lib/web_svr/table_renderer.rb +149 -0
- data/lib/web_svr/web_method.rb +52 -0
- metadata +81 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Author:: Eric Crane (mailto:eric.crane@mac.com)
|
|
2
|
+
# Copyright:: Copyright (c) 2024 Eric Crane. All rights reserved.
|
|
3
|
+
#
|
|
4
|
+
# A helper class for Resource routing.
|
|
5
|
+
#
|
|
6
|
+
|
|
7
|
+
module Routing
|
|
8
|
+
class ResourceRouter
|
|
9
|
+
|
|
10
|
+
INDEX = 'index'.freeze
|
|
11
|
+
SHOW = 'show'.freeze
|
|
12
|
+
DELETE = 'delete'.freeze
|
|
13
|
+
UPDATE = 'update'.freeze
|
|
14
|
+
|
|
15
|
+
POST_ROUTE = 'create'.freeze
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
#
|
|
19
|
+
# Is the given route segment an implicit create resource?
|
|
20
|
+
# It is explicit if it is 'create'
|
|
21
|
+
# and implicit if it is a POST to the resource.
|
|
22
|
+
#
|
|
23
|
+
def self.is_implicit_create?( method, route_segment )
|
|
24
|
+
return false unless WebSvr::WebMethod.is_post?( method )
|
|
25
|
+
|
|
26
|
+
return ! route_segment.eql?( POST_ROUTE )
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
#
|
|
30
|
+
# Add the segment based on the method.
|
|
31
|
+
#
|
|
32
|
+
def self.segment_for_method( method )
|
|
33
|
+
if WebSvr::WebMethod.is_delete?( method )
|
|
34
|
+
return DELETE
|
|
35
|
+
elsif WebSvr::WebMethod.is_patch?( method )
|
|
36
|
+
return UPDATE
|
|
37
|
+
else
|
|
38
|
+
return SHOW
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
# Author:: Eric Crane (mailto:eric.crane@mac.com)
|
|
2
|
+
# Copyright:: Copyright (c) 2024 Eric Crane. All rights reserved.
|
|
3
|
+
#
|
|
4
|
+
# A helper class for page routing.
|
|
5
|
+
#
|
|
6
|
+
|
|
7
|
+
module Routing
|
|
8
|
+
class Router
|
|
9
|
+
|
|
10
|
+
PAGE_CONTAINER = 'page'.freeze
|
|
11
|
+
SEGMENT_DIVIDER = '/'.freeze
|
|
12
|
+
|
|
13
|
+
attr_reader :route_segments
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
# ---------------------------------------------------------------------
|
|
17
|
+
# Initialization
|
|
18
|
+
# ---------------------------------------------------------------------
|
|
19
|
+
|
|
20
|
+
#
|
|
21
|
+
# Set up the web server.
|
|
22
|
+
#
|
|
23
|
+
def initialize( engine, web_svr_obj )
|
|
24
|
+
@engine = engine
|
|
25
|
+
@log = @engine.log
|
|
26
|
+
|
|
27
|
+
@web_svr_obj = web_svr_obj
|
|
28
|
+
@show_routes = ShowRoutes.new( @engine )
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
# ---------------------------------------------------------------------
|
|
33
|
+
# Routing
|
|
34
|
+
# ---------------------------------------------------------------------
|
|
35
|
+
|
|
36
|
+
#
|
|
37
|
+
# Find and return the page for the given route.
|
|
38
|
+
#
|
|
39
|
+
def page_for_route( path, method )
|
|
40
|
+
@log.info "routing to #{path} for method #{method}"
|
|
41
|
+
@method = method
|
|
42
|
+
route_params = nil
|
|
43
|
+
@id = nil
|
|
44
|
+
|
|
45
|
+
detect_segments path
|
|
46
|
+
|
|
47
|
+
return @web_svr_obj.home_page if is_root_path?
|
|
48
|
+
|
|
49
|
+
pages = @web_svr_obj.pages_container
|
|
50
|
+
if pages
|
|
51
|
+
# If the method is POST and the last segment is NOT 'create',
|
|
52
|
+
# we'll add create to the route segments.
|
|
53
|
+
if Routing::ResourceRouter.is_implicit_create?( method, @route_segments.last )
|
|
54
|
+
@route_segments << Routing::ResourceRouter::POST_ROUTE
|
|
55
|
+
page = find_route_segment( pages.children )
|
|
56
|
+
return [ page, @id, route_params ] if page
|
|
57
|
+
|
|
58
|
+
# We didn't find the page, so remove the last segment and try again
|
|
59
|
+
# posting to the resource.
|
|
60
|
+
@route_segments.pop
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
page = find_route_segment( pages.children )
|
|
64
|
+
|
|
65
|
+
# Are there any remaining segments to be added as route parameters?
|
|
66
|
+
if @route_segments.count > 0
|
|
67
|
+
route_params = @route_segments
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
return [ page, @id, route_params ] if page
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
return nil
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
# ---------------------------------------------------------------------
|
|
78
|
+
# Dynamic Add Page Routes
|
|
79
|
+
# ---------------------------------------------------------------------
|
|
80
|
+
|
|
81
|
+
#
|
|
82
|
+
# Get the root level page container.
|
|
83
|
+
#
|
|
84
|
+
def page_container
|
|
85
|
+
pn = Gloo::Core::Pn.new( @engine, PAGE_CONTAINER )
|
|
86
|
+
return pn.resolve
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
#
|
|
90
|
+
# Add all page routes to the web server pages (routes).
|
|
91
|
+
#
|
|
92
|
+
def add_page_routes
|
|
93
|
+
can = page_container
|
|
94
|
+
return unless can
|
|
95
|
+
|
|
96
|
+
@log.debug 'Adding page routes to web server…'
|
|
97
|
+
@factory = @engine.factory
|
|
98
|
+
|
|
99
|
+
add_pages can, @web_svr_obj.pages_container
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
#
|
|
103
|
+
# Add the pages to the web server pages.
|
|
104
|
+
# This is a recursive function that will add all
|
|
105
|
+
# pages in the folder and subfolders.
|
|
106
|
+
#
|
|
107
|
+
def add_pages can, parent
|
|
108
|
+
# for each file in the page container
|
|
109
|
+
# create a page object and add it to the routes
|
|
110
|
+
can.children.each do |obj|
|
|
111
|
+
if obj.class == Gloo::Objs::Container
|
|
112
|
+
child_can = parent.find_add_child( obj.name, 'container' )
|
|
113
|
+
add_pages( obj, child_can )
|
|
114
|
+
elsif obj.class == Objs::Page
|
|
115
|
+
add_route_alias( parent, obj.name, obj.pn )
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
#
|
|
121
|
+
# Add route alias to the page.
|
|
122
|
+
#
|
|
123
|
+
def add_route_alias( parent, name, pn )
|
|
124
|
+
name = name.gsub( '.', '_' )
|
|
125
|
+
|
|
126
|
+
# First make sure the child doesn't already exist.
|
|
127
|
+
child = parent.find_child( name )
|
|
128
|
+
return if child
|
|
129
|
+
|
|
130
|
+
@factory.create_alias( name, pn, parent )
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
# ---------------------------------------------------------------------
|
|
135
|
+
# Helper funcions
|
|
136
|
+
# ---------------------------------------------------------------------
|
|
137
|
+
|
|
138
|
+
#
|
|
139
|
+
# Show the routes in the running app.
|
|
140
|
+
# This uses the ShowRoutes helper class.
|
|
141
|
+
#
|
|
142
|
+
def show_routes
|
|
143
|
+
@show_routes.show page_container
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
#
|
|
147
|
+
# Find the route segment in the object container.
|
|
148
|
+
#
|
|
149
|
+
def find_route_segment objs
|
|
150
|
+
this_segment = next_segment
|
|
151
|
+
|
|
152
|
+
if this_segment.blank? # && WebSvr::WebMethod.is_post?( @method )
|
|
153
|
+
this_segment = Routing::ResourceRouter::INDEX
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
objs.each do |o|
|
|
157
|
+
o = Gloo::Objs::Alias.resolve_alias( @engine, o )
|
|
158
|
+
|
|
159
|
+
if o.name == this_segment
|
|
160
|
+
if o.class == Objs::Page
|
|
161
|
+
@log.debug "found page for route: #{o.pn}"
|
|
162
|
+
return o
|
|
163
|
+
elsif o.class == Gloo::Objs::FileHandle
|
|
164
|
+
@log.debug "found static file for route: #{o.pn}"
|
|
165
|
+
return o
|
|
166
|
+
else
|
|
167
|
+
return nil unless o.child_count > 0
|
|
168
|
+
|
|
169
|
+
return find_route_segment( o.children )
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
return nil
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
#
|
|
178
|
+
# Get the next segment in the route.
|
|
179
|
+
#
|
|
180
|
+
def next_segment
|
|
181
|
+
this_segment = @route_segments.shift
|
|
182
|
+
return nil if this_segment.nil?
|
|
183
|
+
|
|
184
|
+
# A URL might include a dot in a name, but we can't do that
|
|
185
|
+
# because dot is a reserve path thing. So we replace it with
|
|
186
|
+
# an underscore.
|
|
187
|
+
this_segment = this_segment.gsub( '.', '_' )
|
|
188
|
+
|
|
189
|
+
return this_segment
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
#
|
|
193
|
+
# Is this the root path?
|
|
194
|
+
def is_root_path?
|
|
195
|
+
return @route_segments.count == 0
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
#
|
|
199
|
+
# Create a list of path segments.
|
|
200
|
+
#
|
|
201
|
+
def detect_segments path
|
|
202
|
+
# For Assets, substitute the published name with fingerprint
|
|
203
|
+
# for the simple asset name (if it is found).
|
|
204
|
+
asset_info = WebSvr::AssetInfo.find_info_for( path )
|
|
205
|
+
unless asset_info.blank?
|
|
206
|
+
path = asset_info.pn
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
# Split the path into segments.
|
|
210
|
+
@route_segments = path.split SEGMENT_DIVIDER
|
|
211
|
+
|
|
212
|
+
# Remove the first segment if it is empty.
|
|
213
|
+
@route_segments.shift if @route_segments.first.blank?
|
|
214
|
+
|
|
215
|
+
@route_segments.each do |seg|
|
|
216
|
+
if seg.to_i.to_s == seg
|
|
217
|
+
@id = seg.to_i
|
|
218
|
+
@log.info "found id for route: #{@id}"
|
|
219
|
+
@route_segments.delete seg
|
|
220
|
+
@route_segments << ResourceRouter.segment_for_method( @method )
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
return @route_segments
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
end
|
|
228
|
+
end
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# Author:: Eric Crane (mailto:eric.crane@mac.com)
|
|
2
|
+
# Copyright:: Copyright (c) 2024 Eric Crane. All rights reserved.
|
|
3
|
+
#
|
|
4
|
+
# A helper class for to show routes for a running app.
|
|
5
|
+
#
|
|
6
|
+
|
|
7
|
+
module Routing
|
|
8
|
+
class ShowRoutes
|
|
9
|
+
|
|
10
|
+
SEGMENT_DIVIDER = '/'.freeze
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
# ---------------------------------------------------------------------
|
|
14
|
+
# Initialization
|
|
15
|
+
# ---------------------------------------------------------------------
|
|
16
|
+
|
|
17
|
+
#
|
|
18
|
+
# Set up the web server.
|
|
19
|
+
#
|
|
20
|
+
def initialize( engine )
|
|
21
|
+
@engine = engine
|
|
22
|
+
@log = @engine.log
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
# ---------------------------------------------------------------------
|
|
27
|
+
# Show Routes
|
|
28
|
+
# ---------------------------------------------------------------------
|
|
29
|
+
|
|
30
|
+
#
|
|
31
|
+
# Show all available routes.
|
|
32
|
+
#
|
|
33
|
+
def show page_container
|
|
34
|
+
@log.debug "showing routes"
|
|
35
|
+
|
|
36
|
+
@found_routes = []
|
|
37
|
+
@log.debug "building route table"
|
|
38
|
+
add_container_routes( page_container, SEGMENT_DIVIDER )
|
|
39
|
+
|
|
40
|
+
show_table
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
#
|
|
44
|
+
# Show the routes in the given container.
|
|
45
|
+
# This is a recursive function travese the object tree.
|
|
46
|
+
#
|
|
47
|
+
def add_container_routes can, route_path
|
|
48
|
+
can.children.each do |obj|
|
|
49
|
+
if obj.class == Gloo::Objs::Container
|
|
50
|
+
add_container_routes obj, "#{route_path}#{obj.name}#{SEGMENT_DIVIDER}"
|
|
51
|
+
elsif obj.class == Gloo::Objs::Page
|
|
52
|
+
route = "#{route_path}#{obj.name}"
|
|
53
|
+
@found_routes << [ obj.name, obj.pn, route, WebSvr::WebMethod::GET ]
|
|
54
|
+
|
|
55
|
+
# If the method is POST, add a route alias for the create.
|
|
56
|
+
if obj.name.eql? ResourceRouter::POST_ROUTE
|
|
57
|
+
@found_routes << [ '', '', route_path, WebSvr::WebMethod::POST ]
|
|
58
|
+
elsif obj.name.eql? ResourceRouter::UPDATE
|
|
59
|
+
@found_routes << [ '', '', route_path, WebSvr::WebMethod::PATCH ]
|
|
60
|
+
elsif obj.name.eql? ResourceRouter::DELETE
|
|
61
|
+
@found_routes << [ '', '', route_path, WebSvr::WebMethod::DELETE ]
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
# ---------------------------------------------------------------------
|
|
69
|
+
# Show Routes
|
|
70
|
+
# ---------------------------------------------------------------------
|
|
71
|
+
|
|
72
|
+
#
|
|
73
|
+
# Show the Routes title.
|
|
74
|
+
#
|
|
75
|
+
def show_table
|
|
76
|
+
puts Gloo::App::Platform::RETURN
|
|
77
|
+
title = "Routes in Running Web App"
|
|
78
|
+
@engine.platform.table.show headers, @found_routes, title
|
|
79
|
+
puts Gloo::App::Platform::RETURN
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
#
|
|
83
|
+
# Get the table headers.
|
|
84
|
+
#
|
|
85
|
+
def headers
|
|
86
|
+
return [ 'Obj Name', 'Obj Path', 'Route', 'Method' ]
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
end
|
|
90
|
+
end
|