"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
/**
 * Library for proxying requests to origins. Use this to create `fetch` like functions
 *  for making requests to other services. For example:
 *
 * ```javascript
 * // sends all traffic to an Amazon ELB,
 * // `Host` header passes through from visitor request
 * const origin = proxy("https://elb1298.amazonaws.com")
 * ```
 *
 * By default, this function sends the `Host` header inferred from the origin URL. To forward
 * host headers sent by visitors, set `forwardHostHeader` to true.
 *
 * ```javascript
 * // sends all traffic to an Amazon ELB, include host header from original request.
 * const origin = proxy("https://elb1298.amazonaws.com", {
 *  forwardHostHeader: true
 * })
 * ```
 *
 * And then way more rare, no host header at all. Usually you'd strip out `x-forwarded-host`,
 * since some origins don't like that:
 * ```javascript
 * // sends all traffic to an Amazon ELB, never sends a host header
 * const origin = proxy("https://elb1298.amazonaws.com", {
 *  headers: { host: false}
 * })
 * ```
 *
 * @preferred
 * @module fly/fetch/proxy
 */
const _1 = require(".");
/**
 * This generates a `fetch` like function for proxying requests to a given origin.
 * When this function makes origin requests, it adds standard proxy headers like
 * `X-Forwarded-Host` and `X-Forwarded-For`. It also passes headers from the original
 * request to the origin.
 * @param origin A URL to an origin, can include a path to rebase requests.
 * @param options Options and headers to control origin request.
 */
function proxy(origin, options) {
    return function proxyFetch(req, init) {
        if (!options) {
            options = {};
        }
        const breq = buildProxyRequest(origin, options, req, init);
        return fetch(breq);
    };
}
exports.proxy = proxy;
exports.default = proxy;
/**
 * @protected
 * @hidden
 * @param origin
 * @param options
 * @param req
 * @param init
 */
function buildProxyRequest(origin, options, r, init) {
    let req = _1.normalizeRequest(r);
    const url = new URL(req.url);
    let breq = null;
    breq = req.clone();
    if (typeof origin === "string") {
        origin = new URL(origin);
    }
    const requestedHostname = req.headers.get("host") || url.hostname;
    url.hostname = origin.hostname;
    url.protocol = origin.protocol;
    url.port = origin.port;
    if (options.stripPath && typeof options.stripPath === 'string') {
        // remove basePath so we can serve `onehosthame.com/dir/` from `origin.com/`
        url.pathname = url.pathname.substring(options.stripPath.length);
    }
    if (origin.pathname && origin.pathname.length > 0) {
        url.pathname = [origin.pathname.replace(/\/$/, ''), url.pathname.replace(/^\//, "")].join("/");
    }
    if (url.pathname.startsWith("//")) {
        url.pathname = url.pathname.substring(1);
    }
    if (url.toString() != breq.url) {
        breq = new Request(url.toString(), breq);
    }
    // we extend req with remoteAddr
    breq.headers.set("x-forwarded-for", req.remoteAddr);
    breq.headers.set("x-forwarded-host", requestedHostname);
    breq.headers.set("x-forwarded-proto", url.protocol.replace(":", ""));
    if (!options.forwardHostHeader) {
        // set host header to origin.hostnames
        breq.headers.set("host", origin.hostname);
    }
    if (options.headers) {
        for (const h of Object.getOwnPropertyNames(options.headers)) {
            const v = options.headers[h];
            if (v === false) {
                breq.headers.delete(h);
            }
            else if (v && typeof v === "string") {
                breq.headers.set(h, v);
            }
        }
    }
    return breq;
}
exports.buildProxyRequest = buildProxyRequest;
//# sourceMappingURL=proxy.js.map