CacheManager::ParseUrl(const AnyP::Uri &uri)
{
    Parser::Tokenizer tok(uri.path());

    static const SBuf internalMagicPrefix("/squid-internal-mgr/");
    if (!tok.skip(internalMagicPrefix) && !tok.skip('/'))
        throw TextException("invalid URL path", Here());

    Mgr::Command::Pointer cmd = new Mgr::Command();
    cmd->params.httpUri = SBufToString(uri.absolute());

    const auto &fieldChars = MgrFieldChars(uri.getScheme());

    SBuf action;
    if (!tok.prefix(action, fieldChars)) {
        if (uri.getScheme() == AnyP::PROTO_CACHE_OBJECT) {
            static const SBuf menuReport("menu");
            action = menuReport;
        } else {
            static const SBuf indexReport("index");
            action = indexReport;
        }
    }
    cmd->params.actionName = SBufToString(action);

    const auto profile = findAction(action.c_str());
    if (!profile)
        throw TextException(ToSBuf("action '", action, "' not found"), Here());

    const char *prot = ActionProtection(profile);
    if (!strcmp(prot, "disabled") || !strcmp(prot, "hidden"))
        throw TextException(ToSBuf("action '", action, "' is ", prot), Here());
    cmd->profile = profile;

    SBuf passwd;
    if (uri.getScheme() == AnyP::PROTO_CACHE_OBJECT && tok.skip('@')) {
        (void)tok.prefix(passwd, fieldChars);
        cmd->params.password = SBufToString(passwd);
    }

    // TODO: fix when AnyP::Uri::parse() separates path?query#fragment
    SBuf params;
    if (tok.skip('?')) {
        params = tok.remaining();
        Mgr::QueryParams::Parse(tok, cmd->params.queryParams);
    }

    if (!tok.skip('#') && !tok.atEnd())
        throw TextException("invalid characters in URL", Here());
    // else ignore #fragment (if any)

    debugs(16, 3, "MGR request: host=" << uri.host() << ", action=" << action <<
           ", password=" << passwd << ", params=" << params);

    return cmd;
}
CacheManager::ParseUrl(const AnyP::Uri &uri)
{
    Parser::Tokenizer tok(uri.path());

    static const SBuf internalMagicPrefix("/squid-internal-mgr/");
    if (!tok.skip(internalMagicPrefix) && !tok.skip('/'))
        throw TextException("invalid URL path", Here());

    Mgr::Command::Pointer cmd = new Mgr::Command();
    cmd->params.httpUri = SBufToString(uri.absolute());

    const auto &fieldChars = MgrFieldChars(uri.getScheme());

    SBuf action;
    if (!tok.prefix(action, fieldChars)) {
        if (uri.getScheme() == AnyP::PROTO_CACHE_OBJECT) {
            static const SBuf menuReport("menu");
            action = menuReport;
        } else {
            static const SBuf indexReport("index");
            action = indexReport;
        }
    }
    cmd->params.actionName = SBufToString(action);

    const auto profile = findAction(action.c_str());
    if (!profile)
        throw TextException(ToSBuf("action '", action, "' not found"), Here());

    const char *prot = ActionProtection(profile);
    if (!strcmp(prot, "disabled") || !strcmp(prot, "hidden"))
        throw TextException(ToSBuf("action '", action, "' is ", prot), Here());
    cmd->profile = profile;

    SBuf passwd;
    if (uri.getScheme() == AnyP::PROTO_CACHE_OBJECT && tok.skip('@')) {
        (void)tok.prefix(passwd, fieldChars);
        cmd->params.password = SBufToString(passwd);
    }

     
    SBuf params;
    if (tok.skip('?')) {
        params = tok.remaining();
        Mgr::QueryParams::Parse(tok, cmd->params.queryParams);
    }

    if (!tok.skip('#') && !tok.atEnd())
        throw TextException("invalid characters in URL", Here());
     

    debugs(16, 3, "MGR request: host=" << uri.host() << ", action=" << action <<
           ", password=" << passwd << ", params=" << params);

    return cmd;
}