/*
  Licensed to the Apache Software Foundation (ASF) under one
  or more contributor license agreements.  See the NOTICE file
  distributed with this work for additional information
  regarding copyright ownership.  The ASF licenses this file
  to you under the Apache License, Version 2.0 (the
  "License"); you may not use this file except in compliance
  with the License.  You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
*/

/**
 * @file cachekey.cc
 * @brief Cache key manipulation.
 */

#include <cstring> /* strlen() */
#include <sstream> /* istringstream */
#include <utility>
#include "cachekey.h"

static void
append(String &target, unsigned n)
{
  char buf[sizeof("4294967295")];
  snprintf(buf, sizeof(buf), "%u", n);
  target.append(buf);
}

static void
appendEncoded(String &target, const char *s, size_t len)
{
  if (0 == len) {
    return;
  }

  char tmp[len * 2];
  size_t written;

  /* The default table does not encode the comma, so we need to use our own table here. */
  static const unsigned char map[32] = {
    0xFF, 0xFF, 0xFF,
    0xFF,       // control
    0xB4,       // space " # %
    0x08,       // ,
    0x00,       //
    0x0A,       // < >
    0x00, 0x00, //
    0x00,       //
    0x1E, 0x80, // [ \ ] ^ `
    0x00, 0x00, //
    0x1F,       // { | } ~ DEL
    0x00, 0x00, 0x00,
    0x00, // all non-ascii characters unmodified
    0x00, 0x00, 0x00,
    0x00, //               .
    0x00, 0x00, 0x00,
    0x00, //               .
    0x00, 0x00, 0x00,
    0x00 //               .
  };

  if (TSStringPercentEncode(s, len, tmp, sizeof(tmp), &written, map) == TS_SUCCESS) {
    target.append(tmp, written);
  } else {
    /* If the encoding fails (pretty unlikely), then just append what we have.
     * This is just a best-effort encoding anyway. */
    target.append(s, len);
  }
}

template <typename ContainerType, typename Iterator>
static String
containerToString(ContainerType &c, const String &sdelim, const String &delim)
{
  String result;
  for (Iterator arg(c.begin()); arg != c.end(); ++arg) {
    result.append(arg == c.begin() ? sdelim : delim);
    result.append(*arg);
  }
  return result;
}

static void
appendToContainer(StringSet &c, const String &s)
{
  c.insert(s);
}

static void
appendToContainer(StringList &c, const String &s)
{
  c.push_back(s);
}

template <typename T>
static String
getKeyQuery(const char *query, int length, const ConfigQuery &config)
{
  std::istringstream istr(String(query, length));
  String token;
  T container;

  while (std::getline(istr, token, '&')) {
    String::size_type pos(token.find_first_of('='));
    String param(token.substr(0, pos == String::npos ? token.size() : pos));

    if (config.toBeAdded(param)) {
      ::appendToContainer(container, token);
    }
  }

  return containerToString<T, typename T::const_iterator>(container, "?", "&");
}

static void
ltrim(String &target)
{
  String::size_type p(target.find_first_not_of(' '));

  if (p != target.npos) {
    target.erase(0, p);
  }
}

static TSMLoc
nextDuplicate(TSMBuffer buffer, TSMLoc hdr, TSMLoc field)
{
  TSMLoc next = TSMimeHdrFieldNextDup(buffer, hdr, field);
  TSHandleMLocRelease(buffer, hdr, field);
  return next;
}

/**
 * @brief Iterates through all User-Agent headers and fields and classifies them using provided classifier.
 * @param c classifier
 * @param buf marshal buffer from the request
 * @param hdrs headers handle from the request
 * @param classname reference to the string where the class name will be returned
 */
static bool
classifyUserAgent(const Classifier &c, TSMBuffer buf, TSMLoc hdrs, String &classname)
{
  TSMLoc field;
  bool matched = false;

  field = TSMimeHdrFieldFind(buf, hdrs, TS_MIME_FIELD_USER_AGENT, TS_MIME_LEN_USER_AGENT);
  while (field != TS_NULL_MLOC && !matched) {
    const char *value;
    int len;
    int count = TSMimeHdrFieldValuesCount(buf, hdrs, field);

    for (int i = 0; i < count; ++i) {
      value = TSMimeHdrFieldValueStringGet(buf, hdrs, field, i, &len);
      const String val(value, len);
      if (c.classify(val, classname)) {
        matched = true;
        break;
      }
    }

    field = ::nextDuplicate(buf, hdrs, field);
  }

  TSHandleMLocRelease(buf, hdrs, field);
  return matched;
}

static String
getUri(TSMBuffer buf, TSMLoc url)
{
  String uri;
  int uriLen;
  const char *uriPtr = TSUrlStringGet(buf, url, &uriLen);
  if (nullptr != uriPtr && 0 != uriLen) {
    uri.assign(uriPtr, uriLen);
    TSfree((void *)uriPtr);
  } else {
    CacheKeyError("failed to get URI");
  }
  return uri;
}

static String
getCanonicalUrl(TSMBuffer buf, TSMLoc url, bool canonicalPrefix, bool provideDefaultKey)
{
  String canonicalUrl;

  String scheme;
  int schemeLen;
  const char *schemePtr = TSUrlSchemeGet(buf, url, &schemeLen);
  if (nullptr != schemePtr && 0 != schemeLen) {
    scheme.assign(schemePtr, schemeLen);
  } else {
    CacheKeyError("failed to get scheme");
    return canonicalUrl;
  }

  String host;
  int hostLen;
  const char *hostPtr = TSUrlHostGet(buf, url, &hostLen);
  if (nullptr != hostPtr && 0 != hostLen) {
    host.assign(hostPtr, hostLen);
  } else {
    CacheKeyError("failed to get host");
    return canonicalUrl;
  }

  String port;
  int portInt = TSUrlPortGet(buf, url);
  ::append(port, portInt);

  if (canonicalPrefix) {
    /* return the same for both regex input or default key, results in 'scheme://host:port' */
    canonicalUrl.assign(scheme).append("://").append(host).append(":").append(port);
  } else {
    if (provideDefaultKey) {
      /* return the key default - results in '/host/port' */
      canonicalUrl.assign("/").append(host).append("/").append(port);
    } else {
      /* return regex input string - results in 'host:port' (use-case kept for compatibility reasons) */
      canonicalUrl.assign(host).append(":").append(port);
    }
  }

  return canonicalUrl;
}

/**
 * @brief Constructor setting up the cache key prefix, initializing request info.
 * @param txn transaction handle.
 * @param separator cache key elements separator
 * @param uriType type of the URI used to create the cachekey ("remap" or "pristine")
 * @param rri remap request info
 */
CacheKey::CacheKey(TSHttpTxn txn, String separator, CacheKeyUriType uriType, CacheKeyKeyType keyType, TSRemapRequestInfo *rri)
  : _txn(txn), _separator(std::move(separator)), _uriType(uriType), _keyType(keyType)
{
  _key.reserve(512);

  _remap = (nullptr != rri);

  /* Get the URI and header to base the cachekey on.
   * @TODO it might make sense to add more supported URI types */

  CacheKeyDebug("setting %s from a %s plugin", getCacheKeyKeyTypeName(_keyType), _remap ? "remap" : "global");

  if (_remap) {
    if (PRISTINE == _uriType) {
      if (TS_SUCCESS != TSHttpTxnPristineUrlGet(_txn, &_buf, &_url)) {
        /* Failing here is unlikely. No action seems the only reasonable thing to do from within this plug-in */
        CacheKeyError("failed to get pristine URI handle");
        return;
      }
      CacheKeyDebug("using pristine uri '%s'", getUri(_buf, _url).c_str());
    } else {
      _buf = rri->requestBufp;
      _url = rri->requestUrl;
      CacheKeyDebug("using remap uri '%s'", getUri(_buf, _url).c_str());
    }
    _hdrs = rri->requestHdrp;
  } else {
    if (TS_SUCCESS != TSHttpTxnClientReqGet(_txn, &_buf, &_hdrs)) {
      /* Failing here is unlikely. No action seems the only reasonable thing to do from within this plug-in */
      CacheKeyError("failed to get client request handle");
      return;
    }

    if (PRISTINE == _uriType) {
      if (TS_SUCCESS != TSHttpTxnPristineUrlGet(_txn, &_buf, &_url)) {
        TSHandleMLocRelease(_buf, TS_NULL_MLOC, _hdrs);
        CacheKeyError("failed to get pristine URI handle");
        return;
      }
      CacheKeyDebug("using pristine uri '%s'", getUri(_buf, _url).c_str());
    } else {
      if (TS_SUCCESS != TSHttpHdrUrlGet(_buf, _hdrs, &_url)) {
        TSHandleMLocRelease(_buf, TS_NULL_MLOC, _hdrs);
        CacheKeyError("failed to get URI handle");
        return;
      }
      CacheKeyDebug("using post-remap uri '%s','", getUri(_buf, _url).c_str());
    }
  }
  _valid = true; /* success, we got all necessary elements - URI, headers, etc. */
}

CacheKey::~CacheKey()
{
  if (_valid) {
    /* free resources only if valid, if not valid it is assumed nothing was allocated or was freed */
    if (_remap) {
      /* _buf and _hdrs are assigned from remap info - no need to release here. */
      if (PRISTINE == _uriType) {
        if (TS_SUCCESS != TSHandleMLocRelease(_buf, TS_NULL_MLOC, _url)) {
          CacheKeyError("failed to release pristine URI handle");
        }
      }
    } else {
      if (TS_SUCCESS != TSHandleMLocRelease(_buf, TS_NULL_MLOC, _hdrs) &&
          TS_SUCCESS != TSHandleMLocRelease(_buf, TS_NULL_MLOC, _url)) {
        CacheKeyError("failed to release URI and headers handle");
      }
    }
  }
}

/**
 * @brief Append unsigned integer to the key.
 * @param number unsigned integer
 */
void
CacheKey::append(unsigned n)
{
  _key.append(_separator);
  ::append(_key, n);
}

/**
 * @brief Append a string to the key.
 * @param s string
 */
void
CacheKey::append(const String &s)
{
  _key.append(_separator);
  ::appendEncoded(_key, s.data(), s.size());
}

void
CacheKey::append(const String &s, bool useSeparator)
{
  if (useSeparator) {
    append(s);
  } else {
    _key.append(s);
  }
}

/**
 * @brief Append null-terminated C-style string to the key.
 * @param s null-terminated C-style string.
 */
void
CacheKey::append(const char *s)
{
  _key.append(_separator);
  ::appendEncoded(_key, s, strlen(s));
}

/**
 * @brief Append first n characters from array if characters pointed by s.
 * @param n number of characters
 * @param s character array pointer
 */
void
CacheKey::append(const char *s, unsigned n)
{
  _key.append(_separator);
  ::appendEncoded(_key, s, n);
}

/**
 * @brief Append to the cache key a custom prefix, capture from hots:port, capture from URI or default to host:port part of the
 * URI.
 * @note This is the only cache key component from the key which is always available.
 * @param prefix if not empty string will append the static prefix to the cache key.
 * @param prefixCapture if not empty will append regex capture/replacement from the host:port.
 * @param prefixCaptureUri if not empty will append regex capture/replacement from the whole URI.
 * @param canonicalPrefix false - use 'host:port' as starting point of all transformations, true - use 'scheme://host:port'
 * @note if both prefix and pattern are not empty prefix will be added first, followed by the results from pattern.
 */
void
CacheKey::appendPrefix(const String &prefix, Pattern &prefixCapture, Pattern &prefixCaptureUri, bool canonicalPrefix)
{
  // "true" would mean that the plugin config meant to override the default prefix, "false" means use default.
  bool customPrefix = false;

  /* For all the following operations if a canonical prefix is required then appned to the key with no separator
   * to leave the door open for potential valid host name formed in the final resulting cache key. */

  if (!prefix.empty()) {
    customPrefix = true;
    append(prefix, /* useSeparator */ !canonicalPrefix);
    CacheKeyDebug("added static prefix, key: '%s'", _key.c_str());
  }

  if (!prefixCapture.empty()) {
    customPrefix = true;

    StringVector captures;
    if (prefixCapture.process(getCanonicalUrl(_buf, _url, canonicalPrefix, /* provideDefaultKey */ false), captures)) {
      for (auto &capture : captures) {
        append(capture, /* useSeparator */ !canonicalPrefix);
      }
      CacheKeyDebug("added host:port capture prefix, key: '%s'", _key.c_str());
    }
  }

  if (!prefixCaptureUri.empty()) {
    customPrefix = true;

    String uri = getUri(_buf, _url);
    if (!uri.empty()) {
      StringVector captures;
      if (prefixCaptureUri.process(uri, captures)) {
        for (auto &capture : captures) {
          append(capture, /* useSeparator */ !canonicalPrefix);
        }
        CacheKeyDebug("added URI capture prefix, key: '%s'", _key.c_str());
      }
    }
  }

  if (!customPrefix) {
    /* nothing was customized => default prefix */
    append(getCanonicalUrl(_buf, _url, canonicalPrefix, /* provideDefaultKey */ true), /* useSeparator */ false);
    CacheKeyDebug("added default prefix, key: '%s'", _key.c_str());
  }
}

