1 let assert = require('assert')
2 let config = require('./config')
3 let cookie = require('cookie')
5 let js_template = require('js_template')
6 let resources = require('./resources')
7 let server = require('./server')
8 let util = require('util')
9 let url = require('url')
11 let fs_readFile = util.promisify(fs.readFile)
12 let fs_stat = util.promisify(fs.stat)
14 let app = async (site, site_root, req, res, protocol) => {
15 // parse the pathname portion of url
16 // this is actually cheating since it's not a complete url
17 let parsed_url = url.parse(req.url, true)
18 let path = parsed_url.pathname.split('/')
20 // path must begin with /
21 if (path.length === 0 || path[0].length) {
26 // path elements must be findable in the file system (thus can't be empty)
28 let dir_name_is_pub = false
29 for (let i = 1; i < path.length - 1; ++i) {
30 dir_name += '/' + path[i]
31 if (path[i].length === 0 || path[i].charAt(0) === '.') {
32 console.log(site, 'bad path component', dir_name)
38 stats = await fs_stat(site_root + dir_name)
41 if (err.code !== 'ENOENT')
43 if (!dir_name_is_pub) {
44 let temp = dir_name + '.pub'
46 stats = await fs_stat(site_root + temp)
48 dir_name_is_pub = true
51 if (err2.code !== 'ENOENT')
53 console.log(site, 'directory not found', dir_name)
58 if (!stats.isDirectory()) {
59 console.log(site, 'not directory', dir_name)
66 file_name = path[path.length - 1]
67 if (file_name === '') {
68 path[path.length - 1] = 'index.html'
70 console.log(site, 'server.redirecting', parsed_url.pathname, 'to', path)
71 server.redirect(res, path + (parsed_url.search || ''))
74 let page = path.join('/')
76 let temp = file_name.lastIndexOf('.')
77 let file_type = temp === -1 ? '' : file_name.substring(temp + 1)
79 Object.prototype.hasOwnProperty.call(config.mime_types, file_type) ?
80 config.mime_types[file_type] :
81 config.mime_type_default
83 if (dir_name_is_pub) {
84 temp = site_root + dir_name + '/' + file_name
86 let data = await fs_readFile(temp)
95 server.serve(res, 200, mime_type, data)
99 if (err.code !== 'ENOENT')
104 // at this point dir_name is guaranteed to be a prefix of page
105 // (has no .pub component), though constructed in a roundabout way
108 let data = await fs_readFile(site_root + temp)
117 server.serve(res, 200, mime_type, data)
121 if (err.code !== 'ENOENT')
130 await (await js_template(site_root, site_root, temp))(
132 cookies: cookie.parse(req.headers.cookie || ''),
136 query: parsed_url.query,
138 resources: resources,
139 set_cookie: (key, value, expires, path) => {
157 let data = Buffer.from(_out.join(''))
166 server.serve(res, 200, mime_type, data)
170 if (err.code !== 'ENOENT') // should check error type
176 temp = page + '.less'
178 let data = await resources.get_less(
191 server.serve(res, 200, mime_type, data)
195 if (err.code !== 'ENOENT') // note: err.code might be undefined
202 let favicons = await resources.get_zip(site_root + '/favicons.zip')
203 if (Object.prototype.hasOwnProperty.call(favicons, page)) {
204 let data = favicons[page]
213 server.serve(res, 200, mime_type, data)
217 console.log(site, 'file not found', page)