"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.rootsMiddleware = exports.roots = void 0;
const config_1 = require("./config");
const misc_1 = require("./misc");
const connections_1 = require("./connections");
const listen_1 = require("./listen");
const lodash_1 = __importDefault(require("lodash"));
exports.roots = (0, config_1.defineConfig)(misc_1.CFG.roots, {}, map => {
    const list = Object.keys(map);
    const matchers = list.map(hostMask => (0, misc_1.makeMatcher)(hostMask));
    const values = Object.values(map).map(x => (0, misc_1.enforceFinal)('/', (0, misc_1.enforceStarting)('/', x.replace(/\/{2,}/g, '/'))));
    return (host) => values[matchers.findIndex(m => m(host))];
});
const forceAddress = (0, config_1.defineConfig)(misc_1.CFG.force_address, false);
const rootsMiddleware = (ctx, next) => (() => {
    if (!ctx.path) // it was once reported "Cannot read properties of null (reading 'startsWith')" but I can't reproduce it, and it shouldn't happen anyway
        return (0, connections_1.disconnect)(ctx, 'no path'); // let's assume that such requests can't be served anyway. This will leave a trace with an ip, anyway
    ctx.state.originalPath = ctx.path;
    let params; // undefined if we are not going to work on api parameters
    if (ctx.path.startsWith(misc_1.SPECIAL_URI)) { // special uris should be excluded...
        if (!ctx.path.startsWith(misc_1.API_URI))
            return; // ...unless it's an api
        params = ctx.state.params || ctx.query; // for api we'll translate params
        changeUriParams(v => (0, misc_1.removeStarting)(ctx.state.revProxyPath, v)); // this removal must be done before adding the root; this operation doesn't conceptually belong to "roots", and it may be placed in different middleware, but it's convenient to do it here
        const { referer } = ctx.headers;
        if (referer && (0, misc_1.try_)(() => new URL(referer).pathname.startsWith(ctx.state.revProxyPath + misc_1.ADMIN_URI)))
            return; // exclude apis for admin-panel
    }
    if (lodash_1.default.isEmpty(exports.roots.get()))
        return;
    const root = ctx.state.root = exports.roots.compiled()(ctx.host);
    if (!ctx.state.skipFilters && forceAddress.get()
        && root === undefined && !(0, misc_1.isLocalHost)(ctx) && ctx.host !== listen_1.baseUrl.compiled())
        return (0, connections_1.disconnect)(ctx, forceAddress.key()); // returning truthy will not call next
    if (!root || root === '/')
        return; // no transformation is required
    changeUriParams(v => (0, misc_1.join)(root, v));
    if (!params)
        ctx.path = (0, misc_1.join)(root, ctx.path);
    function changeUriParams(cb) {
        if (!params)
            return;
        for (const [k, v] of Object.entries(params))
            if (k.startsWith('uri'))
                params[k] = Array.isArray(v) ? v.map(cb) : lodash_1.default.isString(v) ? cb(v) : v;
    }
})() || next();
exports.rootsMiddleware = rootsMiddleware;
