-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathfrontend-core.lua
More file actions
242 lines (210 loc) · 6.27 KB
/
frontend-core.lua
File metadata and controls
242 lines (210 loc) · 6.27 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
#!/usr/bin/env tarantool
local json = require('json')
local core_bundle = require('frontend-core.bundle')
local index_body = nil
local modules = {
-- [1] = namespace
-- [namespace] = filemap
}
local variables = {}
local prefix = ''
local function index_handler(_)
if index_body == nil then
local entries = {}
for _, namespace in ipairs(modules) do
local mod = modules[namespace]
local data
if type(mod.__data) == 'function' then
data = mod.__data()
else
data = mod
end
for filename, file in pairs(data) do
if file.is_entry then
table.insert(entries,
string.format(
'<script src="%s/static/%s/%s"></script>',
prefix, namespace, filename
)
)
end
end
end
index_body =
'<!doctype html>' ..
'<html>' ..
'<head>' ..
'<title>Tarantool Cartridge</title>'..
'<script>'..
('window.__tarantool_admin_prefix = %q;'):format(prefix)..
('window.__tarantool_variables = %s;'):format(json.encode(variables))..
'</script>'..
'</head>' ..
'<body>' ..
'<div id="root"></div>' ..
table.concat(entries) ..
'<script>window.tarantool_enterprise_core.install()</script>'..
'</body>' ..
'</html>'
end
return {
status = 200,
headers = {['content-type'] = 'text/html; charset=utf8'},
body = index_body
}
end
local function static_handler(req)
local mod = modules[req:stash('namespace')]
if mod == nil then
return { status = 404 }
end
local data
if type(mod.__data) == 'function' then
data = mod.__data()
else
data = mod
end
local file = data[req:stash('filename')]
if file == nil then
return { status = 404 }
end
return {
status = 200,
body = file.body,
headers = {
['content-type'] = file.mime,
['cache-control'] = 'max-age=86400',
},
}
end
local function add(namespace, filemap, replace)
if type(namespace) ~= 'string' then
error('Bad argument #1 to add' ..
' (string expected, got ' .. type(namespace) .. ')', 2)
end
if type(filemap) ~= 'table' then
error('Bad argument #2 to add' ..
' (table expected, got ' .. type(filemap) .. ')', 2)
end
if replace ~= nil and type(replace) ~= 'boolean' then
error('Bad argument #3 to add' ..
' (?boolean expected, got ' .. type(replace) .. ')', 2)
end
if modules[namespace] ~= nil and replace ~= true then
return nil, string.format('Front module %q already added', namespace)
elseif modules[namespace] == nil then
table.insert(modules, namespace)
end
modules[namespace] = filemap
-- invalidate cached index_body
index_body = nil
return true
end
local function remove(namespace)
if type(namespace) ~= 'string' then
error('Bad argument #1 to remove' ..
' (string expected, got ' .. type(namespace) .. ')', 2)
end
if modules[namespace] == nil then
return nil, string.format('Front module %q not exists', namespace)
end
modules[namespace] = nil
for i, mod_name in ipairs(modules) do
if mod_name == namespace then
table.remove(modules, i)
break
end
end
-- invalidate cached index_body
index_body = nil
return true
end
local function set_variable(name, value)
if type(name) ~= 'string' then
error('Bad argument #1 to set_variable' ..
' (string expected, got ' .. type(name) .. ')', 2)
end
variables[name] = value
-- invalidate cached index_body
index_body = nil
return true
end
local function redirect(cx)
return cx:redirect_to(prefix .. '/admin')
end
local function init(httpd, options)
if type(httpd) ~= 'table' then
local err = string.format(
"bad argument #1 to frontend-core.init" ..
" (table expected, got %s)", type(httpd)
)
error(err, 2)
end
if options == nil then
options = {}
elseif type(options) ~= 'table' then
local err = string.format(
"bad argument #2 to frontend-core.init" ..
" (?table expected, got %s)", type(options)
)
error(err, 2)
end
local enforce_root_redirect
if options.enforce_root_redirect == nil then
enforce_root_redirect = true
elseif type(options.enforce_root_redirect) ~= 'boolean' then
local err = string.format(
"bad argument options.enforce_root_redirect" ..
" to frontend-core.init (?boolean expected, got %s)",
type(options.enforce_root_redirect)
)
error(err, 2)
else
enforce_root_redirect = options.enforce_root_redirect
end
if options.prefix == nil then
prefix = ''
elseif type(options.prefix) ~= 'string' then
local err = string.format(
"bad argument options.prefix" ..
" to frontend-core.init (?string expected, got %s)",
type(options.prefix)
)
error(err, 2)
else
prefix = options.prefix
end
httpd:route({
path = prefix .. '/static/:namespace/*filename',
method = 'GET',
}, static_handler)
httpd:route({
path = prefix .. '/admin',
method = 'GET',
}, index_handler)
httpd:route({
path = prefix .. '/admin/*any',
method = 'GET',
}, index_handler)
if enforce_root_redirect then
httpd:route({
path = '/',
method = 'GET',
}, redirect)
if prefix ~= '' then
httpd:route({
path = prefix,
method = 'GET',
}, redirect)
end
end
index_body = nil
add('core', core_bundle)
return true
end
return {
init = init,
add = add,
remove = remove,
set_variable = set_variable
}