aft-web-services
Version:
Automated Functional Testing (AFT) module for testing web services over HTTP and HTTPS
265 lines • 10.8 kB
JavaScript
;
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