Socket
Socket
Sign inDemoInstall

@nohost/router

Package Overview
Dependencies
Maintainers
2
Versions
20
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@nohost/router - npm Package Compare versions

Comparing version 0.7.0 to 0.8.0

113

lib/index.js
const url = require('url');
const { parse: parseUrl } = require('url');
const { onClose, getRawHeaders } = require('@nohost/connect');
const { getServers, isFinished, getJSON } = require('./util');
const { getServers, isFinished, decode, getJSON } = require('./util');
const { connect, writeError, writeHead, writeBody } = require('./connect');

@@ -13,3 +13,50 @@

const ENV_HEAD = 'x-whistle-nohost-env';
const NOHOST_RULE = 'x-whistle-rule-value';
const NOHOST_VALUE = 'x-whistle-key-value';
const CLIENT_ID = 'x-whistle-client-id';
const CLIENT_ID_FILTER = 'x-whistle-filter-client-id';
const ROUTE_RE = /([?&])route=([^?&]+)($|&)/;
const ROUTE_VALUE_RE = /^[\w.:/=+-]{1,100}$/;
const isString = (str) => {
return str && typeof str === 'string';
};
const getString = (obj) => {
if (!obj || typeof obj === 'string') {
return obj;
}
if (typeof obj === 'object') {
try {
return JSON.stringify(obj);
} catch (e) {}
}
};
const addOptions = (req, options) => {
if (!options) {
return;
}
const { headers, isUIRequest } = req;
delete headers['x-whistle-nohost-rule'];
delete headers['x-whistle-nohost-value'];
const addHeader = (name, value) => {
if (isString(value)) {
headers[name] = encodeURIComponent(value);
} else {
delete headers[name];
}
};
if (isUIRequest) {
addHeader(CLIENT_ID_FILTER, options.clientId);
} else {
addHeader(NOHOST_RULE, options.rules);
addHeader(NOHOST_VALUE, getString(options.values));
addHeader(CLIENT_ID, options.clientId);
}
addHeader(SPACE_NAME, options.spaceName);
addHeader(GROUP_NAME, options.groupName);
addHeader(ENV_NAME, options.envName);
};
class Router {

@@ -51,3 +98,3 @@ constructor(servers) {

const server = servers[i];
if (typeof callback === 'function') {
if (callback) {
callback(server);

@@ -98,4 +145,16 @@ }

async proxy(req, res, callback) {
existsHost(host) {
return this._result ? this._result.map[host] : false;
}
async proxy(req, res, options) {
onClose(res);
let callback;
if (typeof options === 'function') {
callback = options;
options = null;
} else if (typeof options.callback === 'function') {
callback = options.callback;
}
addOptions(req, options);
if (this._nohostAddress) {

@@ -105,3 +164,3 @@ if (req.isUIRequest) {

}
if (typeof callback === 'function') {
if (callback) {
callback(this._nohostAddress);

@@ -116,7 +175,3 @@ }

if (!result || isFinished(req)) {
if (!res) {
throw new Error(result ? 'request is finished.' : 'not found nohost server.');
}
req.destroy();
return;
throw new Error(result ? 'request is finished.' : 'not found nohost server.');
}

@@ -129,11 +184,21 @@ const { headers } = req;

if (req.isUIRequest) {
if (!res) {
throw new Error('space & group is required.');
}
req.destroy();
return;
throw new Error('space & group is required.');
}
return this._connectDefault(req, res, callback);
}
const status = await this._getStatus(space, group, name);
let status;
let needRoute;
if (req.isUIRequest && ROUTE_RE.test(req.url)) {
let host = decode(RegExp.$2);
if (host === '!required!') {
needRoute = true;
} else if (ROUTE_VALUE_RE.test(host)) {
host = Buffer.from(host, 'base64').toString();
if (this.existsHost(host)) {
host = host.split(':');
status = { host: host[0], port: host[1] };
}
}
}
status = status || await this._getStatus(space, group, name);
if (!status || !status.host) {

@@ -152,5 +217,9 @@ return this._connectDefault(req, res, callback);

req.url = `/account/${env}${path}`;
if (needRoute) {
const route = Buffer.from(`${status.host}:${status.port}`).toString('base64');
req.url = req.url.replace(ROUTE_RE, `$1route=${route}$3`);
}
}
headers[ENV_HEAD] = env;
if (typeof callback === 'function') {
if (callback) {
callback(status);

@@ -161,5 +230,5 @@ }

proxyUI(req, res, callback) {
proxyUI(req, res, options) {
req.isUIRequest = true;
return this.proxy(req, res, callback);
return this.proxy(req, res, options);
}

@@ -171,6 +240,6 @@ }

Router.ENV_NAME = ENV_NAME;
Router.NOHOST_RULE = 'x-whistle-rule-value';
Router.NOHOST_VALUE = 'x-whistle-key-value';
Router.CLIENT_ID = 'x-whistle-client-id';
Router.CLIENT_ID_FILTER = 'x-whistle-filter-client-id';
Router.NOHOST_RULE = NOHOST_RULE;
Router.NOHOST_VALUE = NOHOST_VALUE;
Router.CLIENT_ID = CLIENT_ID;
Router.CLIENT_ID_FILTER = CLIENT_ID_FILTER;
Router.writeError = writeError;

@@ -177,0 +246,0 @@ Router.writeHead = writeHead;

@@ -94,6 +94,10 @@ const http = require('http');

servers = usableServers.filter(noop);
const map = {};
const list = servers.map((server) => {
return `${server.host}:${server.port}/${server.workerNum}`;
const host = `${server.host}:${server.port}`;
map[host] = server;
return `${host}/${server.workerNum}`;
});
return list.length && {
map,
servers,

@@ -103,1 +107,8 @@ base64: Buffer.from(list.join()).toString('base64'),

};
exports.decode = (str) => {
try {
return decodeURIComponent(str);
} catch (e) {}
return str;
};

2

package.json
{
"name": "@nohost/router",
"version": "0.7.0",
"version": "0.8.0",
"description": "Nohost cluster router",

@@ -5,0 +5,0 @@ "main": "lib/",

@@ -70,17 +70,28 @@ # router

``` js
const { headers } = req;
// 设置规则,可以从数据库动态获取
headers[NOHOST_RULE] = encodeURIComponent('ke.qq.com file://{test.html}');
headers[NOHOST_VALUE] = encodeURIComponent(JSON.stringify({ 'test.html': 'hell world.' }));
const getOptions = (req) => {
const { headers } = req;
const spaceName = 'imweb';
let gruopName;
let envName;
if (headers.host === 'km.oa2.com') {
gruopName = 'avenwu';
envName = '测试'; // 可选
} else if (req.headers.host !== 'km.oa.com') {
gruopName = 'avenwu2';
envName = '测试2'; // 可选
}
// 设置环境
headers[SPACE_NAME] = encodeURIComponent('imweb');
headers[GROUP_NAME] = encodeURIComponent('avenwu');
headers[ENV_NAME] = encodeURIComponent('测试'); // 可选
return {
rules: 'file://{test.html} km.oa2.com www.test2.com',
values: { 'test.html': 'hell world.' },
spaceName,
gruopName,
envName,
callback: console.log, // 可选
// clientId: 'test', // 如果从外网转发过来的带登录态请求,设置下 clientId 方便插件当前用户的请求抓包
};
};
// 如果从外网转发过来的带登录态请求,设置下 clientId 方便插件当前用户的请求抓包
// headers[CLIENT_ID] = uin;
router.proxy(req, res, getOptions(req));
router.proxy(req, res);
// 或自己处理响应

@@ -92,11 +103,3 @@ // const svrRes = await router.proxy(req);

``` js
// 设置环境
headers[SPACE_NAME] = encodeURIComponent('imweb');
headers[GROUP_NAME] = encodeURIComponent('avenwu');
headers[ENV_NAME] = encodeURIComponent('测试'); // 可选
// 只查看指定 clientId 的请求
// headers[CLIENT_ID_FILTER] = uin;
router.proxyUI(req, res);
router.proxyUI(req, res, getOptions(req));
```

@@ -103,0 +106,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc