better caching, private files
This commit is contained in:
parent
821034cbab
commit
b7e5939524
18 changed files with 100 additions and 58 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1,2 +1,4 @@
|
|||
node_modules
|
||||
server.log
|
||||
.env
|
||||
overlay
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<title>404</title>
|
||||
<meta charset="utf8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="/assets/style.css?{{time}}"></link>
|
||||
<link rel="stylesheet" href="/assets/style.css?v={{cache.style}}"></link>
|
||||
</head>
|
||||
<body>
|
||||
<h1>404</h1>
|
||||
|
@ -12,4 +12,3 @@
|
|||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
/assets/ resources for the site itself
|
||||
/media/ images, videos, music, and other cool stuff
|
||||
/media/ images, videos, music, and other cool stuff i found
|
||||
/public/ random things that i have made public
|
||||
/public/school/ some random notes from school, to test the markdown renderer
|
||||
/public/snek/ snek!
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
<title>index of {{dir}}</title>
|
||||
<meta charset="utf8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="/assets/style.css?{{time}}"></link>
|
||||
<link rel="stylesheet" href="/assets/directory.css?{{time}}"></link>
|
||||
<link rel="stylesheet" href="/assets/style.css?v={{cache.style}}"></link>
|
||||
<link rel="stylesheet" href="/assets/directory.css?v={{cache.dir}}"></link>
|
||||
</head>
|
||||
<body>
|
||||
<h1>index of {{dir}}</h1>
|
||||
|
|
|
@ -4,8 +4,9 @@
|
|||
<title>{{title}}</title>
|
||||
<meta charset="utf8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="/assets/style.css?{{time}}"></link>
|
||||
<link rel="stylesheet" href="/assets/code.css?{{time}}"></link>
|
||||
<link rel="stylesheet" href="/assets/style.css?v={{cache.style}}"></link>
|
||||
<link rel="stylesheet" href="/assets/code.css?v={{cache.code}}"></link>{{#essay}}
|
||||
<link rel="stylesheet" href="/assets/essay.css?v={{cache.essay}}"></link>{{/essay}}
|
||||
</head>
|
||||
<body>
|
||||
{{{body}}}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const mustache = require("mustache");
|
||||
const time = Date.now().toString(32).toString(36);
|
||||
const { version } = require("../modules/cache.js");
|
||||
const template = fs.readFileSync("assets/directory.html", "utf8");
|
||||
|
||||
const comments = fs.readFileSync(path.join(__dirname, "../assets/comments"), "utf8")
|
||||
|
@ -44,7 +44,11 @@ exports.render = (where, name) => {
|
|||
dir: name,
|
||||
files: sorted,
|
||||
comment: comments.get(name),
|
||||
time,
|
||||
cache: {
|
||||
style: version("/assets/style.css"),
|
||||
dir: version("/assets/directory.css"),
|
||||
upload: version("/assets/upload.js"),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ const fs = require("fs");
|
|||
const path = require("path");
|
||||
const mustache = require("mustache");
|
||||
const gemini = require("../util/gemini.js");
|
||||
const time = Date.now().toString(36);
|
||||
const { version } = require("../modules/cache.js");
|
||||
|
||||
const template = fs.readFileSync("assets/wrapper.html", "utf8");
|
||||
|
||||
|
@ -11,6 +11,10 @@ exports.hash = (where) => fs.statSync(where).mtime.valueOf();
|
|||
exports.render = (where) => mustache.render(template, {
|
||||
body: gemini(fs.readFileSync(where, "utf8")),
|
||||
title: path.basename(where),
|
||||
time,
|
||||
cache: {
|
||||
style: version("/assets/style.css"),
|
||||
code: version("/assets/code.css"),
|
||||
essay: version("/assets/essay.css"),
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const mustache = require("mustache");
|
||||
const { version } = require("../modules/cache.js");
|
||||
const md = require("../util/markdown.js");
|
||||
|
||||
const time = Date.now().toString(36);
|
||||
|
||||
const template = fs.readFileSync("assets/wrapper.html", "utf8").valueOf();
|
||||
|
||||
exports.hash = (where) => fs.statSync(where).mtime;
|
||||
|
@ -12,6 +11,11 @@ exports.hash = (where) => fs.statSync(where).mtime;
|
|||
exports.render = (where) => mustache.render(template, {
|
||||
title: path.basename(where),
|
||||
body: md(fs.readFileSync(where, "utf8")),
|
||||
time,
|
||||
essay: where.includes("essay"),
|
||||
cache: {
|
||||
style: version("/assets/style.css"),
|
||||
code: version("/assets/code.css"),
|
||||
essay: version("/assets/essay.css"),
|
||||
},
|
||||
});
|
||||
|
||||
|
|
6
index.js
6
index.js
|
@ -1,3 +1,5 @@
|
|||
require("dotenv").config();
|
||||
|
||||
const express = require("express");
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
@ -10,9 +12,7 @@ log.info("starting server");
|
|||
app.use(require("compression")());
|
||||
require("express-ws")(app);
|
||||
|
||||
app.get("*", (req, res, next) => {
|
||||
// console.log(req.headers);
|
||||
// log.debug(`request from ${req.headers['x-real-ip']}`);
|
||||
app.all("*", (req, res, next) => {
|
||||
log.debug(`${req.method} request for ${req.url}`);
|
||||
next();
|
||||
});
|
||||
|
|
36
modules/cache.js
Normal file
36
modules/cache.js
Normal file
|
@ -0,0 +1,36 @@
|
|||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const mtimes = new Map();
|
||||
|
||||
function version(file) {
|
||||
const str = (time) => time.valueOf().toString(36);
|
||||
try {
|
||||
const where = path.resolve(__dirname + "/../overlay/" + file);
|
||||
if(mtimes.has(file) && Date.now() - mtimes.get(file) < 5 * 1000) return str(mtimes.get(file));
|
||||
const mtime = fs.statSync(where).mtime;
|
||||
mtimes.set(file, mtime);
|
||||
return str(mtime);
|
||||
} catch {
|
||||
mtimes.set(file, 1e20);
|
||||
return (1e20).toString(36);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = (app, dir) => {
|
||||
app.get("/assets/*", (req, res, next) => {
|
||||
if(req.query.v) {
|
||||
res.set("Cache-Control", "public, max-age=" + 60 * 60 * 24);
|
||||
next();
|
||||
} else {
|
||||
res.redirect(req.path + "?v=" + version(req.path));
|
||||
}
|
||||
});
|
||||
|
||||
app.get("/cinny/*", (req, res, next) => {
|
||||
res.set("Cache-Control", "public, max-age=" + 60 * 60 * 24);
|
||||
next();
|
||||
});
|
||||
}
|
||||
|
||||
module.exports.version = version;
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
// TODO
|
||||
|
||||
const tls = require("tls");
|
||||
|
||||
function fetch() {
|
||||
|
||||
}
|
||||
|
||||
module.exports = (app) => {
|
||||
// app.get("/gemini/*", (req, res) => {
|
||||
//
|
||||
// });
|
||||
};
|
||||
|
|
@ -4,6 +4,7 @@ const types = require("../types.js");
|
|||
const getType = (name) => types.get(path.extname(name).slice(1));
|
||||
|
||||
module.exports = (app, dir, log) => {
|
||||
const redir = (to) => (req, res, next) => req.path === to ? next() : res.redirect(to);
|
||||
const file = (name) => {
|
||||
const data = fs.readFileSync(path.join(dir, "overlay", name));
|
||||
return (req, res) => res.writeHead(200, { "Content-Type": getType(name) }).end(data);
|
||||
|
@ -12,6 +13,6 @@ module.exports = (app, dir, log) => {
|
|||
app.get("/", file("index.html"));
|
||||
app.get("/stats", file("stats.html"));
|
||||
app.get("/unlist", (req, res) => res.redirect("/nope"));
|
||||
// app.get("/cinny", file("cinny/index.html"));
|
||||
app.get("/cinny", redir("/cinny/"), file("/cinny/index.html"));
|
||||
};
|
||||
|
||||
|
|
|
@ -1,22 +1,29 @@
|
|||
// authentication thing, maybe would be useful later?
|
||||
const sleep = (ms) => new Promise((res) => setTimeout(res, ms));
|
||||
|
||||
module.exports = (app, dir, log) => {
|
||||
const authorize = (req, res, next) => {
|
||||
const authorize = async (req, res, next) => {
|
||||
if(req.headers["x-forwarded-proto"] !== "https") {
|
||||
res.writeHead(400).end("use https");
|
||||
}
|
||||
|
||||
const auth = req.headers.authorization;
|
||||
try {
|
||||
const [user, pass] = atob(auth.slice(6)).split(":");
|
||||
if(user !== "username") throw "no";
|
||||
if(pass !== "password") throw "no";
|
||||
if(user !== process.env.SECURE_USER) throw "no";
|
||||
if(pass !== process.env.SECURE_PASS) throw "no";
|
||||
next();
|
||||
} catch (err) {
|
||||
if(err === "no") log.warn("attemped login on /secrets");
|
||||
if(err === "no") {
|
||||
log.warn("attemped login on " + req.path);
|
||||
await sleep(300);
|
||||
}
|
||||
res.writeHead(401, {
|
||||
"WWW-Authenticate": 'Basic realm="secrets..."',
|
||||
}).end();
|
||||
}
|
||||
};
|
||||
|
||||
// app.get("/secrets/*", authorize);
|
||||
// app.get("/secrets/", authorize);
|
||||
app.get("/private/*", authorize);
|
||||
app.get("/private/", authorize);
|
||||
}
|
||||
|
||||
|
|
1
overlay
1
overlay
|
@ -1 +0,0 @@
|
|||
Subproject commit fd5a366348ddaeffdad9230912981405d358b2e9
|
|
@ -10,10 +10,11 @@
|
|||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"compression": "^1.7.4",
|
||||
"dotenv": "^16.0.0",
|
||||
"express": "^4.17.3",
|
||||
"express-ws": "^5.0.2",
|
||||
"highlight.js": "^11.5.0",
|
||||
"lru-cache": "^7.5.1",
|
||||
"lru-cache": "^7.7.1",
|
||||
"markdown-it": "^12.3.2",
|
||||
"markdown-it-image-figures": "^2.0.0",
|
||||
"mustache": "^4.2.0",
|
||||
|
|
|
@ -2,10 +2,11 @@ lockfileVersion: 5.3
|
|||
|
||||
specifiers:
|
||||
compression: ^1.7.4
|
||||
dotenv: ^16.0.0
|
||||
express: ^4.17.3
|
||||
express-ws: ^5.0.2
|
||||
highlight.js: ^11.5.0
|
||||
lru-cache: ^7.5.1
|
||||
lru-cache: ^7.7.1
|
||||
markdown-it: ^12.3.2
|
||||
markdown-it-image-figures: ^2.0.0
|
||||
mustache: ^4.2.0
|
||||
|
@ -13,10 +14,11 @@ specifiers:
|
|||
|
||||
dependencies:
|
||||
compression: 1.7.4
|
||||
dotenv: 16.0.0
|
||||
express: 4.17.3
|
||||
express-ws: 5.0.2_express@4.17.3
|
||||
highlight.js: 11.5.0
|
||||
lru-cache: 7.5.1
|
||||
lru-cache: 7.7.1
|
||||
markdown-it: 12.3.2
|
||||
markdown-it-image-figures: 2.0.0_markdown-it@12.3.2
|
||||
mustache: 4.2.0
|
||||
|
@ -122,6 +124,11 @@ packages:
|
|||
resolution: {integrity: sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=}
|
||||
dev: false
|
||||
|
||||
/dotenv/16.0.0:
|
||||
resolution: {integrity: sha512-qD9WU0MPM4SWLPJy/r2Be+2WgQj8plChsyrCNQzW/0WjvcJQiKQJ9mH3ZgB3fxbUUxgc/11ZJ0Fi5KiimWGz2Q==}
|
||||
engines: {node: '>=12'}
|
||||
dev: false
|
||||
|
||||
/ee-first/1.1.1:
|
||||
resolution: {integrity: sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=}
|
||||
dev: false
|
||||
|
@ -268,8 +275,8 @@ packages:
|
|||
uc.micro: 1.0.6
|
||||
dev: false
|
||||
|
||||
/lru-cache/7.5.1:
|
||||
resolution: {integrity: sha512-q1TS8IqKvcg3aScamKCHpepSrHF537Ww7nHahBOxhDu9D2YoBXAsj/7uFdZFj1xJr9LmyeJ62AdyofCHafUbIA==}
|
||||
/lru-cache/7.7.1:
|
||||
resolution: {integrity: sha512-cRffBiTW8s73eH4aTXqBcTLU0xQnwGV3/imttRHGWCrbergmnK4D6JXQd8qin5z43HnDwRI+o7mVW0LEB+tpAw==}
|
||||
engines: {node: '>=12'}
|
||||
dev: false
|
||||
|
||||
|
|
14
static.js
14
static.js
|
@ -2,6 +2,7 @@ const fs = require("fs");
|
|||
const path = require("path");
|
||||
const types = require("./types.js");
|
||||
const log = require("./log.js");
|
||||
const { version } = require("./modules/cache.js");
|
||||
const mustache = require("mustache");
|
||||
const LRU = require("lru-cache");
|
||||
|
||||
|
@ -16,21 +17,15 @@ const handlers = {
|
|||
file: require("./handlers/file.js"),
|
||||
};
|
||||
|
||||
const cacheable = [
|
||||
"/assets/style.css",
|
||||
"/assets/directory.css",
|
||||
"/assets/code.css",
|
||||
];
|
||||
|
||||
function generate(file, raw) {
|
||||
const where = path.resolve(__dirname + "/overlay/" + file);
|
||||
|
||||
if(!fs.existsSync(where)) {
|
||||
return send("text/html", mustache.render(template404, { file, time }), 404);
|
||||
return send("text/html", mustache.render(template404, { file, time, cache: { style: version("/assets/style.css") } }), 404);
|
||||
}
|
||||
|
||||
const stat = fs.statSync(where);
|
||||
|
||||
|
||||
if(stat.isDirectory()) {
|
||||
if(!file.endsWith("/")) return (req, res) => res.redirect(file + "/");
|
||||
return send("text/html", run(handlers.directory));
|
||||
|
@ -53,9 +48,6 @@ function generate(file, raw) {
|
|||
|
||||
function send(type, content, status = 200) {
|
||||
const headers = { "Content-Type": type || "text/plain" };
|
||||
if(cacheable.includes(file)) {
|
||||
headers["Cache-Control"] = "public, max-age=" + 60 * 60 * 24;
|
||||
}
|
||||
return (req, res) => res.writeHead(status, headers).end(content);
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ module.exports = (data) => {
|
|||
html += clean(line) + "\n";
|
||||
} else if(header) {
|
||||
const n = header[1].length;
|
||||
html += `<h${n}>${clean(line)}</h${n}>\n`;
|
||||
html += `<h${n}>${clean(line.replace(/^#+ */, ""))}</h${n}>\n`;
|
||||
} else if(line.startsWith(">")) {
|
||||
html += `<blockquote>${clean(line.replace(/^> */, ""))}</blockquote>\n`;
|
||||
} else if(link) {
|
||||
|
|
Loading…
Reference in a new issue