Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 61 additions & 35 deletions plugins/experimental/escalate/escalate.cc
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ struct EscalationState {

typedef std::map<unsigned, RetryInfo> StatusMapType;

EscalationState()
EscalationState() : use_pristine(false)
{
cont = TSContCreate(EscalateResponse, NULL);
TSContDataSet(cont, this);
Expand All @@ -63,9 +63,25 @@ struct EscalationState {

TSCont cont;
StatusMapType status_map;
bool use_pristine;
};


// Little helper function, to update the Host portion of a URL, and stringify the result.
// Returns the URL string, and updates url_len with the length.
char *
MakeEscalateUrl(TSMBuffer mbuf, TSMLoc url, const char *host, size_t host_len, int &url_len)
{
char *url_str = NULL;

// Update the request URL with the new Host to try.
TSUrlHostSet(mbuf, url, host, host_len);
url_str = TSUrlStringGet(mbuf, url, &url_len);
TSDebug(PLUGIN_NAME, "Setting new URL to %.*s", url_len, url_str);

return url_str;
}

//////////////////////////////////////////////////////////////////////////////////////////
// Main continuation for the plugin, examining an origin response for a potential retry.
//
Expand Down Expand Up @@ -110,15 +126,20 @@ EscalateResponse(TSCont cont, TSEvent event, void *edata)
url_len = entry->second.target.size();
TSDebug(PLUGIN_NAME, "Setting new URL to %.*s", url_len, url_str);
} else if (EscalationState::RETRY_HOST == entry->second.type) {
if (TS_SUCCESS == TSHttpTxnClientReqGet(txn, &mbuf, &hdrp)) {
if (TS_SUCCESS == TSHttpHdrUrlGet(mbuf, hdrp, &url)) {
// Update the request URL with the new Host to try.
TSUrlHostSet(mbuf, url, entry->second.target.c_str(), entry->second.target.size());
url_str = TSUrlStringGet(mbuf, url, &url_len);
TSDebug(PLUGIN_NAME, "Setting new Host: to %.*s", url_len, url_str);
if (es->use_pristine) {
if (TS_SUCCESS == TSHttpTxnPristineUrlGet(txn, &mbuf, &url)) {
url_str = MakeEscalateUrl(mbuf, url, entry->second.target.c_str(), entry->second.target.size(), url_len);
printf("STRING is %.*s\n", url_len, url_str);
}
} else {
if (TS_SUCCESS == TSHttpTxnClientReqGet(txn, &mbuf, &hdrp)) {
if (TS_SUCCESS == TSHttpHdrUrlGet(mbuf, hdrp, &url)) {
url_str = MakeEscalateUrl(mbuf, url, entry->second.target.c_str(), entry->second.target.size(), url_len);
printf("Old code STRING is %.*s\n", url_len, url_str);
}
// Release the request MLoc
TSHandleMLocRelease(mbuf, TS_NULL_MLOC, hdrp);
}
// Release the request MLoc
TSHandleMLocRelease(mbuf, TS_NULL_MLOC, hdrp);
}
}

Expand Down Expand Up @@ -151,38 +172,43 @@ TSRemapNewInstance(int argc, char *argv[], void **instance, char *errbuf, int er
for (int i = 2; i < argc; ++i) {
char *sep, *token, *save;

// Each token should be a status code then a URL, separated by ':'.
sep = strchr(argv[i], ':');
if (sep == NULL) {
snprintf(errbuf, errbuf_size, "malformed status:target config: %s", argv[i]);
goto fail;
}
// Ugly, but we set the precedence before with non-command line parsing of args
if (0 == strncasecmp(argv[i], "--pristine", 10)) {
es->use_pristine = true;
} else {
// Each token should be a status code then a URL, separated by ':'.
sep = strchr(argv[i], ':');
if (sep == NULL) {
snprintf(errbuf, errbuf_size, "malformed status:target config: %s", argv[i]);
goto fail;
}

*sep = '\0';
++sep; // Skip over the ':' (which is now \0)
*sep = '\0';
++sep; // Skip over the ':' (which is now \0)

// OK, we have a valid status/URL pair.
EscalationState::RetryInfo info;
// OK, we have a valid status/URL pair.
EscalationState::RetryInfo info;

info.target = sep;
if (std::string::npos != info.target.find('/')) {
info.type = EscalationState::RETRY_URL;
TSDebug(PLUGIN_NAME, "Creating Redirect rule with URL = %s", sep);
} else {
info.type = EscalationState::RETRY_HOST;
TSDebug(PLUGIN_NAME, "Creating Redirect rule with Host = %s", sep);
}
info.target = sep;
if (std::string::npos != info.target.find('/')) {
info.type = EscalationState::RETRY_URL;
TSDebug(PLUGIN_NAME, "Creating Redirect rule with URL = %s", sep);
} else {
info.type = EscalationState::RETRY_HOST;
TSDebug(PLUGIN_NAME, "Creating Redirect rule with Host = %s", sep);
}

for (token = strtok_r(argv[i], ",", &save); token; token = strtok_r(NULL, ",", &save)) {
unsigned status = strtol(token, NULL, 10);
for (token = strtok_r(argv[i], ",", &save); token; token = strtok_r(NULL, ",", &save)) {
unsigned status = strtol(token, NULL, 10);

if (status < 100 || status > 599) {
snprintf(errbuf, errbuf_size, "invalid status code: %.*s", (int)std::distance(argv[i], sep), argv[i]);
goto fail;
}
if (status < 100 || status > 599) {
snprintf(errbuf, errbuf_size, "invalid status code: %.*s", (int)std::distance(argv[i], sep), argv[i]);
goto fail;
}

TSDebug(PLUGIN_NAME, " added status = %d to rule", status);
es->status_map[status] = info;
TSDebug(PLUGIN_NAME, " added status = %d to rule", status);
es->status_map[status] = info;
}
}
}

Expand Down