lib/respond.js - git - Webernet Explorer _X
git 🏠 Home 👤 Sign up Self hosted git, retro shell
★ otgit, code hosting from the year 2000 ★
📄 octuna / lib / respond.js
85 lines · 2.4 KB · Raw
1const config = require('./config');
2 
3const STATIC_HEADERS = {
4 'X-Content-Type-Options': 'nosniff',
5 'X-Frame-Options': 'DENY',
6 'Referrer-Policy': 'no-referrer',
7 'Permissions-Policy': 'interest-cohort=()',
8 'Strict-Transport-Security': 'max-age=31536000; includeSubDomains'
9};
10 
11function securityHeaders() { return { ...STATIC_HEADERS }; }
12 
13function htmlHeaders() {
14 return {
15 'Content-Type': 'text/html; charset=utf-8',
16 'Content-Security-Policy': config.get('security.csp'),
17 ...STATIC_HEADERS
18 };
19}
20 
21function json(res, code, obj, extra) {
22 const body = JSON.stringify(obj);
23 res.writeHead(code, {
24 'Content-Type': 'application/json',
25 'Content-Length': Buffer.byteLength(body),
26 ...STATIC_HEADERS,
27 ...(extra || {})
28 });
29 res.end(body);
30}
31 
32function html(res, code, body, extra) {
33 res.writeHead(code, { ...htmlHeaders(), ...(extra || {}) });
34 res.end(body);
35}
36 
37function text(res, code, body, extra) {
38 res.writeHead(code, {
39 'Content-Type': 'text/plain; charset=utf-8',
40 ...STATIC_HEADERS,
41 ...(extra || {})
42 });
43 res.end(body);
44}
45 
46function redirect(res, location) {
47 res.writeHead(302, { Location: location, ...STATIC_HEADERS });
48 res.end();
49}
50 
51function notFound(res) { text(res, 404, 'Not found'); }
52function unauthorized(res) { json(res, 401, { error: 'Not authenticated' }); }
53function forbidden(res, msg) { json(res, 403, { error: msg || 'Forbidden' }); }
54function badRequest(res, msg) { json(res, 400, { error: msg || 'Bad request' }); }
55function tooMany(res, msg) { json(res, 429, { error: msg || 'Too many requests' }); }
56function serverError(res, msg) { json(res, 500, { error: msg || 'Server error' }); }
57 
58function readJson(req, cb) {
59 let buf = '';
60 req.on('data', chunk => {
61 buf += chunk;
62 if (buf.length > 100_000) { req.destroy(); cb(new Error('Request body too large')); }
63 });
64 req.on('end', () => {
65 try { cb(null, buf ? JSON.parse(buf) : {}); }
66 catch (e) { cb(new Error('Invalid JSON')); }
67 });
68 req.on('error', cb);
69}
70 
71function clientIp(req) {
72 if (config.get('security.trustProxy')) {
73 const xf = req.headers['x-forwarded-for'];
74 if (xf) return xf.split(',')[0].trim();
75 }
76 return req.socket.remoteAddress || 'unknown';
77}
78 
79module.exports = {
80 securityHeaders, htmlHeaders,
81 json, html, text, redirect,
82 notFound, unauthorized, forbidden, badRequest, tooMany, serverError,
83 readJson, clientIp
84};
85 
Done 🔒 Internet