better caching, private files

This commit is contained in:
tezlm 2022-03-17 20:11:30 -07:00
parent 821034cbab
commit b7e5939524
18 changed files with 100 additions and 58 deletions

2
.gitignore vendored
View file

@ -1,2 +1,4 @@
node_modules
server.log
.env
overlay

View file

@ -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>

View file

@ -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!

View file

@ -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>

View file

@ -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}}}

View file

@ -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"),
},
});
}

View file

@ -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"),
},
});

View file

@ -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"),
},
});

View file

@ -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
View 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;

View file

@ -1,14 +0,0 @@
// TODO
const tls = require("tls");
function fetch() {
}
module.exports = (app) => {
// app.get("/gemini/*", (req, res) => {
//
// });
};

View file

@ -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"));
};

View file

@ -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 +0,0 @@
Subproject commit fd5a366348ddaeffdad9230912981405d358b2e9

View file

@ -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",

View file

@ -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

View file

@ -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);
}

View file

@ -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) {