/**
 * @brief Appends to the cache key the path from the URI (default), regex capture/replacement from the URI path,
 * regex capture/replacement from URI as whole.
 * @note A path is always defined for a URI, though the defined path may be empty (zero length) (RFC 3986)
 * @param pathCapture if not empty will append regex capture/replacement from the URI path
 * @param pathCaptureUri if not empty will append regex capture/replacement from the URI as a whole
 * @todo enhance, i.e. /<regex>/<replace>/
 */
void
CacheKey::appendPath(Pattern &pathCapture, Pattern &pathCaptureUri)
{
  // "true" would mean that the plugin config meant to override the default path.
  bool customPath = false;
  String path;

  int pathLen;
  const char *pathPtr = TSUrlPathGet(_buf, _url, &pathLen);
  if (nullptr != pathPtr && 0 != pathLen) {
    path.assign(pathPtr, pathLen);
  }

  if (!pathCaptureUri.empty()) {
    customPath = true;

    String uri = getUri(_buf, _url);
    if (!uri.empty()) {
      StringVector captures;
      if (pathCaptureUri.process(uri, captures)) {
        for (auto &capture : captures) {
          append(capture);
        }
        CacheKeyDebug("added URI capture (path), key: '%s'", _key.c_str());
      }
    }
  }

  if (!pathCapture.empty()) {
    customPath = true;

    // If path is empty don't even try to capture/replace.
    if (!path.empty()) {
      StringVector captures;
      if (pathCapture.process(path, captures)) {
        for (auto &capture : captures) {
          append(capture);
        }
        CacheKeyDebug("added path capture, key: '%s'", _key.c_str());
      }
    }
  }

  if (!customPath && !path.empty()) {
    append(path);
  }
}

template <class T>
void
CacheKey::processHeader(const String &name, const ConfigHeaders &config, T &dst,
                        void (*fun)(const ConfigHeaders &config, const String &name_s, const String &value_s, T &captures))
{
  TSMLoc field;

  for (field = TSMimeHdrFieldFind(_buf, _hdrs, name.c_str(), name.size()); field != TS_NULL_MLOC;
       field = ::nextDuplicate(_buf, _hdrs, field)) {
    const char *value;
    int vlen;
    int count = TSMimeHdrFieldValuesCount(_buf, _hdrs, field);

    for (int i = 0; i < count; ++i) {
      value = TSMimeHdrFieldValueStringGet(_buf, _hdrs, field, i, &vlen);
      if (value == nullptr || vlen == 0) {
        CacheKeyDebug("missing value %d for header %s", i, name.c_str());
        continue;
      }

      String value_s(value, vlen);
      fun(config, name, value_s, dst);
    }
  }
}

template <class T>
void
captureWholeHeaders(const ConfigHeaders &config, const String &name, const String &value, T &captures)
{
  CacheKeyDebug("processing header %s", name.c_str());
  if (config.toBeAdded(name)) {
    String header;
    header.append(name).append(":").append(value);
    captures.insert(header);
    CacheKeyDebug("adding header '%s: %s'", name.c_str(), value.c_str());
  } else {
    CacheKeyDebug("failed to find header '%s'", name.c_str());
  }
}

template <class T>
void
captureFromHeaders(const ConfigHeaders &config, const String &name, const String &value, T &captures)
{
  CacheKeyDebug("processing capture from header %s", name.c_str());
  auto itMp = config.getCaptures().find(name);
  if (config.getCaptures().end() != itMp) {
    itMp->second->process(value, captures);
    CacheKeyDebug("found capture pattern for header '%s'", name.c_str());
  } else {
    CacheKeyDebug("failed to find header '%s'", name.c_str());
  }
}

/**
 * @brief Append headers by following the rules specified in the header configuration object.
 * @param config header-related configuration containing information about which headers need to be appended to the key.
 * @note Add the headers to hier-part (RFC 3986), always sort them in the cache key.
 */
