feat(domains) implement domain routing; Logger
This commit is contained in:
51
src/Routing/BaseRouter.js
Normal file
51
src/Routing/BaseRouter.js
Normal file
@@ -0,0 +1,51 @@
|
||||
import Logger from '../Utils/Logger';
|
||||
|
||||
export default class BaseRouter {
|
||||
add(path, cb, options = {}) {
|
||||
Logger.error('add method not implemented');
|
||||
}
|
||||
|
||||
any(path, cb) {
|
||||
this.all(path, cb);
|
||||
}
|
||||
|
||||
all(path, cb) {
|
||||
this.add(path, cb, { ...(arguments[2] || {}), method: 'all' });
|
||||
return this;
|
||||
}
|
||||
|
||||
get(path, cb) {
|
||||
this.add(path, cb, { ...(arguments[2] || {}), method: 'get' });
|
||||
return this;
|
||||
}
|
||||
|
||||
post(path, cb) {
|
||||
this.add(path, cb, { ...(arguments[2] || {}), method: 'post' });
|
||||
return this;
|
||||
}
|
||||
|
||||
put(path, cb) {
|
||||
this.add(path, cb, { ...(arguments[2] || {}), method: 'put' });
|
||||
return this;
|
||||
}
|
||||
|
||||
patch(path, cb) {
|
||||
this.add(path, cb, { ...(arguments[2] || {}), method: 'patch' });
|
||||
return this;
|
||||
}
|
||||
|
||||
delete(path, cb) {
|
||||
this.add(path, cb, { ...(arguments[2] || {}), method: 'delete' });
|
||||
return this;
|
||||
}
|
||||
|
||||
head(path, cb) {
|
||||
this.add(path, cb, { ...(arguments[2] || {}), method: 'head' });
|
||||
return this;
|
||||
}
|
||||
|
||||
options(path, cb) {
|
||||
this.add(path, cb, { ...(arguments[2] || {}), method: 'options' });
|
||||
return this;
|
||||
}
|
||||
}
|
||||
50
src/Routing/BaseRouter.js~
Normal file
50
src/Routing/BaseRouter.js~
Normal file
@@ -0,0 +1,50 @@
|
||||
import Logger from '../Utils/Logger';
|
||||
export default class BaseRouter {
|
||||
add(path, cb, options = {}) {
|
||||
Logger.error('add method not implemented');
|
||||
}
|
||||
|
||||
any(path, cb) {
|
||||
this.all(path, cb);
|
||||
}
|
||||
|
||||
all(path, cb) {
|
||||
this.add(path, cb, { ...(arguments[2] || {}), method: 'all' });
|
||||
return this;
|
||||
}
|
||||
|
||||
get(path, cb) {
|
||||
this.add(path, cb, { ...(arguments[2] || {}), method: 'get' });
|
||||
return this;
|
||||
}
|
||||
|
||||
post(path, cb) {
|
||||
this.add(path, cb, { ...(arguments[2] || {}), method: 'post' });
|
||||
return this;
|
||||
}
|
||||
|
||||
put(path, cb) {
|
||||
this.add(path, cb, { ...(arguments[2] || {}), method: 'put' });
|
||||
return this;
|
||||
}
|
||||
|
||||
patch(path, cb) {
|
||||
this.add(path, cb, { ...(arguments[2] || {}), method: 'patch' });
|
||||
return this;
|
||||
}
|
||||
|
||||
delete(path, cb) {
|
||||
this.add(path, cb, { ...(arguments[2] || {}), method: 'delete' });
|
||||
return this;
|
||||
}
|
||||
|
||||
head(path, cb) {
|
||||
this.add(path, cb, { ...(arguments[2] || {}), method: 'head' });
|
||||
return this;
|
||||
}
|
||||
|
||||
options(path, cb) {
|
||||
this.add(path, cb, { ...(arguments[2] || {}), method: 'options' });
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,23 @@
|
||||
export default class LayRouting {
|
||||
router;
|
||||
namespace;
|
||||
constructor(router, namespace = null) {
|
||||
this.router = router;
|
||||
import Router from './Router';
|
||||
import BaseRouter from './BaseRouter';
|
||||
import LayRequest from '../IO/LayRequest';
|
||||
import LayResponse from '../IO/LayResponse';
|
||||
import Logger from '../Utils/Logger';
|
||||
|
||||
if (namespace !== null) this.namespace = namespace;
|
||||
export default class LayRouting extends BaseRouter {
|
||||
routers;
|
||||
namespace = null;
|
||||
server;
|
||||
constructor(server, namespace = null) {
|
||||
super();
|
||||
this.server = server;
|
||||
this.routers = new Map([
|
||||
['$default', new Router(this.server)]
|
||||
]);
|
||||
}
|
||||
|
||||
getServer() {
|
||||
return this.server;
|
||||
}
|
||||
|
||||
setNamespace(ns) {
|
||||
@@ -13,16 +26,18 @@ export default class LayRouting {
|
||||
}
|
||||
|
||||
routes() {
|
||||
return this.router.routes;
|
||||
return this.routers.get('$default').routes;
|
||||
}
|
||||
|
||||
add(path, cb, method) {
|
||||
if (this.namespace) {
|
||||
if (!path.startsWith('/')) path = '/' + path;
|
||||
path = this.namespace + path;
|
||||
addRouter(router) {
|
||||
let routerInstance;
|
||||
if(typeof router == 'undefined' || router === null) {
|
||||
routerInstance = new Router(this.server);
|
||||
} else {
|
||||
routerInstance = new router(this.server);
|
||||
}
|
||||
|
||||
this.router.add(path, cb, method);
|
||||
this.routers.set(router.domain || '$default', routerInstance);
|
||||
}
|
||||
|
||||
route(config = {}) {
|
||||
@@ -38,47 +53,48 @@ export default class LayRouting {
|
||||
return this;
|
||||
}
|
||||
|
||||
any(path, cb) {
|
||||
this.all(path, cb);
|
||||
async handle(req) {
|
||||
const url = new URL(req.url);
|
||||
const reqContext = {
|
||||
request: null,
|
||||
response: null,
|
||||
};
|
||||
try {
|
||||
reqContext.request = new LayRequest(req);
|
||||
reqContext.response = new LayResponse(this);
|
||||
} catch (err) {
|
||||
Logger.error(err);
|
||||
}
|
||||
|
||||
let domain = url.hostname;
|
||||
if([...this.routers.keys()].indexOf(domain) < 0) domain = '$default';
|
||||
return await this.routers.get(domain).handle(reqContext);
|
||||
}
|
||||
|
||||
all(path, cb) {
|
||||
this.add(path, cb, 'all');
|
||||
return this;
|
||||
}
|
||||
add(path, cb) {
|
||||
let options = arguments[2] ?? { method: 'get', domain: '$default' };
|
||||
if(typeof options.domain != 'string') options.domain = '$default';
|
||||
if (this.namespace) {
|
||||
if (!path.startsWith('/')) path = '/' + path;
|
||||
path = this.namespace + path;
|
||||
}
|
||||
|
||||
get(path, cb) {
|
||||
this.add(path, cb, 'get');
|
||||
return this;
|
||||
}
|
||||
Logger(path, options)
|
||||
|
||||
post(path, cb) {
|
||||
this.add(path, cb, 'post');
|
||||
return this;
|
||||
}
|
||||
if(options.domain === '$default') {
|
||||
let domains = this.routers.keys();
|
||||
for(let domain of [...domains]) {
|
||||
this.routers.get(domain).add(path, cb, options);
|
||||
}
|
||||
} else {
|
||||
if(!this.routers.has(options.domain)) {
|
||||
const domainRouter = Router;
|
||||
domainRouter.domain = options.domain;
|
||||
this.addRouter(domainRouter);
|
||||
Logger('added new router for domain', options.domain)
|
||||
}
|
||||
|
||||
put(path, cb) {
|
||||
this.add(path, cb, 'put');
|
||||
return this;
|
||||
}
|
||||
|
||||
patch(path, cb) {
|
||||
this.add(path, cb, 'patch');
|
||||
return this;
|
||||
}
|
||||
|
||||
delete(path, cb) {
|
||||
this.add(path, cb, 'delete');
|
||||
return this;
|
||||
}
|
||||
|
||||
head(path, cb) {
|
||||
this.add(path, cb, 'head');
|
||||
return this;
|
||||
}
|
||||
|
||||
options(path, cb) {
|
||||
this.add(path, cb, 'options');
|
||||
return this;
|
||||
this.routers.get(options.domain).add (path, cb, options);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
100
src/Routing/LayRouting.js~
Normal file
100
src/Routing/LayRouting.js~
Normal file
@@ -0,0 +1,100 @@
|
||||
import Router from './Router';
|
||||
import BaseRouter from './BaseRouter';
|
||||
import LayRequest from '../IO/LayRequest';
|
||||
import LayResponse from '../IO/LayResponse';
|
||||
import Logger from '../Utils/Logger';
|
||||
|
||||
export default class LayRouting extends BaseRouter {
|
||||
routers;
|
||||
namespace = null;
|
||||
server;
|
||||
constructor(server, namespace = null) {
|
||||
super();
|
||||
this.server = server;
|
||||
this.routers = new Map([
|
||||
['$default', new Router(this.server)]
|
||||
]);
|
||||
}
|
||||
|
||||
getServer() {
|
||||
return this.server;
|
||||
}
|
||||
|
||||
setNamespace(ns) {
|
||||
if (!ns || typeof ns != 'string') this.namespace = null;
|
||||
this.namespace = ns;
|
||||
}
|
||||
|
||||
routes() {
|
||||
return this.routers.get('$default').routes;
|
||||
}
|
||||
|
||||
addRouter(router) {
|
||||
let routerInstance;
|
||||
if(typeof router == 'undefined' || router === null) {
|
||||
routerInstance = new Router(this.server);
|
||||
} else {
|
||||
routerInstance = new router(this.server);
|
||||
}
|
||||
|
||||
this.routers.set(router.domain || '$default', routerInstance);
|
||||
}
|
||||
|
||||
route(config = {}) {
|
||||
if (typeof config != 'object')
|
||||
throw new Error('route config is not an object');
|
||||
|
||||
const { path, handle, method = 'get' } = config;
|
||||
if (typeof path != 'string')
|
||||
throw new Error('route path is not a string');
|
||||
if (typeof handle != 'function')
|
||||
throw new Error('route handle is not a function');
|
||||
this.add(path, handle, method);
|
||||
return this;
|
||||
}
|
||||
|
||||
async handle(req) {
|
||||
const url = new URL(req.url);
|
||||
const reqContext = {
|
||||
request: null,
|
||||
response: null,
|
||||
};
|
||||
try {
|
||||
reqContext.request = new LayRequest(req);
|
||||
reqContext.response = new LayResponse(this);
|
||||
} catch (err) {
|
||||
Logger.error(err);
|
||||
}
|
||||
|
||||
let domain = url.hostname;
|
||||
if([...this.routers.keys()].indexOf(domain) < 0) domain = '$default';
|
||||
return await this.routers.get(domain).handle(reqContext);
|
||||
}
|
||||
|
||||
add(path, cb) {
|
||||
let options = arguments[2] ?? { method: 'get', domain: '$default' };
|
||||
if(typeof options.domain != 'string') options.domain = '$default';
|
||||
if (this.namespace) {
|
||||
if (!path.startsWith('/')) path = '/' + path;
|
||||
path = this.namespace + path;
|
||||
}
|
||||
|
||||
Logger(path, options)
|
||||
|
||||
if(options.domain === '$default') {
|
||||
let domains = this.routers.keys();
|
||||
for(let domain of [...domains]) {
|
||||
this.routers.get(domain).add(path, cb, options);
|
||||
}
|
||||
} else {
|
||||
if(!this.routers.has(options.domain)) {
|
||||
const domainRouter = Router;
|
||||
domainRouter.domain = options.domain;
|
||||
this.addRouter(domainRouter);
|
||||
Logger('added new router for domain', options.domain)
|
||||
}
|
||||
|
||||
this.routers.get(options.domain).add (path, cb, options);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,9 @@
|
||||
import LayRequest from '../IO/LayRequest';
|
||||
import LayResponse from '../IO/LayResponse';
|
||||
import RequestParser from '../Utils/RequestParser';
|
||||
import BaseRouter from './BaseRouter';
|
||||
import Logger from '../Utils/Logger';
|
||||
|
||||
export default class Router {
|
||||
export default class Router extends BaseRouter {
|
||||
domain = undefined;
|
||||
server = undefined;
|
||||
routes = new Map();
|
||||
static allMethodKey = '$all';
|
||||
@@ -10,6 +11,7 @@ export default class Router {
|
||||
headerList = new Map();
|
||||
|
||||
constructor(server) {
|
||||
super();
|
||||
this.server = server;
|
||||
}
|
||||
|
||||
@@ -17,15 +19,11 @@ export default class Router {
|
||||
return this.server;
|
||||
}
|
||||
|
||||
async handle(req) {
|
||||
if (!(req instanceof Request)) {
|
||||
throw new Error('`req` is not a proper Request');
|
||||
}
|
||||
|
||||
let method = (req.method || '').toString().toLowerCase();
|
||||
async handle(reqContext) {
|
||||
let method = (reqContext.request.method || '').toString().toLowerCase();
|
||||
const methodKey = `$${method.toLowerCase()}`;
|
||||
let path;
|
||||
let url = req.url;
|
||||
let url = reqContext.request.url;
|
||||
|
||||
if (!(url instanceof URL) && typeof url == 'string') {
|
||||
url = new URL(url);
|
||||
@@ -78,16 +76,6 @@ export default class Router {
|
||||
});
|
||||
}
|
||||
|
||||
const reqContext = {
|
||||
request: null,
|
||||
response: null,
|
||||
};
|
||||
try {
|
||||
reqContext.request = new LayRequest(req);
|
||||
reqContext.response = new LayResponse(this);
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
}
|
||||
let handle =
|
||||
currentNode.get(methodKey) || currentNode.get(Router.allMethodKey);
|
||||
|
||||
@@ -124,7 +112,7 @@ export default class Router {
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
Logger(err);
|
||||
return new Response('Error', { status: 500 });
|
||||
}
|
||||
|
||||
@@ -141,21 +129,23 @@ export default class Router {
|
||||
});
|
||||
}
|
||||
|
||||
add(route, callback, method = 'get', middleware = null) {
|
||||
add(route, callback) {
|
||||
let options = arguments[2];
|
||||
let middleware = arguments[3];
|
||||
if (typeof callback != 'function')
|
||||
throw new Error('`callback` is not a function');
|
||||
if (typeof route != 'string')
|
||||
throw new Error('`route` is not a string');
|
||||
if (Router.methods.indexOf(method) < 0)
|
||||
if (Router.methods.indexOf(options.method) < 0)
|
||||
throw new Error(
|
||||
`invalid \`method\` (${method}) given`,
|
||||
`invalid \`method\` (${options.method}) given`,
|
||||
Router.methods
|
||||
);
|
||||
if (!Array.isArray(middleware)) {
|
||||
middleware = typeof middleware == 'function' ? [middleware] : null;
|
||||
}
|
||||
|
||||
const methodKey = `$${method.toLowerCase()}`;
|
||||
const methodKey = `$${options.method.toLowerCase()}`;
|
||||
if (route.startsWith('/')) route = route.substring(1);
|
||||
if (route.endsWith('/')) route = route.substring(0, route.length - 1);
|
||||
|
||||
@@ -165,14 +155,14 @@ export default class Router {
|
||||
|
||||
if (route == '') {
|
||||
if (currentNode.get(methodKey)) {
|
||||
if (!this.server.option('allowOverwrite')) {
|
||||
console.log(
|
||||
`overwriting of routes is prohibited: [${method}] \`${route}\``
|
||||
if (!this.server.option('allowRouteOverwrite')) {
|
||||
Logger(
|
||||
`overwriting of routes is prohibited: [${options.method}] \`${route}\``
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`overwriting route for \`${route}\``);
|
||||
Logger(`overwriting route for \`${route}\``);
|
||||
}
|
||||
currentNode.set(methodKey, { callback, middleware, params: [] });
|
||||
return;
|
||||
@@ -202,14 +192,14 @@ export default class Router {
|
||||
}
|
||||
|
||||
if (currentNode.has(methodKey)) {
|
||||
if (!this.server.option('allowOverwrite')) {
|
||||
console.log(
|
||||
if (!this.server.option('allowRouteOverwrite')) {
|
||||
Logger(
|
||||
`overwriting of routes is prohibited: [${method}] \`${route}\``
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`overwriting route for \`${route}\``);
|
||||
Logger(`overwriting route for \`${route}\``);
|
||||
}
|
||||
|
||||
currentNode.set(methodKey, { callback, middleware, params });
|
||||
|
||||
Reference in New Issue
Block a user