import JSTCache from '@ndcode/jst_cache'
import Listener from './Listener.mjs'
+import Problem from './Problem.mjs'
import Resources from './Resources.mjs'
import Site from './Site.mjs'
import assert from 'assert'
response.end(data)
}
- die(response, pathname, message) {
- console.log(message)
- this.serve_internal(
- response,
- 404,
- 'text/html; charset=utf-8',
- Buffer.from(
- `<html>
- <head>
- <meta http-equiv="content-type" content="text/html;charset=utf-8">
- <title>404 Not Found</title>
- </head>
- <body style="font-family: sans-serif, serif, monospace; font-size: 16px;">
- <h2>404 Not Found</h2>
- <p>The document ${pathname} was not found.</p>
- </body>
-</html>
-`
- )
- )
- }
-
redirect(response, location, message) {
console.log(message)
response.statusCode = 301
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<title>301 Moved Permanently</title>
</head>
- <body style="font-family: sans-serif, serif, monospace; font-size: 16px;">
+ <body style="font-family: sans-serif, serif, monospace; font-size: 20px;">
<h2>301 Moved Permanently</h2>
- <p>The document has moved <a href="${location}">here</a>.</p>
+ The document has moved <a href="${location}">here</a>.
</body>
</html>
-`
+`,
+ 'utf-8'
)
)
}
async respond(request, response, protocol) {
+ let parsed_url = url.parse(
+ protocol + '//' + (request.headers.host || 'localhost') + request.url,
+ true
+ )
+ //console.log('parsed_url', parsed_url)
try {
- let parsed_url = url.parse(
- protocol + '//' + (request.headers.host || 'localhost') + request.url,
- true
- )
- //console.log('parsed_url', parsed_url)
-
if (
- !Object.prototype.hasOwnProperty.call(this.options.hosts, parsed_url.hostname)
- ) {
- this.die(
- response,
- parsed_url.pathname,
- 'nonexistent site: ' + parsed_url.hostname
+ !Object.prototype.hasOwnProperty.call(
+ this.options.hosts,
+ parsed_url.hostname
+ )
+ )
+ throw new Problem(
+ 'Not found',
+ `Site "${parsed_url.hostname}" not found.`,
+ 404
)
- return
- }
let host = this.options.hosts[parsed_url.hostname]
switch (host.type) {
assert(false)
}
}
- catch (err) {
- let message = (err.stack || err.message).toString()
- console.error(message)
+ catch (error) {
+ let problem = Problem.from(error)
+ console.log(`${parsed_url.host} ${problem.status} ${problem.title}`)
+ console.log(` ${problem.detail}`)
this.serve_internal(
response,
- 500,
+ problem.status,
'text/html; charset=utf-8',
- Buffer.from(`<html><body><pre>${message}</pre></body></html>`)
+ Buffer.from(
+ `<html>
+ <head>
+ <meta http-equiv="content-type" content="text/html; charset=utf-8">
+ <title>${problem.status} ${problem.title}</title>
+ </head>
+ <body style="font-family: sans-serif, serif, monospace; font-size: 20px;">
+ <h2>${problem.status} ${problem.title}</h2>
+ ${problem.detail.replaceAll('&', '&').replaceAll('<', '<').replaceAll('\n', '<br>')}
+ </body>
+</html>
+`,
+ 'utf-8'
+ )
)
}
}
import MinJSCache from '@ndcode/min_js_cache'
import MinHTMLCache from '@ndcode/min_html_cache'
import MinSVGCache from '@ndcode/min_svg_cache'
+import Problem from './Problem.mjs'
import Resources from './Resources.mjs'
import SassCSSCache from '@ndcode/sass_css_cache'
import TextCache from '@ndcode/text_cache'
this.serve_internal(env.response, status, env.mime_type, env.caching, data)
}
- die(env, message) {
- console.log(`${env.parsed_url.host} ${message}`)
- this.serve_internal(
- env.response,
- 404,
- this.options.mime_types['.html'],
- false,
- Buffer.from(
- `<html>
- <head>
- <meta http-equiv="content-type" content="text/html;charset=utf-8">
- <title>404 Not Found</title>
- </head>
- <body style="font-family: sans-serif, serif, monospace; font-size: 16px;">
- <h2>404 Not Found</h2>
- <p>The document ${env.parsed_url.pathname} was not found.</p>
- </body>
-</html>
-`
- )
- )
- }
-
redirect(env, pathname, message) {
console.log(
`${env.parsed_url.host} redirecting ${env.parsed_url.pathname} to ${pathname}`
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<title>301 Moved Permanently</title>
</head>
- <body style="font-family: sans-serif, serif, monospace; font-size: 16px;">
+ <body style="font-family: sans-serif, serif, monospace; font-size: 20px;">
<h2>301 Moved Permanently</h2>
- <p>The document has moved <a href="${location}">here</a>.</p>
+ The document has moved <a href="${location}">here</a>.
</body>
</html>
-`
+`,
+ 'utf-8'
)
)
}
}
async serve_file(env, pathname) {
- //console.log(`serve_file ${pathname}`)
- if (await this.serve_jst(env, pathname + '.jst'))
- return
- if (await this.serve_less_css(env, pathname + '.less'))
- return
- if (await this.serve_min_css(env, pathname + '.min'))
- return
- if (await this.serve_min_html(env, pathname + '.min'))
- return
- if (await this.serve_min_js(env, pathname + '.min'))
- return
- if (await this.serve_min_svg(env, pathname + '.min'))
- return
- if (await this.serve_sass_css(env, pathname + '.sass'))
- return
- if (await this.serve_sass_css(env, pathname + '.scss'))
- return
- if (await this.serve_fs(env, pathname))
- return
- this.die(env, `file not found ${env.parsed_url.pathname}`)
+ if (
+ !await this.serve_jst(env, pathname + '.jst') &&
+ !await this.serve_less_css(env, pathname + '.less') &&
+ !await this.serve_min_css(env, pathname + '.min') &&
+ !await this.serve_min_html(env, pathname + '.min') &&
+ !await this.serve_min_js(env, pathname + '.min') &&
+ !await this.serve_min_svg(env, pathname + '.min') &&
+ !await this.serve_sass_css(env, pathname + '.sass') &&
+ !await this.serve_sass_css(env, pathname + '.scss') &&
+ !await this.serve_fs(env, pathname)
+ )
+ throw new Problem(
+ 'Not found',
+ `File "${pathname}" not found.`,
+ 404
+ )
}
async serve_dir(env, pathname, components) {
try {
stats = await fsPromises.stat(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,
- components.length > 1 ?
- `not directory ${pathname}` :
- `unknown file type in ${env.parsed_url.pathname}`
+ catch (error) {
+ if (!(error instanceof Error) || error.code !== 'ENOENT')
+ throw error
+ throw new Problem(
+ 'Not found',
+ `Directory "${pathname}" not found.`,
+ 404
)
- return
}
+ if (!stats.isDirectory())
+ throw new Problem(
+ 'Not found',
+ `Path "${pathname}" not directory.`,
+ 404
+ )
return /*await*/ this.serve_path(env, pathname, components)
}
if (components[0].length === 0) {
if (components.length > 1)
- this.die(env, `empty directory name in ${env.parsed_url.pathname}`)
- else
- // directory with trailing slash
- this.redirect(env, env.parsed_url.pathname + 'index.html')
+ throw new Problem(
+ 'Not found',
+ `Path "${pathname}" followed by empty directory name.`,
+ 404
+ )
+ // directory with trailing slash
+ this.redirect(env, env.parsed_url.pathname + 'index.html')
return
}
if (
components[0].charAt(0) === '.' ||
components[0].charAt(0) === '_'
- ) {
- this.die(env, `bad component "${components[0]}" in ${env.parsed_url.pathname}`)
- return
- }
+ )
+ throw new Problem(
+ 'Not found',
+ `Path "${pathname}" followed by bad component "${components[0]}".`,
+ 404
+ )
let i = components[0].lastIndexOf('.')
if (i === -1)
extension.length !== 0 &&
Object.prototype.hasOwnProperty.call(this.options.mime_types, extension)
) {
- if (components.length > 1) {
- this.die(env, `non-directory extension "${extension}" in ${env.parsed_url.pathname}`)
- return
- }
+ if (components.length > 1)
+ throw new Problem(
+ 'Not found',
+ `Directory "${pathname}" has non-directory extension "${extension}".`,
+ 404
+ )
return /*await*/ this.serve_file(env, pathname)
}
return /*await*/ this.serve_dir(env, pathname, components.slice(1))
// build path, ensuring that remaining components are safe
/*let*/ pathname = `${this.options.certbot_webroot}/.well-known`
for (let i = 1; i < components.length; ++i) {
- if (components[i].charAt(0) == '.') {
- this.die(env, `bad component "${components[i]}" in ${env.parsed_url.pathname}`)
- return
- }
+ if (components[i].charAt(0) == '.')
+ throw new Problem(
+ 'Not found',
+ `Path "${pathname}" followed by bad component "${components[i]}".`,
+ 404
+ )
pathname = `${pathname}/${components[i]}`
}