void
CacheKey::appendHeaders(const ConfigHeaders &config)
{
  if (!config.toBeRemoved() && !config.toBeSkipped()) {
    /* Iterating header by header is not efficient according to comments inside traffic server API,
     * Iterate over an 'include'-kind of list or the capture definitions to avoid header by header iteration.
     * @todo: revisit this when (if?) adding regex matching for headers. */

    /* Adding whole headers, iterate over "--include-header" list */
    StringSet hdrSet; /* Sort and uniquify the header list in the cache key. */
    for (auto it = config.getInclude().begin(); it != config.getInclude().end(); ++it) {
      processHeader(*it, config, hdrSet, captureWholeHeaders);
    }

    /* Append to the cache key. It doesn't make sense to have the headers unordered in the cache key. */
    String headers_key = containerToString<StringSet, StringSet::const_iterator>(hdrSet, "", _separator);
    if (!headers_key.empty()) {
      append(headers_key);
    }
  }

  if (!config.getCaptures().empty()) {
    /* Adding captures from headers, iterate over "--capture-header" definitions */
    StringVector hdrCaptures;
    for (auto it = config.getCaptures().begin(); it != config.getCaptures().end(); ++it) {
      processHeader(it->first, config, hdrCaptures, captureFromHeaders);
    }

    /* Append to the cache key. Add the captures in the order capture definitions are captured / specified */
    for (auto &capture : hdrCaptures) {
      append(capture);
    }
  }
}

/**
 * @brief Append cookies by following the rules specified in the cookies config object.
 * @param config cookies-related configuration containing information about which cookies need to be appended to the key.
 * @note Add the cookies to "hier-part" (RFC 3986), always sort them in the cache key.
 */
void
CacheKey::appendCookies(const ConfigCookies &config)
{
  if (config.toBeRemoved() || config.toBeSkipped()) {
    /* Don't append any cookies to the cache key. */
    return;
  }

  TSMLoc field;
  StringSet cset; /* sort and uniquify the cookies list in the cache key */

  for (field = TSMimeHdrFieldFind(_buf, _hdrs, TS_MIME_FIELD_COOKIE, TS_MIME_LEN_COOKIE); field != TS_NULL_MLOC;
       field = ::nextDuplicate(_buf, _hdrs, field)) {
    int count = TSMimeHdrFieldValuesCount(_buf, _hdrs, field);

    for (int i = 0; i < count; ++i) {
      const char *value;
      int len;

      value = TSMimeHdrFieldValueStringGet(_buf, _hdrs, field, i, &len);
      if (value == nullptr || len == 0) {
        continue;
      }

      std::istringstream istr(String(value, len));
      String cookie;

      while (std::getline(istr, cookie, ';')) {
        ::ltrim(cookie); // Trim leading spaces.

        String::size_type pos(cookie.find_first_of('='));
        String name(cookie.substr(0, pos == String::npos ? cookie.size() : pos));

        /* We only add it to the cache key it is in the cookie set. */
        if (config.toBeAdded(name)) {
          cset.insert(cookie);
        }
      }
    }
  }

  /* We are iterating over the cookies in client order,
   * but the cache key needs a stable ordering, so we sort via std::set. */
  String cookies_keys = containerToString<StringSet, StringSet::const_iterator>(cset, "", ";");
  if (!cookies_keys.empty()) {
    append(cookies_keys);
  }
}

/**
 * @brief Append query parameters by following the rules specified in the query configuration object.
 * @param config query configuration containing information about which query parameters need to be appended to the key.
 * @note Keep the query parameters in the "query part" (RFC 3986).
 */
void
CacheKey::appendQuery(const ConfigQuery &config)
{
  /* No query parameters in the cache key? */
  if (config.toBeRemoved()) {
    return;
  }

  const char *query;
  int length;

  query = TSUrlHttpQueryGet(_buf, _url, &length);
  if (query == nullptr || length == 0) {
    return;
  }

  /* If need to skip all other rules just append the whole query to the key. */
  if (config.toBeSkipped()) {
    _key.append("?");
    _key.append(query, length);
    return;
  }

  /* Use the corresponding container based on whether we need
   * to sort the parameters (set) or keep the order (list) */
  String keyQuery;
  if (config.toBeSorted()) {
    keyQuery = getKeyQuery<StringSet>(query, length, config);
  } else {
    keyQuery = getKeyQuery<StringList>(query, length, config);
  }

  if (!keyQuery.empty()) {
    _key.append(keyQuery);
  }
}

/**
 * @brief Append User-Agent header captures specified in the Pattern configuration object.
 *
 * Apply given PCRE pattern/replacement to the first User-Agent value, and append any captured portions to cache key.
 * @param config PCRE pattern which contains capture groups.
 * @todo: TBD if ignoring the comma in the header as a field separator is generic enough.
 * @note Add the UA captures to hier-part (RFC 3986) in the original order.
 */
