oak-domain/lib/utils/SimpleConnector.js

269 lines
9.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const assert_1 = tslib_1.__importDefault(require("assert"));
const stream_1 = require("stream");
const url_1 = tslib_1.__importDefault(require("url"));
const types_1 = require("../types");
class SimpleConnector {
static ASPECT_ROUTER = '/aspect';
static BRIDGE_ROUTER = '/bridge';
static SUBSCRIBE_PATH = process.env.OAK_SUBSCRIBE_PATH || '/subscribe';
static SOCKET_PATH = process.env.OAK_SOCKET_PATH || '/socket';
static SOCKET_POINT_ROUTER = '/socketPoint';
static ENDPOINT_ROUTER = '/endpoint';
serverUrl;
serverAspectUrl;
serverBridgeUrl;
serverSubscribePointUrl;
configuration;
makeException;
timeout;
clockDriftDuration;
constructor(configuration, makeException) {
this.configuration = configuration;
const { routerPrefixes, http, timeout, clockDriftDuration } = configuration;
this.timeout = timeout || 5000;
this.clockDriftDuration = clockDriftDuration || 10000;
const { ssl, hostname, port, path } = http;
const protocol = ssl ? 'https:' : 'http:';
let serverUrl = `${protocol}//${hostname}`;
this.serverUrl = serverUrl;
if (typeof port === 'number') {
serverUrl += `:${port}`;
}
if (path) {
if (path.startsWith('/')) {
serverUrl += path;
}
else {
serverUrl += `/${path}`;
}
}
this.serverAspectUrl = `${serverUrl}${routerPrefixes?.aspect || SimpleConnector.ASPECT_ROUTER}`;
this.serverBridgeUrl = `${serverUrl}${routerPrefixes?.bridge || SimpleConnector.BRIDGE_ROUTER}`;
this.serverSubscribePointUrl = `${serverUrl}${routerPrefixes?.getSubscribePoint ||
SimpleConnector.SOCKET_POINT_ROUTER}`;
this.makeException = makeException;
}
getCorsHeader() {
return [
'oak-cxt',
'oak-aspect'
];
}
async makeHeadersAndBody(name, data, context) {
const cxtStr = context ? await context.toString() : '{}';
const headers = {
'oak-cxt': cxtStr,
'oak-aspect': name,
};
if (process.env.OAK_PLATFORM !== 'wechatMp') {
// 小程序环境下没有FormData跑到这里会挂
if (data instanceof FormData) {
return {
headers,
body: data,
};
}
}
return {
headers: {
'Content-Type': 'application/json',
...headers,
},
body: JSON.stringify(data),
};
}
;
async parseAspectResult(response) {
if (response.status > 299) {
throw new types_1.OakServerProxyException(`网络请求返回status是${response.status}`);
}
const message = response.headers.get('oak-message');
const responseType = response.headers.get('Content-Type') || response.headers.get('content-type');
if (responseType?.toLocaleLowerCase().match(/application\/json/i)) {
const { exception, result, opRecords } = await response.json();
if (exception) {
throw this.makeException(exception);
}
return {
result,
opRecords,
message,
};
}
// else if (
// responseType
// ?.toLocaleLowerCase()
// .match(/application\/octet-stream/i)
// ) {
// const result = await response.arrayBuffer();
// return {
// result,
// message,
// };
// }
else {
const result = response.body;
return {
result,
message,
};
}
}
async callAspect(name, params, context) {
const { headers, body } = await this.makeHeadersAndBody(name, params, context);
let response;
try {
response = await this.fetchWithTimeout(this.serverAspectUrl, {
method: 'POST',
headers,
body,
}, this.timeout);
}
catch (err) {
// fetch返回异常一定是网络异常
if (err instanceof types_1.OakRequestTimeoutException) {
throw new types_1.OakNetworkException(`接口请求超时`);
}
throw new types_1.OakNetworkException(`接口请求时发生网络异常`);
}
return this.parseAspectResult(response);
}
getRouter() {
return this.configuration.routerPrefixes?.aspect || SimpleConnector.ASPECT_ROUTER;
}
/* getSubscribePath(): string {
return this.configuration.socketPath?.subscribe || SimpleConnector.SUBSCRIBE_PATH;
} */
getSocketPath() {
return this.configuration.socketPath || SimpleConnector.SOCKET_PATH;
}
getSocketPointRouter() {
return this.configuration.routerPrefixes?.getSubscribePoint || SimpleConnector.SOCKET_POINT_ROUTER;
}
async getSocketPoint() {
let response;
try {
response = await this.fetchWithTimeout(this.serverSubscribePointUrl, {}, this.timeout);
}
catch (err) {
if (err instanceof types_1.OakRequestTimeoutException) {
throw new types_1.OakNetworkException(`接口请求超时`);
}
throw new types_1.OakNetworkException(`接口请求时发生网络异常`);
}
if (response.status > 299) {
throw new types_1.OakServerProxyException(`网络请求返回status是${response.status}`);
}
const message = response.headers.get('oak-message');
const responseType = response.headers.get('Content-Type') || response.headers.get('content-type');
if (responseType?.toLocaleLowerCase().match(/application\/json/i)) {
const { socketUrl, subscribeUrl, path } = await response.json();
return {
path,
subscribeUrl,
socketUrl,
};
}
else {
throw new Error(`尚不支持的content-type类型${responseType}`);
}
}
getEndpointRouter() {
return this.configuration.routerPrefixes?.endpoint || SimpleConnector.ENDPOINT_ROUTER;
}
parseRequest(headers, body, files) {
const { 'oak-cxt': oakCxtStr, 'oak-aspect': aspectName } = headers;
(0, assert_1.default)(typeof oakCxtStr === 'string' || oakCxtStr === undefined);
(0, assert_1.default)(typeof aspectName === 'string');
return {
contextString: oakCxtStr,
aspectName,
/* data: !files ? body : {
data: body,
files,
}, */ // 下个版本再改
data: files ? Object.assign({}, body, files) : body,
};
}
async serializeResult(result, opRecords, headers, body, message) {
if (result instanceof stream_1.Stream || result instanceof Buffer) {
return {
body: result,
headers: {
'oak-message': message,
},
};
}
return {
body: {
result,
opRecords,
},
headers: {
'oak-message': message,
},
};
}
serializeException(exception, headers, body) {
return {
body: {
exception: exception.toString(),
},
};
}
getBridgeRouter() {
return SimpleConnector.BRIDGE_ROUTER;
}
/**
* 通过本地服务器桥接访问外部资源的url
* @param url
* @param headers
*/
makeBridgeUrl(url, headers) {
const encodeUrl = encodeURIComponent(url);
return `${this.serverBridgeUrl}?url=${encodeUrl}`;
}
parseBridgeRequestQuery(urlParams) {
const search = new url_1.default.URLSearchParams(urlParams);
const url = search.get('url');
const headers = search.get('headers');
return {
url,
headers: headers && JSON.parse(headers),
};
}
async getFullData() {
console.error('前后台模式下暂时不支持此操作,请到数据库查看数据');
return {};
}
async fetchWithTimeout(url, options, timeout = 5000) {
return global.fetch(url, options);
// if (typeof AbortController === 'undefined' || timeout === 0) {
// return global.fetch(url, options);
// }
// const controller = new AbortController();
// const signal = controller.signal;
// // 设置超时
// const timeoutId = setTimeout(() => {
// controller.abort();
// }, timeout);
// // 发起 fetch 请求并传递 signal
// return global.fetch(url, Object.assign({}, options, { signal }))
// .then(response => {
// clearTimeout(timeoutId); // 如果请求成功,清除超时
// return response;
// })
// .catch(error => {
// clearTimeout(timeoutId); // 如果请求失败,清除超时
// if (error.name === 'AbortError') {
// throw new OakRequestTimeoutException();
// }
// throw error; // 其他错误
// });
}
}
exports.default = SimpleConnector;