http-up
Version:
Simple share folder via http with upload
323 lines (258 loc) • 10.2 kB
JavaScript
import os from 'os';
import fs from 'fs';
import path from 'node:path';
import chalk from 'chalk';
import * as urlencode from 'urlencode';
import express from 'express';
import compression from 'compression';
import { engine } from 'express-handlebars';
//import basicAuth from 'express-basic-auth';
import { basicAuth3 } from '../lib/express-basic-auth3.js';
import config from '../lib/config.js';
import * as model from '../model/index.js';
import * as api from '../lib/api/index.js';
import * as thumb from '../lib/thumb.js';
import * as edit from '../lib/edit.js';
import * as openssl from '../lib/openssl.js';
import * as search from '../lib/search.js';
import * as player from '../lib/player.js';
import * as util from '../lib/util.js';
const makeServer = async (argv) => {
// -----------------------------------------------------------------------------------------------------------------------
// MAKE FOLDERS
fs.stat(config.httpup_home, {}, (err, stats) => {
if (err && err.code == 'ENOENT') {
fs.mkdir(config.httpup_home, { recursive: false }, (err) => {});
}
});
fs.stat(config.httpup_thumb, {}, (err, stats) => {
if (err && err.code == 'ENOENT') {
fs.mkdir(config.httpup_thumb, { recursive: false }, (err) => {});
}
});
fs.stat(config.httpup_db, {}, (err, stats) => {
if (err && err.code == 'ENOENT') {
fs.mkdir(config.httpup_db, { recursive: false }, (err) => {});
}
});
fs.stat(config.httpup_temp, {}, (err, stats) => {
if (err && err.code == 'ENOENT') {
fs.mkdir(config.httpup_temp, { recursive: false }, (err) => {});
} else {
fs.rm(config.httpup_temp, { recursive: true, force: false }, (err) => {
fs.mkdir(config.httpup_temp, { recursive: false }, (err) => {});
});
}
});
fs.stat(config.httpup_parts, {}, (err, stats) => {
if (err && err.code == 'ENOENT') {
fs.mkdir(config.httpup_parts, { recursive: false }, (err) => {});
} else {
fs.rm(config.httpup_parts, { recursive: true, force: false }, (err) => {
fs.mkdir(config.httpup_parts, { recursive: false }, (err) => {});
});
}
});
// -----------------------------------------------------------------------------------------------------------------------
// DATABASE
//let db;
if (argv.usedb) {
//let db = model.connect();
//model.init_db(db);
model.init_db();
}
// -----------------------------------------------------------------------------------------------------------------------
// EXPRESS
const app = express();
app.disable('x-powered-by');
app.engine('.hbs', engine({ extname: '.hbs' }));
app.set('view engine', '.hbs');
app.set('views', path.join(config.__rootdir, 'view'));
app.enable('view cache'); // enable cache template
app.use(compression());
app.use((req, res, next) => {
res.locals.argv = argv;
next();
});
// -----------------------------------------------------------------------------------------------------------------------
// SHOW SETUP INFO
console.log();
if (argv.basic) {
console.log('--basic basic auth enable');
}
if (argv['upload-disable']) {
console.log('--upload-disable flag enable');
}
if (argv['folder-make-disable']) {
console.log('--folder-make-disable flag enable');
}
if (argv['share-only']) {
console.log('--share-only flag enable');
}
if (argv.tls) {
console.log('--tls flag enable');
}
if (argv['tls-debug']) {
console.log('--tls-debug flag enable');
}
if (argv['extend-mode']) {
console.log('--extend-mode flag enable');
}
if (argv.crypt) {
console.log('--crypt flag enable');
}
if (argv.silence) {
console.log('--silence flag enable');
}
if (argv.usedb) {
console.log('--usedb flag enable');
}
console.log();
// -----------------------------------------------------------------------------------------------------------------------
// BASIC AUTH
if (argv.login && argv.password) {
console.log(chalk.yellow('Set basic authorization:'));
console.log(' ', argv.login, ' ', argv.password);
console.log('');
app.use(
basicAuth3({
users: { [argv.login]: argv.password },
challenge: true,
unauthorizedResponse: (req, res) => {
if (!req.auth) {
let req_path = urlencode.decode(req.path);
req_path = util.http_path_clear(req_path);
//console.log('401', req_path);
model.event_log.write(res, req, 401, 'basicAuth', '401 Unauthorized ' + chalk.yellow(req_path));
return util.error_page_content('401', '401 Unauthorized');
}
},
}),
);
}
if (argv.basic) {
console.log(chalk.yellow('Set basic authorization:'));
let userz = {};
let cnt = 0;
while (cnt < 10) {
let login = 'login' + util.random_string(2);
let passw = util.random_string(16);
userz[login] = passw;
console.log(' ', login, ' ', passw);
cnt += 1;
}
console.log('');
app.use(
basicAuth3({
users: userz,
challenge: true,
unauthorizedResponse: (req, res) => {
if (!req.auth) {
let req_path = urlencode.decode(req.path);
req_path = util.http_path_clear(req_path);
//console.log('401', req_path);
model.event_log.write(res, req, 401, 'basicAuth', '401 Unauthorized ' + chalk.yellow(req_path));
return util.error_page_content('401', '401 Unauthorized');
}
},
}),
);
}
// -----------------------------------------------------------------------------------------------------------------------
// API
if (!argv['upload-disable']) {
api.post_file(app, argv);
api.post_file_part(app, argv);
}
if (!argv['folder-make-disable']) {
api.post_folder(app, argv);
api.post_file_touch(app, argv);
}
if (argv['extend-mode']) {
api.post_delete(app, argv);
api.post_move(app, argv);
api.post_copy(app, argv);
api.post_rename(app, argv);
api.post_zip(app, argv);
thumb.api_thumb(app, argv);
edit.api_edit(app, argv);
search.search_result(app, argv);
}
player.player_page(app, argv);
api.get_all(app, argv);
// -----------------------------------------------------------------------------------------------------------------------
// 400 Bad Request
app.all('*splat', (req, res, next) => {
let req_path = urlencode.decode(req.path);
model.event_log.write(res, req, 400, 'bad_request', '400 Bad Request ' + req.method + ' ' + chalk.yellow(req_path));
res.status(400).json({
code: 400,
msg: 'Bad Request',
});
});
// -----------------------------------------------------------------------------------------------------------------------
// LISTEN
if (argv.tls) {
let https;
try {
https = await import('node:https');
} catch (err) {
console.error('https support is disabled!');
return;
}
openssl.openssl_make_keys(argv);
console.log('crt:', path.join(config.httpup_home, '/tls/server.crt'));
console.log('key:', path.join(config.httpup_home, '/tls/server.key'));
console.log('');
const serverOptions = {
cert: fs.readFileSync(path.join(config.httpup_home, '/tls/server.crt')),
key: fs.readFileSync(path.join(config.httpup_home, '/tls/server.key')),
maxVersion: 'TLSv1.3',
minVersion: 'TLSv1.2',
};
//console.log('https=', https);
const server = https.Server(serverOptions, app);
server.listen(argv.port, '0.0.0.0', (err) => {
console.log('Server TLS start:', chalk.green(argv.port));
if (err) {
console.log('HTTPS app.listen err=', err);
return;
}
let ifaces = os.networkInterfaces();
Object.keys(ifaces).forEach((k) => {
ifaces[k].forEach((el) => {
if (el.family && el.family == 'IPv4') {
console.log(' https://' + el.address + chalk.green(':' + argv.port));
}
});
});
console.log('');
console.log('Folder serve:', chalk.yellow(argv.fold));
console.log('');
console.log('[' + chalk.yellow('Control + C') + '] for server stop');
console.log('');
});
} else {
app.listen(argv.port, '0.0.0.0', (err) => {
console.log('Server start:', argv.port);
if (err) {
console.log('app.listen err=', err);
return;
}
let ifaces = os.networkInterfaces();
Object.keys(ifaces).forEach((k) => {
ifaces[k].forEach((el) => {
if (el.family && el.family == 'IPv4') {
console.log(' http://' + el.address + chalk.green(':' + argv.port));
}
});
});
console.log('');
console.log('Folder serve:', chalk.yellow(argv.fold));
console.log('');
console.log('[' + chalk.yellow('Control + C') + '] for server stop');
console.log('');
});
}
};
export { makeServer };