"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    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) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
const node_fetch_1 = require("node-fetch");
const url_1 = require("url");
const envoy_context_1 = require("./envoy-context");
/**
 * the fetch function share most of the signature of the original node-fetch
 * but helps you on setting up the request being send to envoy egress port
 * @param envoyParams the params of envoy context as well as request control params (timeout / retry, etc)
 * @param url the target url, the same as node-fetch's first param
 * @param init the init, the same as node-fetch's second param
 */
function envoyFetch(envoyParams, url, init) {
    return __awaiter(this, void 0, void 0, function* () {
        const { protocol, host, path } = url_1.parse(url);
        if (!protocol || !host || !path) {
            throw new Error("Cannot read the URL for envoy to fetch");
        }
        const callDirectly = envoyParams.context.shouldCallWithoutEnvoy(host);
        if (protocol !== "http:" && protocol !== "https:" && !callDirectly) {
            throw new Error(`envoy fetch is designed only for http / https for now, current found: ${url}`);
        }
        const refinedInit = Object.assign({}, init);
        const oldHeaders = {};
        Object.assign(oldHeaders, refinedInit.headers);
        refinedInit.headers = Object.assign({}, oldHeaders, envoyParams.assembleRequestHeaders(), { host });
        const actualUrl = callDirectly
            ? url
            : `http://${envoyParams.context.envoyEgressAddr}:${envoyParams.context.envoyEgressPort}${path}`;
        const response = yield node_fetch_1.default(actualUrl, refinedInit);
        const upstreamTimeHeader = response.headers.get(envoy_context_1.X_ENVOY_UPSTREAM_SERVICE_TIME);
        const upstreamServiceTime = upstreamTimeHeader === null ? NaN : parseInt(upstreamTimeHeader, 10);
        /* tslint:disable:prefer-object-spread */
        const envoyResponse = Object.assign(response, {
            overloaded: response.headers.has(envoy_context_1.X_ENVOY_OVERLOADED),
            upstreamServiceTime
        });
        /* tslint:enable:prefer-object-spread */
        return envoyResponse;
    });
}
exports.default = envoyFetch;
//# sourceMappingURL=envoy-fetch.js.map