}
SiteRoot.prototype.serve_less = async function(env, pathname) {
- if (env.pathname.slice(env.pathname_pos) !== '.css')
+ if (pathname.slice(-9) !== '.css.less')
return false
let data
return true
}
-SiteRoot.prototype.serve_zip = async function(env, pathname) {
+SiteRoot.prototype.serve_zip = async function(env, zipname, pathname) {
let zip
try {
- zip = await this.server.get_zip(pathname)
+ zip = await this.server.get_zip(zipname)
}
catch (err) {
if (!(err instanceof Error) || err.code !== 'ENOENT')
throw err
return false
}
- if (!Object.prototype.hasOwnProperty.call(zip, env.pathname))
+ if (!Object.prototype.hasOwnProperty.call(zip, pathname))
return false
- this.serve(env, 200, zip[env.pathname], 'zip')
+ this.serve(env, 200, zip[pathname], 'zip')
return true
}
-SiteRoot.prototype.respond = async function(env) {
- while (true) {
- if (env.pathname_pos >= env.pathname.length) {
- // directory without trailing slash
- this.redirect(env, env.pathname + '/index.html')
- return
- }
-
- assert(env.pathname.charAt(env.pathname_pos) === '/')
- let i = env.pathname_pos + 1
- let j = env.pathname.indexOf('/', i)
- if (j === -1)
- j = env.pathname.length
- let filename = env.pathname.slice(i, j)
-
- if (filename.length === 0) {
- if (j >= env.pathname.length)
- // directory with trailing slash
- this.redirect(env, env.pathname + 'index.html')
- else
- this.die(env, `empty directory name in ${env.pathname}`)
- return
- }
-
- if (
- filename.charAt(0) === '.' ||
- filename.charAt(0) === '_'
- ) {
- this.die(env, `bad component "${filename}" in ${env.pathname}`)
- return
- }
-
- let k = filename.lastIndexOf('.')
- if (k === -1)
- k = filename.length
- let filetype = filename.slice(k)
-
- if (
- filetype.length !== 0 &&
- Object.prototype.hasOwnProperty.call(this.server.mime_types, filetype)
- ) {
- if (j < env.pathname.length) {
- this.die(env, `non-directory filetype "${filetype}" in ${env.pathname}`)
- return
- }
- env.pathname_pos = i + k // advance to "." at start of filetype
- break
- }
-
- env.pathname_pos = j
- let pathname = env.pathname.slice(0, env.pathname_pos)
- if (await this.serve_jst(env, this.root + pathname + '.dir.jst'))
- return
-
- let stats
- try {
- stats = await fs_stat(this.root + pathname)
- }
- catch (err) {
- if (!(err instanceof Error) || err.code !== 'ENOENT')
- throw err
- this.die(env, `directory not found ${pathname}`)
- return
- }
- if (!stats.isDirectory()) {
- this.die(
- env,
- j < env.pathname.length ?
- `not directory ${pathname}` :
- `unknown filetype "${filetype}" in ${pathname}`
- )
- return
- }
- }
-
+SiteRoot.prototype.serve_file = async function(env, pathname) {
+ //console.log(`serve_file ${pathname}`)
if (
- !await this.serve_jst(env, this.root + env.pathname + '.jst') &&
- !await this.serve_less(env, this.root + env.pathname + '.less') &&
- !await this.serve_fs(env, this.root + env.pathname) &&
- !await this.serve_zip(env, this.root + '/_favicon/favicons.zip')
+ !await this.serve_jst(env, pathname + '.jst') &&
+ !await this.serve_less(env, pathname + '.less') &&
+ !await this.serve_fs(env, pathname)
) {
this.die(env, `file not found ${env.pathname}`)
}
}
+SiteRoot.prototype.serve_dir = async function(env, dirname, pathname) {
+ //console.log(`serve_dir ${dirname} ${pathname}`)
+ if (pathname.length == 0) {
+ // directory without trailing slash
+ this.redirect(env, env.pathname + '/index.html')
+ return
+ }
+
+ assert(pathname.charAt(0) === '/')
+ let i = pathname.indexOf('/', 1)
+ if (i === -1)
+ i = pathname.length
+ let component = pathname.slice(0, i)
+
+ if (component.length === 1) {
+ if (i < pathname.length)
+ this.die(env, `empty directory name in ${env.pathname}`)
+ else
+ // directory with trailing slash
+ this.redirect(env, env.pathname + 'index.html')
+ return
+ }
+
+ if (
+ component.charAt(1) === '.' ||
+ component.charAt(1) === '_'
+ ) {
+ this.die(env, `bad component "${component}" in ${env.pathname}`)
+ return
+ }
+
+ let j = component.lastIndexOf('.')
+ if (j === -1)
+ j = component.length
+ let extension = component.slice(j)
+
+ if (
+ extension.length !== 0 &&
+ Object.prototype.hasOwnProperty.call(this.server.mime_types, extension)
+ ) {
+ if (i < pathname.length)
+ this.die(env, `non-directory extension "${extension}" in ${env.pathname}`)
+ else
+ this.serve_file(env, dirname + pathname)
+ return
+ }
+
+ dirname += component
+ if (await this.serve_jst(env, dirname + '.dir.jst'))
+ return
+
+ let stats
+ try {
+ stats = await fs_stat(dirname)
+ }
+ catch (err) {
+ if (!(err instanceof Error) || err.code !== 'ENOENT')
+ throw err
+ this.die(env, `directory not found ${dirname}`)
+ return
+ }
+ if (!stats.isDirectory()) {
+ this.die(
+ env,
+ i < pathname.length ?
+ `not directory ${dirname}` :
+ `unknown extension "${extension}" in ${env.pathname}`
+ )
+ return
+ }
+ this.serve_dir(env, dirname, pathname.slice(i))
+}
+
+SiteRoot.prototype.respond = async function(env) {
+ if (
+ !await this.serve_zip(
+ env,
+ this.root + '/_favicon/favicons.zip',
+ env.pathname
+ )
+ )
+ this.serve_dir(env, this.root, env.pathname)
+}
+
module.exports = SiteRoot