Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## `1.2.0` June 3, 2018

### Add

- Multi-process log system.

## `1.1.3` May 20, 2018

### Fix
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ ServerHub can do a lot of things now. No matter you want to start a static websi

## Latest Updates

`v1.1.0` supports auto-redirect HTTP traffic to HTTPS. Asynchronous plugins are supported since `v1.0.8`. TLS supported since `v1.0.6`, you can use your self-signed or verified certificate to hold an HTTPS connection for your websites. Module style of ServerHub controllers now supported (since `v1.0.4`). You can import your own libraries in your controllers now. Legacy ways of scripting controllers will also be supported. But a little workaround should be taken into consideration (deprecated usage).
`v1.2.0` supports **runtime** and **error** log service. They are available through `global` object. `v1.1.0` supports auto-redirect HTTP traffic to HTTPS. Asynchronous plugins are supported since `v1.0.8`. TLS supported since `v1.0.6`, you can use your self-signed or verified certificate to hold an HTTPS connection for your websites. Module style of ServerHub controllers now supported (since `v1.0.4`). You can import your own libraries in your controllers now. Legacy ways of scripting controllers will also be supported. But a little workaround should be taken into consideration (deprecated usage).

Detailed update information could be found on [CHANGELOG.md](CHANGELOG.md) (English only).

