@creditkarma/thrift-client
Version:
Thrift client library for NodeJS written in TypeScript.
145 lines • 5.97 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.HttpConnection = exports.DEFAULT_PATH = void 0;
const Core = __importStar(require("@creditkarma/thrift-server-core"));
const got_1 = __importStar(require("got"));
const utils_1 = require("./utils");
exports.DEFAULT_PATH = '/thrift';
function shouldRetry(response, retry, withEndpointPerMethod) {
return (withEndpointPerMethod && response?.statusCode === 404 && retry === false);
}
function isErrorResponse(response) {
return (response.statusCode !== null &&
response.statusCode !== undefined &&
(response.statusCode < 200 || response.statusCode > 299));
}
function filterHeaders(options, blacklist) {
options.headers = options.headers || {};
blacklist = blacklist.map((next) => next.toLocaleLowerCase());
options.headers = Object.keys(options.headers).reduce((acc, next) => {
if (blacklist.indexOf(next.toLocaleLowerCase()) === -1) {
acc[next] = options.headers[next];
}
return acc;
}, {});
return options;
}
function applyFilters(currentRequest, filters, callback) {
const [head, ...tail] = filters;
if (head === undefined) {
return callback(currentRequest);
}
else {
return head(currentRequest, (nextData, nextOptions) => {
const data = nextData !== undefined ? nextData : currentRequest.data;
return applyFilters({
data,
methodName: currentRequest.methodName,
uri: currentRequest.uri,
context: Core.deepMerge(currentRequest.context, nextOptions || {}),
}, tail, callback);
});
}
}
class HttpConnection extends Core.ThriftConnection {
constructor({ hostName, port, path = '/thrift', https = false, transport = 'buffered', protocol = 'binary', requestOptions = {}, serviceName, withEndpointPerMethod = false, headerBlacklist = [], gotImpl = got_1.default, }) {
super(Core.getTransport(transport), Core.getProtocol(protocol));
this.requestOptions = Object.freeze(filterHeaders({ responseType: 'buffer', ...requestOptions }, headerBlacklist));
this.port = port;
this.hostName = hostName;
this.path = Core.normalizePath(path || exports.DEFAULT_PATH);
this.protocol = https === true ? 'https' : 'http';
this.serviceName = serviceName;
this.basePath = `${this.protocol}://${this.hostName}:${this.port}`;
this.withEndpointPerMethod = withEndpointPerMethod;
this.url = `${this.basePath}${this.path}`;
this.filters = [];
this.gotImpl = gotImpl;
}
register(...filters) {
filters.forEach((next) => {
this.filters.push({
methods: next.methods || [],
handler: next.handler,
});
});
}
send(dataToSend, context = {}) {
const requestMethod = Core.readThriftMethod(dataToSend, this.Transport, this.Protocol);
const filters = this.filtersForMethod(requestMethod);
const thriftRequest = {
data: dataToSend,
methodName: requestMethod,
uri: this.url,
context,
};
return applyFilters(thriftRequest, filters, (finalRequest) => {
return this.write(finalRequest.data, finalRequest.methodName, finalRequest.context);
}).then((res) => {
return res.body;
});
}
write(dataToWrite, methodName, options = {}, retry = false) {
const requestUrl = this.withEndpointPerMethod && retry === false
? `${this.url}/${this.serviceName}/${methodName}`
: this.url;
const requestOptions = Core.overlayObjects(this.requestOptions, options, {
method: 'POST',
body: dataToWrite,
url: requestUrl,
headers: {
'Content-Length': dataToWrite.length.toString(),
'Content-Type': 'application/octet-stream',
},
});
return this.gotImpl(requestOptions)
.then((response) => {
if (isErrorResponse(response)) {
throw response;
}
return {
statusCode: response.statusCode,
headers: response.headers,
body: response.rawBody,
};
})
.catch((err) => {
if (err instanceof got_1.HTTPError) {
if (shouldRetry(err.response, retry, this.withEndpointPerMethod)) {
return this.write(dataToWrite, methodName, options, true);
}
}
throw err;
});
}
filtersForMethod(name) {
return this.filters
.filter((0, utils_1.filterByMethod)(name))
.map((filter) => filter.handler);
}
}
exports.HttpConnection = HttpConnection;
//# sourceMappingURL=HttpConnection.js.map