UNPKG

aft-web-services

Version:

Automated Functional Testing (AFT) module for testing web services over HTTP and HTTPS

265 lines 10.8 kB
"use strict"; 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.httpService = exports.HttpService = exports.HttpServiceConfig = void 0; const http = require("http"); const https = require("https"); const aft_core_1 = require("aft-core"); class HttpServiceConfig { constructor() { this.defaultUrl = 'http://127.0.0.1'; this.defaultHeaders = {}; this.defaultMethod = 'GET'; this.defaultAllowRedirect = true; this.defaultMultipart = false; } } exports.HttpServiceConfig = HttpServiceConfig; /** * supports performing requests over http / https returning the response as a * `HttpResponse` object. Requests should include a URL at a minimum, * but may also specify additional details such as headers, auto redirect, * post data and the request method (GET|POST|PUT|DELETE|UPDATE) * ex: * ```typescript * await httpService.performRequest({url: 'https://some.domain/path'}); * ``` * or fully as: * ```typescript * await httpService.performRequest({ * url: 'https://some.domain/path', * allowAutoRedirect: false, * headers: {"Authorization": "basic AS0978FASLKLJA/=="}, * method: 'POST', * postData: someObject, * multipart: false * }); * ``` * or multipart post as: * ```typescript * let formData = new FormData(); * formData.append("Authorization": "basic AS0978FASLKLJA/=="); * await httpService.performRequest({ * url: 'https://some.domain/path', * allowAutoRedirect: false, * method: 'POST', * postData: formData, * multipart: true * }); * ``` */ class HttpService { constructor(aftCfg) { this.aftCfg = aftCfg !== null && aftCfg !== void 0 ? aftCfg : aft_core_1.aftConfig; } /** * issues a request over http / https and returns the response as a * `HttpResponse` object. Requests should include a URL at a minimum, * but may also specify additional details such as headers, auto redirect, * post data and the request method (GET|POST|PUT|DELETE|UPDATE) * ex: * ```typescript * await httpService.performRequest({url: 'https://some.domain/path'}); * ``` * or fully as: * ```typescript * await httpService.performRequest({ * url: 'https://some.domain/path', * allowAutoRedirect: false, * headers: {"Authorization": "basic AS0978FASLKLJA/=="}, * method: 'POST', * postData: someObject, * multipart: false * }); * ``` * or multipart post as: * ```typescript * let formData = new FormData(); * formData.append("Authorization": "basic AS0978FASLKLJA/=="); * await httpService.performRequest({ * url: 'https://some.domain/path', * allowAutoRedirect: false, * method: 'POST', * postData: formData, * multipart: true * }); * ``` * @param req a `HttpResponse` object that specifies details of the request */ performRequest(req) { return __awaiter(this, void 0, void 0, function* () { try { req = yield this.setRequestDefaults(req); let logMessage = `issuing '${req.method}' request to '${req.url}' with post body '${req.postData}' and headers '${JSON.stringify(req.headers)}'.`; if (req.reporter) { yield req.reporter.debug(logMessage); } else { aft_core_1.aftLogger.log({ name: this.constructor.name, level: 'trace', message: logMessage }); } const message = yield this._request(req); const resp = yield this._response(message, req.allowAutoRedirect); logMessage = `received response data of '${resp === null || resp === void 0 ? void 0 : resp.data}' and headers '${JSON.stringify(resp === null || resp === void 0 ? void 0 : resp.headers)}'.`; if (req.reporter) { yield req.reporter.debug(logMessage); } else { aft_core_1.aftLogger.log({ name: this.constructor.name, level: 'trace', message: logMessage }); } return resp; } catch (e) { return Promise.reject(e); } }); } setRequestDefaults(req) { var _a, _b, _c, _d, _e, _f, _g; return __awaiter(this, void 0, void 0, function* () { const hsc = this.aftCfg.getSection(HttpServiceConfig); req !== null && req !== void 0 ? req : (req = {}); (_a = req.url) !== null && _a !== void 0 ? _a : (req.url = hsc.defaultUrl); (_b = req.headers) !== null && _b !== void 0 ? _b : (req.headers = (_c = hsc.defaultHeaders) !== null && _c !== void 0 ? _c : {}); (_d = req.method) !== null && _d !== void 0 ? _d : (req.method = hsc.defaultMethod); (_e = req.allowAutoRedirect) !== null && _e !== void 0 ? _e : (req.allowAutoRedirect = hsc.defaultAllowRedirect); (_f = req.postData) !== null && _f !== void 0 ? _f : (req.postData = hsc.defaultPostData); (_g = req.multipart) !== null && _g !== void 0 ? _g : (req.multipart = hsc.defaultMultipart); return req; }); } _request(r) { return __awaiter(this, void 0, void 0, function* () { return new Promise((resolve, reject) => { try { const client = (r.url.includes('https://')) ? https : http; let req; if (r.multipart) { const form = r.postData; req = client.request(r.url, { headers: form.getHeaders(r.headers), method: r.method }); req = form.pipe(req, { end: true }); } else { req = client.request(r.url, { headers: r.headers, method: r.method }); if (r.postData) { let data; if (typeof r.postData !== "string") { data = JSON.stringify(r.postData); } else { data = r.postData; } req.write(data); } req.end(); // close the request } req === null || req === void 0 ? void 0 : req.on('error', reject); req === null || req === void 0 ? void 0 : req.on('response', resolve); } catch (e) { reject(e); } }); }); } _response(message, allowAutoRedirect = true) { return __awaiter(this, void 0, void 0, function* () { message.setEncoding('utf8'); // handle 302 redirect response if enabled if (message.statusCode == 302 && allowAutoRedirect) { const req = { url: message.headers.location, headers: { 'Cookie': '' } }; for (var header in message.headers) { if (Object.prototype.hasOwnProperty.call(message.headers, header)) { if (header.toLocaleLowerCase() == 'set-cookie') { req.headers['Cookie'] += message.headers[header] + '; '; } } } const redirectedMessage = yield this._request(req); return yield this._response(redirectedMessage, allowAutoRedirect); } else { const response = { statusCode: message.statusCode, headers: message.headers }; yield new Promise((resolve, reject) => { try { message.on('data', (chunk) => { if (!response.data) { response.data = ''; } response.data += chunk; }); message.on('end', resolve); } catch (e) { reject(e); } }); return response; } }); } } exports.HttpService = HttpService; /** * supports performing requests over http / https returning the response as a * `HttpResponse` object. Requests should include a URL at a minimum, * but may also specify additional details such as headers, auto redirect, * post data and the request method (GET|POST|PUT|DELETE|UPDATE) * ex: * ```typescript * await httpService.performRequest({url: 'https://some.domain/path'}); * ``` * or fully as: * ```typescript * await httpService.performRequest({ * url: 'https://some.domain/path', * allowAutoRedirect: false, * headers: {...HttpHeaders.Authorization.basic('myUser', 'myPass')}, * method: 'POST', * postData: someObject, * multipart: false * }); * ``` * or multipart post as: * ```typescript * let formData = new FormData(); * formData.append('file', fs.createReadStream('/path/to/file.ext')); * await httpService.performRequest({ * url: 'https://some.domain/path', * allowAutoRedirect: false, * headers: {...HttpHeaders.Authorization.basic('myUser', 'myPass')} * method: 'POST', * postData: formData, * multipart: true * }); * ``` */ exports.httpService = new HttpService(); //# sourceMappingURL=http-service.js.map