Expand Down
2 changes: 1 addition & 1 deletion dist/lib/core/core.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ export declare function RegisterController(controllerJs: string): void;
export declare function RegisterControllerM(controllerJs: string): void;
export declare function UpdateGlobalVariable(variable: string, value: Object): boolean;
export declare function SetGlobalVariable(variable: string, value: Object): void;
export declare function RoutePath(path: string, request: IncomingMessage, response: ServerResponse): void;
export declare function RoutePath(path: string, request: IncomingMessage, res: ServerResponse): void;
export declare function RegisterRouter(route: Route): void;
22 changes: 18 additions & 4 deletions dist/lib/core/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ const content_type_1 = require("./content-type");
const rcs_1 = require("./cache/rcs");
const index_1 = require("./helper/index");
const plugin_1 = require("./plugin");
const server_1 = require("./server");
const log_1 = require("./log");
const node_version = process.version;
global['EnvironmentVariables'] = global['EnvironmentVariables'] ? global['EnvironmentVariables'] : {
ServerBaseDir: __dirname,
Expand All @@ -25,7 +27,15 @@ global['EnvironmentVariables'] = global['EnvironmentVariables'] ? global['Enviro
Verbose: true,
TLSOptions: void 0,
RedirectToTLS: true,
Hostname: 'localhost'
Hostname: 'localhost',
LogConfig: {
Dir: 'log/',
MaxSize: 65536,
Access: true,
Error: true,
Runtime: true,
Filename: 'serverhub'
}
};
const core_env = {
platform: process.platform,
Expand All @@ -51,9 +61,13 @@ function SetGlobalVariable(variable, value) {
global['EnvironmentVariables'][variable] = value;
}
exports.SetGlobalVariable = SetGlobalVariable;
function RoutePath(path, request, response) {
response.setHeader('server', `ServerHub/${global['EnvironmentVariables'].PackageData['version']} (${core_env.platform}) Node.js ${core_env.node_version}`);
response.setHeader('x-powered-by', `ServerHub`);
function RoutePath(path, request, res) {
res.setHeader('server', `ServerHub/${global['EnvironmentVariables'].PackageData['version']} (${core_env.platform}) Node.js ${core_env.node_version}`);
res.setHeader('x-powered-by', `ServerHub`);
let response = new server_1.ServerHubResponse(res);
response.on('finish', () => {
log_1.LogAccess(request.connection.remoteAddress || '::1', path, response.__length__, request['user'] || 'guest', '-', request.method, request['secure'], request.httpVersion, response.statusCode);
});
let bPromise = plugin_1.BeforeRoute(request, response);
let routeResult = ROUTE.RunRoute(path);
let doneAfterRoutePluginExecution = (errCount) => {
Expand Down
9 changes: 9 additions & 0 deletions dist/lib/core/global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,15 @@ export interface GlobalEnvironmentVariables {
TLSOptions: TLSConfiguration;
RedirectToTLS: true;
Hostname: string;
LogConfig: LogConfiguration;
}
export interface LogConfiguration {
Dir: string;
MaxSize: number;
Access: boolean;
Error: boolean;
Runtime: boolean;
Filename: string;
}
export interface TLSConfiguration {
Port: number;
Expand Down
7 changes: 7 additions & 0 deletions dist/lib/core/log/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import Access from "./log_access";
import Runtime from "./log_runtime";
import Error from "./log_error";
declare class LogService {
static Start(): void;
}
export { Access as LogAccess, Runtime as LogRuntime, Error as LogError, LogService };
39 changes: 39 additions & 0 deletions dist/lib/core/log/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const log_access_1 = require("./log_access");
exports.LogAccess = log_access_1.default;
const log_runtime_1 = require("./log_runtime");
exports.LogRuntime = log_runtime_1.default;
const log_error_1 = require("./log_error");
exports.LogError = log_error_1.default;
const worker_manager_1 = require("./worker_manager");
class LogService {
static Start() {
let variables = global['EnvironmentVariables'];
if (variables.LogConfig.Runtime) {
LogServiceCallback(worker_manager_1.EWorkerType.RUNTIME, () => {
log_runtime_1.default('system', 'ServerHub started');
});
}
if (variables.LogConfig.Access) {
LogServiceCallback(worker_manager_1.EWorkerType.ACCESS, () => { });
}
if (variables.LogConfig.Error) {
LogServiceCallback(worker_manager_1.EWorkerType.ERROR, () => { });
}
}
}
exports.LogService = LogService;
function LogServiceCallback(type, callback) {
switch (type) {
case worker_manager_1.EWorkerType.RUNTIME:
worker_manager_1.WorkerManager.GetInstace().ForkWorker(worker_manager_1.EWorkerType.RUNTIME).then(() => callback());
break;
case worker_manager_1.EWorkerType.ACCESS:
worker_manager_1.WorkerManager.GetInstace().ForkWorker(worker_manager_1.EWorkerType.ACCESS).then(() => callback());
break;
case worker_manager_1.EWorkerType.ERROR:
worker_manager_1.WorkerManager.GetInstace().ForkWorker(worker_manager_1.EWorkerType.ERROR).then(() => callback());
break;
}
}
1 change: 1 addition & 0 deletions dist/lib/core/log/log_access.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default function (ip: string, path: string, length: number, user: string, identity?: string, method?: string, secure?: boolean, version?: string, status?: number): Promise<void>;
37 changes: 37 additions & 0 deletions dist/lib/core/log/log_access.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const worker_manager_1 = require("./worker_manager");
const _1 = require("../util/");
function default_1(ip, path, length, user, identity = '-', method = 'GET', secure = true, version = '1.1', status = 200) {
return __awaiter(this, void 0, void 0, function* () {
let data = `${ip} ${identity} ${user} [${ConvertLogDate(new Date())}] "${method} ${path} HTTP${secure ? 'S' : ''}/${version}" ${status} ${length}`;
if (!worker_manager_1.WorkerManager.GetInstace().Status(worker_manager_1.EWorkerType.ACCESS)) {
yield worker_manager_1.WorkerManager.GetInstace().ForkWorker(worker_manager_1.EWorkerType.ACCESS);
worker_manager_1.WorkerManager.GetInstace().Use(worker_manager_1.EWorkerType.ACCESS, data);
}
else
worker_manager_1.WorkerManager.GetInstace().Use(worker_manager_1.EWorkerType.ACCESS, data);
});
}
exports.default = default_1;
function ConvertLogDate(date) {
let offset = date.getTimezoneOffset();
let offsetStr = '';
if (offset < 0) {
offsetStr = '-' + ((Math.abs(offset) > 999 ? offset.toString() : () => Math.abs(offset) > 99) ? '0' + Math.abs(offset) : '00' + Math.abs(offset));
}
else if (offset > 0) {
offsetStr = '+' + ((offset > 999 ? offset.toString() : () => offset > 99) ? '0' + offset : '00' + offset);
}
else
offsetStr = '0000';
return `${_1.DateTime.GetDay(date.getDate())}/${_1.DateTime.GetMonth(date.getMonth())}/${_1.DateTime.GetYear(date.getFullYear())}:${_1.DateTime.GetHours(date.getHours())}:${_1.DateTime.GetMinutes(date.getMinutes())}:${_1.DateTime.GetSeconds(date.getSeconds())} ${offsetStr}`;
}
1 change: 1 addition & 0 deletions dist/lib/core/log/log_error.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default function (type: string, message: string, note?: any[], source?: string): Promise<void>;
37 changes: 37 additions & 0 deletions dist/lib/core/log/log_error.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const worker_manager_1 = require("./worker_manager");
const _1 = require("../util/");
function default_1(type, message, note = [], source = '') {
return __awaiter(this, void 0, void 0, function* () {
let data = ` [${ConvertLogDate(new Date())}] [${type}] [${note.join(' ')}] "${message}" ${source}`;
if (!worker_manager_1.WorkerManager.GetInstace().Status(worker_manager_1.EWorkerType.ERROR)) {
yield worker_manager_1.WorkerManager.GetInstace().ForkWorker(worker_manager_1.EWorkerType.ERROR);
worker_manager_1.WorkerManager.GetInstace().Use(worker_manager_1.EWorkerType.ERROR, data);
}
else
worker_manager_1.WorkerManager.GetInstace().Use(worker_manager_1.EWorkerType.ERROR, data);
});
}
exports.default = default_1;
function ConvertLogDate(date) {
let offset = date.getTimezoneOffset();
let offsetStr = '';
if (offset < 0) {
offsetStr = '-' + ((Math.abs(offset) > 999 ? offset.toString() : () => Math.abs(offset) > 99) ? '0' + Math.abs(offset) : '00' + Math.abs(offset));
}
else if (offset > 0) {
offsetStr = '+' + ((offset > 999 ? offset.toString() : () => offset > 99) ? '0' + offset : '00' + offset);
}
else
offsetStr = '0000';
return `${_1.DateTime.GetDayName(date.getDay())} ${_1.DateTime.GetMonth(date.getMonth())} ${_1.DateTime.GetDay(date.getDate())} ${_1.DateTime.GetHours(date.getHours())}:${_1.DateTime.GetMinutes(date.getMinutes())}:${_1.DateTime.GetSeconds(date.getSeconds())} ${offsetStr}`;
}
1 change: 1 addition & 0 deletions dist/lib/core/log/log_runtime.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default function (role: string, message: string): Promise<void>;
37 changes: 37 additions & 0 deletions dist/lib/core/log/log_runtime.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const worker_manager_1 = require("./worker_manager");
const _1 = require("../util/");
function default_1(role, message) {
return __awaiter(this, void 0, void 0, function* () {
let data = `${role} [${ConvertLogDate(new Date())}] "${message}"`;
if (!worker_manager_1.WorkerManager.GetInstace().Status(worker_manager_1.EWorkerType.RUNTIME)) {
yield worker_manager_1.WorkerManager.GetInstace().ForkWorker(worker_manager_1.EWorkerType.RUNTIME);
worker_manager_1.WorkerManager.GetInstace().Use(worker_manager_1.EWorkerType.RUNTIME, data);
}
else
worker_manager_1.WorkerManager.GetInstace().Use(worker_manager_1.EWorkerType.RUNTIME, data);
});
}
exports.default = default_1;
function ConvertLogDate(date) {
let offset = date.getTimezoneOffset();
let offsetStr = '';
if (offset < 0) {
offsetStr = '-' + ((Math.abs(offset) > 999 ? offset.toString() : () => Math.abs(offset) > 99) ? '0' + Math.abs(offset) : '00' + Math.abs(offset));
}
else if (offset > 0) {
offsetStr = '+' + ((offset > 999 ? offset.toString() : () => offset > 99) ? '0' + offset : '00' + offset);
}
else
offsetStr = '0000';
return `${_1.DateTime.GetDay(date.getDate())}/${_1.DateTime.GetMonth(date.getMonth())}/${_1.DateTime.GetYear(date.getFullYear())}:${_1.DateTime.GetHours(date.getHours())}:${_1.DateTime.GetMinutes(date.getMinutes())}:${_1.DateTime.GetSeconds(date.getSeconds())} ${offsetStr}`;
}
1 change: 1 addition & 0 deletions dist/lib/core/log/worker.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export {};
71 changes: 71 additions & 0 deletions dist/lib/core/log/worker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const path = require("path");
const fs = require("fs");
const BUFFER = Buffer.alloc(65536 * 8);
const BUFFER_STATUS = {
DATA_FLAG: false,
LENGTH: 0
};
const StreamWrapper = (ws) => {
ws.on('drain', () => {
if (BUFFER_STATUS.DATA_FLAG !== false) {
let buffer = BUFFER.toString('utf8', 0, BUFFER_STATUS.LENGTH);
BUFFER.fill(0);
BUFFER_STATUS.DATA_FLAG = false;
BUFFER_STATUS.LENGTH = 0;
ws.write(buffer);
}
});
};
let filename = 'serverhub';
let maxsize = 65536;
process.argv.forEach(arg => {
if (arg.match(/^filename=[^=/\\><?!]+$/i)) {
filename = arg.split('=')[1];
}
else if (arg.match(/^maxsize=[^=/\\><?!]+$/i)) {
let size = arg.split('=')[1];
try {
maxsize = Math.abs(parseInt(size));
}
catch (error) { }
}
});
let initialPath = path.resolve(process.cwd(), `${filename}-${new Date().getTime()}.log`);
let logstream = fs.createWriteStream(initialPath);
StreamWrapper(logstream);
process.on('message', (data) => {
try {
if (logstream.bytesWritten > maxsize) {
const newstream = () => {
logstream.close();
logstream = fs.createWriteStream(path.resolve(process.cwd(), `${filename}-${new Date().getTime()}.log`));
logstream.on('open', () => {
StreamWrapper(logstream);
logstream.write(data);
});
};
if (logstream.writable) {
newstream();
}
else
logstream.on('drain', newstream);
}
else {
if (logstream.writable) {
logstream.write(data);
}
else {
BUFFER.write(data, BUFFER_STATUS.LENGTH, data.length);
BUFFER_STATUS.DATA_FLAG = true;
BUFFER_STATUS.LENGTH += data.length;
}
}
}
catch (err) {
process.send({
error: err
});
}
});
15 changes: 15 additions & 0 deletions dist/lib/core/log/worker_manager.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
declare enum EWorkerType {
ACCESS = 0,
ERROR = 1,
RUNTIME = 2,
}
declare class WorkerManager {
private constructor();
private static _instance;
private _workers;
static GetInstace(): WorkerManager;
ForkWorker(type: EWorkerType): Promise<{}>;
Use(type: EWorkerType, data: string): void;
Status(type: EWorkerType): boolean;
}
export { EWorkerType, WorkerManager };
Loading