void
CacheKey::appendUaCaptures(Pattern &config)
{
  if (config.empty()) {
    return;
  }

  TSMLoc field;
  const char *value;
  int len;

  field = TSMimeHdrFieldFind(_buf, _hdrs, TS_MIME_FIELD_USER_AGENT, TS_MIME_LEN_USER_AGENT);
  if (field == TS_NULL_MLOC) {
    CacheKeyDebug("missing %.*s header", TS_MIME_LEN_USER_AGENT, TS_MIME_FIELD_USER_AGENT);
    return;
  }

  /* Now, strictly speaking, the User-Agent header should not contain a comma,
   * because that's really a field separator (RFC 2616). Unfortunately, the
   * iOS apps will send an embedded comma and we have to deal with it as if
   * it was a single header. */
  value = TSMimeHdrFieldValueStringGet(_buf, _hdrs, field, -1, &len);
  if (value && len) {
    String val(value, len);
    StringVector captures;

    if (config.process(val, captures)) {
      for (auto &capture : captures) {
        append(capture);
      }
    }
  }

  TSHandleMLocRelease(_buf, _hdrs, field);
}

/**
 * @brief Append the class name based on the User-Agent classification using the provided classifier.
 * @param classifier User-Agent header classifier which will return a single class name to be added to the key.
 * @return true if classification successful, false if no match was found.
 * @note Add the class to hier-part (RFC 3986).
 */
bool
CacheKey::appendUaClass(Classifier &classifier)
{
  String classname;
  bool matched = ::classifyUserAgent(classifier, _buf, _hdrs, classname);

  if (matched) {
    append(classname);
  } else {
    /* @todo: TBD do we need a default class name to be added to the key? */
  }

  return matched;
}

/**
 * @brief Update cache key.
 * @return true if success, false if failed to set the cache key.
 */
bool
CacheKey::finalize() const
{
  bool res = false;
  String msg;

  CacheKeyDebug("finalizing %s '%s' from a %s plugin", getCacheKeyKeyTypeName(_keyType), _key.c_str(),
                (_remap ? "remap" : "global"));
  switch (_keyType) {
  case CACHE_KEY: {
    if (TS_SUCCESS == TSCacheUrlSet(_txn, &(_key[0]), _key.size())) {
      /* Set cache key succesfully */
      msg.assign("set cache key to ").append(_key);
      res = true;
    } else {
      if (_remap) {
        /* Remap instance. Always runs first by design (before TS_HTTP_POST_REMAP_HOOK) */
        msg.assign("failed to set cache key");
      } else {
        /* Global instance. We would fail and get here if a per-remap instance has already set the cache key
         * (currently TSCacheUrlSet() can be called only once successfully). Don't error, just debug.
         * @todo avoid the consecutive attempts and error only on unexpected failures. */
        msg.assign("failed to set cache key");
      }
    }
  } break;
  case PARENT_SELECTION_URL: {
    /* parent selection */
    const char *start = _key.c_str();
    const char *end   = _key.c_str() + _key.length();
    TSMLoc new_url_loc;
    if (TS_SUCCESS == TSUrlCreate(_buf, &new_url_loc)) {
      if (TS_PARSE_DONE == TSUrlParse(_buf, new_url_loc, &start, end)) {
        if (TS_SUCCESS == TSHttpTxnParentSelectionUrlSet(_txn, _buf, new_url_loc)) {
          msg.assign("set parent selection URL to ").append(_key);
          res = true;
        } else {
          msg.assign("failed to set parent selection URL");
        }
      } else {
        msg.assign("failed to parse parent selection URL");
      }
      TSHandleMLocRelease(_buf, TS_NULL_MLOC, new_url_loc);
    } else {
      msg.assign("failed to create parent selection URL");
    }
  } break;
  default: {
    msg.assign("unknown target URI type");
  } break;
  }

  /* Report status - debug level in case of success, error in case of failure.
   * Since getting effective URI is expensive add it only in case of failure */
  if (res) {
    CacheKeyDebug("%.*s", static_cast<int>(msg.length()), msg.c_str());
  } else {
    int len;
    char *url = TSHttpTxnEffectiveUrlStringGet(_txn, &len);
    if (nullptr != url) {
      msg.append(" for url ").append(url, len);
      TSfree(url);
    }
    CacheKeyError("%.*s", static_cast<int>(msg.length()), msg.c_str());
  }
  return res;
}
