UNPKG

@fullstory/server-api-client

Version:

The official FullStory server API client SDK for NodeJS.

153 lines 7.12 kB
"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 __exportStar = (this && this.__exportStar) || function(m, exports) { for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); }; 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; }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } 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) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.FSHttpClientImpl = void 0; __exportStar(require("./options"), exports); const http = __importStar(require("node:http")); const https = __importStar(require("node:https")); const errors_1 = require("../errors"); const defaultHttpsAgent = new https.Agent({ keepAlive: true }); const defaultHttpAgent = new http.Agent({ keepAlive: true }); const integrationSourceKey = 'Integration-Source'; // TODO(sabrina): separate out the error handling stuff out from the http client class FSHttpClientImpl { // TODO(sabrina): allow passing in a node https agent? constructor(opts) { this.opts = opts; } request(opts, body, fsReq) { return new Promise((resolve, reject) => { let connectionEvent = 'secureConnect'; if (!opts.agent) { if (opts.protocol === 'http:') { connectionEvent = 'connect'; opts.agent = defaultHttpAgent; } else { opts.agent = defaultHttpsAgent; } } const req = https.request(opts); req.setHeader('Authorization', this.opts.apiKey); // TODO(sabrina): make opts object to be able to update headers so we can add them easier if (!req.hasHeader(integrationSourceKey) && (fsReq === null || fsReq === void 0 ? void 0 : fsReq.integrationSource)) { // first check per request opt if any req.setHeader(integrationSourceKey, fsReq.integrationSource); } else if (!req.hasHeader(integrationSourceKey) && this.opts.integrationSource) { // fall back to opts for the whole client if any req.setHeader(integrationSourceKey, this.opts.integrationSource); } req.once('socket', (socket) => { if (socket.connecting) { socket.once(connectionEvent, () => { body && req.write(JSON.stringify(body)); req.end(); }); } else { // already connected, send body body && req.write(JSON.stringify(body)); req.end(); } }); req.on('response', inMsg => { this.handleResponse(inMsg) .then(rsp => { resolve({ httpHeaders: inMsg.headers, httpStatusCode: inMsg.statusCode, body: rsp }); }) .catch(err => reject(err)); }); req.on('error', (error) => { reject(error); }); req.on('timeout', () => { const err = new errors_1.FSTimeoutError(`Request ${req.path} timed out.`); req.destroy(err); }); }); } handleResponse(msg) { return __awaiter(this, void 0, void 0, function* () { return new Promise((resolve, reject) => { let responseDataStr = ''; msg.setEncoding('utf8'); msg.on('data', (chunk) => { responseDataStr += chunk; }); msg.once('end', () => { if (!msg.statusCode) { // TODO(sabrina): better handle unknown status code error reject(new Error('Unknown error occurred, did not receive HTTP status code.')); return; } if (msg.statusCode === 204) { resolve({}); return; } if (msg.statusCode < 200 || msg.statusCode >= 300) { reject(new errors_1.FSApiError(`HTTP error status ${msg.statusCode} received.`, msg.statusCode, msg.headers, responseDataStr)); return; } let responseData; if (responseDataStr) { try { responseData = JSON.parse(responseDataStr); } catch (e) { // It's possible that response is invalid json, return parse error regardless of response status if (e instanceof SyntaxError) { reject(new errors_1.FSParserError('Invalid JSON response', msg.statusCode, msg.headers, responseDataStr, e)); } else { reject(new errors_1.FSParserError('Unknown error while parsing JSON response', msg.statusCode, msg.headers, responseDataStr, e)); } return; } } resolve(responseData); }); }); }); } } exports.FSHttpClientImpl = FSHttpClientImpl; //# sourceMappingURL=index.js.map