UNPKG

pluto-http-client

Version:

HTTP client for NodeJS. Inspired in the Java JAX-RS spec so you can expect excellence, versatility and extensibility.

225 lines (224 loc) 7.92 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.HttpNodeRequest = exports.Http2NodeRequest = exports.NodeRequest = void 0; const method_1 = require("../method"); const url_1 = require("url"); const https_1 = __importDefault(require("https")); const http_1 = __importDefault(require("http")); const header_1 = require("../header"); const http_headers_1 = require("../http-headers"); const collections_1 = require("../../utils/collections"); const stream_1 = require("stream"); const request_context_1 = require("../request-context"); const http2_1 = require("http2"); const node_response_1 = require("./node-response"); const buffer_1 = require("buffer"); class NodeRequest { constructor(client, url, abortSignal) { this._transformers = []; this._url = url; this._client = client; this._method = method_1.Method.GET; this.headers = this._client.headers; this._abortSignal = abortSignal; } getHeaders() { return (0, http_headers_1.fromMap)(this.headers); } setHeader(key, value) { this.headers.add(new header_1.Header(key, value)); } accept(mediaType) { this.setHeader(http_headers_1.HttpHeaders.ACCEPT, mediaType.toString()); return this; } acceptEncoding(encoding) { this.setHeader(encoding.key, encoding.value); this._client.filters.put(encoding.order(), encoding); return this; } acceptLanguage(locale) { this.setHeader(http_headers_1.HttpHeaders.ACCEPT_LANGUAGE, locale); return this; } build(method, entity) { this._method = method; return this.makeRequest(entity); } cacheControl(cacheControl) { this.setHeader(http_headers_1.HttpHeaders.CACHE_CONTROL, cacheControl.toString()); return this; } cookie(cookie) { this.setHeader(http_headers_1.HttpHeaders.COOKIE, cookie.toString()); return this; } delete(entity) { this._method = method_1.Method.DELETE; return this.makeRequest(entity); } get() { return this.makeRequest(); } header(key, value) { this.setHeader(key, value); return this; } post(entity) { this._method = method_1.Method.POST; return this.makeRequest(entity); } put(entity) { this._method = method_1.Method.PUT; return this.makeRequest(entity); } executePreFilters(request) { for (let filters of this._client.filters.subMap(Number.MIN_SAFE_INTEGER, 0)) { for (const [_, filter] of filters.entries()) { filter.filter(request); } } } executePostFilters(request, response) { for (let filters of this._client.filters.subMap(0, Number.MAX_SAFE_INTEGER)) { for (const [_, filter] of filters.entries()) { filter.filter(request, response); } } } makeRequest(entity) { if (entity) { this.header(http_headers_1.HttpHeaders.CONTENT_TYPE, entity.mediaType.toString()); } return this.execute(entity); } transform(transform) { this._transformers.push(transform); } getUrl() { return this._url; } getMethod() { return this._method; } static writeEntity(entity, sink, transformers, cb) { return entity .marshal() .then((data) => { let bodyStream; if (data instanceof stream_1.Readable) { bodyStream = data; } else if (data instanceof buffer_1.Buffer) { bodyStream = stream_1.Readable.from(data); } else { bodyStream = stream_1.Readable.from(buffer_1.Buffer.from(data)); } (0, stream_1.pipeline)(bodyStream, ...transformers, sink, (error) => { if (error) { cb(error); } }); }); } } exports.NodeRequest = NodeRequest; class Http2NodeRequest extends NodeRequest { constructor(client, url, session, abortSignal, error) { super(client, url, abortSignal); this._req = session; this._responseHeaders = new collections_1.MultiValueMap(); this._error = error; } execute(entity) { if (this._error) { return Promise.reject(this._error); } return new Promise((resolve, reject) => { const requestContext = new request_context_1.RequestContext(this); const headers = (0, http_headers_1.fromMap)(this.headers); headers[http2_1.constants.HTTP2_HEADER_METHOD] = this._method; headers[http2_1.constants.HTTP2_HEADER_PATH] = this.getPath(); const stream = this._req.request(headers, { endStream: !entity, signal: this._abortSignal, }); stream.on("response", (responseHeaders, _flags) => { const response = new node_response_1.NodeResponse(responseHeaders, stream, responseHeaders[":status"]); this.executePostFilters(requestContext, response); resolve(response); }); stream.on("error", (error) => { reject(error); }); stream.on("timeout", () => { stream.destroy(new Error("Client Timeout")); }); this.executePreFilters(requestContext); if (entity) { Http2NodeRequest .writeEntity(entity, stream, this._transformers, reject) .catch(reject); } else { stream.end(); } }); } getPath() { const urlParts = (0, url_1.urlToHttpOptions)(this._url); let path = "/"; if (urlParts.path) { path = urlParts.path; } if (urlParts.search) { path += urlParts.search; } if (urlParts.hash) { path += urlParts.hash; } return path; } } exports.Http2NodeRequest = Http2NodeRequest; class HttpNodeRequest extends NodeRequest { execute(entity) { return new Promise((resolve, reject) => { const requestContext = new request_context_1.RequestContext(this); const lib = this._url.protocol === 'https:' ? https_1.default : http_1.default; this.req = lib.request(this._url, { timeout: this._client.timeout, headers: (0, http_headers_1.fromMap)(this.headers), method: this._method, agent: this._client.agent, rejectUnauthorized: !this._client.allowInsecure, signal: this._abortSignal, }, (response) => { const nodeResponse = new node_response_1.NodeResponse(response.headers, response, response.statusCode); this.executePostFilters(requestContext, nodeResponse); resolve(nodeResponse); }); this.req.once('timeout', () => { var _a; (_a = this.req) === null || _a === void 0 ? void 0 : _a.destroy(new Error("Client timeout")); }); this.req.once('error', (error) => { reject(error); }); this.executePreFilters(requestContext); if (entity) { HttpNodeRequest .writeEntity(entity, this.req, this._transformers, reject) .catch(reject); } else { this.req.end(); } }); } } exports.HttpNodeRequest = HttpNodeRequest;