blob: e29fea204e3ab633974df39486556e3151374b5f [file] [log] [blame]
/** @file
@section license License
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.
*/
#include <arpa/inet.h>
#include <ts.h>
#include <algorithm>
#include "ts-cpp11.h"
#include "ts-cpp11-headers.h"
using namespace ats::api;
TSHttpHookID TSHookIDFromHookType(HookType hook);
class HookContinuationData {
public:
GlobalHookCallback callback;
HookType hooktype;
TSHttpHookID ts_hook_id;
};
class ats::api::Transaction {
public:
TSHttpTxn ts_http_txn_ = NULL;
TSCont ts_contp_ = NULL;
};
extern "C" void TSPluginInit(int argc, const char *argv[]) {
TSPluginRegistrationInfo registration_info;
const char *api_version_string = "cpp11api";
registration_info.plugin_name = const_cast<char*>(api_version_string);
registration_info.vendor_name = const_cast<char*>(api_version_string);
registration_info.support_email = const_cast<char*>(api_version_string);
if (TSPluginRegister(TS_SDK_VERSION_3_0, &registration_info) != TS_SUCCESS) {
return;
}
StringVector arguments;
for (int i = 0; i < argc; ++i) {
arguments.push_back(std::string(argv[i]));
}
// Finally we will call the wrapper API registration point
PluginRegister(arguments);
}
TSHttpHookID TSHookIDFromHookType(HookType hook) {
switch (hook) {
case ats::api::HookType::HOOK_PRE_REMAP:
return TS_HTTP_PRE_REMAP_HOOK;
break;
case ats::api::HookType::HOOK_POST_REMAP:
return TS_HTTP_POST_REMAP_HOOK;
break;
case ats::api::HookType::HOOK_READ_REQUEST_HEADERS:
return TS_HTTP_READ_REQUEST_HDR_HOOK;
break;
case ats::api::HookType::HOOK_READ_RESPONSE_HEADERS:
return TS_HTTP_READ_RESPONSE_HDR_HOOK;
break;
case ats::api::HookType::HOOK_SEND_RESPONSE_HEADERS:
return TS_HTTP_SEND_RESPONSE_HDR_HOOK;
break;
case ats::api::HookType::HOOK_TRANSACTION_START:
return TS_HTTP_TXN_START_HOOK;
break;
case ats::api::HookType::HOOK_TRANSACTION_END:
return TS_HTTP_TXN_CLOSE_HOOK;
break;
}
return TS_HTTP_PRE_REMAP_HOOK;
}
void inline ReenableBasedOnNextState(TSHttpTxn txnp, NextState ns) {
switch (ns) {
case NextState::HTTP_DONT_CONTINUE:
return;
break;
case NextState::HTTP_ERROR:
TSHttpTxnReenable(txnp, static_cast<TSEvent>(TS_EVENT_HTTP_ERROR));
break;
case NextState::HTTP_CONTINUE:
default:
TSHttpTxnReenable(txnp, static_cast<TSEvent>(TS_EVENT_HTTP_CONTINUE));
break;
}
}
std::string printable_sockaddr_ip(sockaddr const * s_sockaddr) {
const struct sockaddr_in * s_sockaddr_in =
reinterpret_cast<const struct sockaddr_in *>(s_sockaddr);
char res[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &s_sockaddr_in->sin_addr, res, INET_ADDRSTRLEN);
return std::string(res);
}
std::string ats::api::GetPristineRequestUrl(Transaction &t) {
TSMBuffer bufp;
TSMLoc url_loc;
if (TSHttpTxnPristineUrlGet(t.ts_http_txn_, &bufp, &url_loc) != TS_SUCCESS)
return std::string();
int url_len;
char *urlp = TSUrlStringGet(bufp, url_loc, &url_len);
std::string url(urlp, url_len);
TSfree(urlp);
TSHandleMLocRelease(bufp, TS_NULL_MLOC, url_loc);
return url;
}
std::string ats::api::GetRequestUrl(Transaction &t) {
TSMBuffer bufp;
TSMLoc hdr_loc;
TSMLoc url_loc;
if (TSHttpTxnClientReqGet(t.ts_http_txn_, &bufp, &hdr_loc) != TS_SUCCESS)
return std::string();
TSHttpHdrUrlGet(bufp, hdr_loc, &url_loc);
int url_len;
char *urlp = TSUrlStringGet(bufp, url_loc, &url_len);
std::string url(urlp, url_len);
TSfree(urlp);
TSHandleMLocRelease(bufp, hdr_loc, url_loc);
TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
return url;
}
std::string ats::api::GetRequestUrlScheme(Transaction &t) {
TSMBuffer bufp;
TSMLoc hdr_loc;
TSMLoc url_loc;
if (TSHttpTxnClientReqGet(t.ts_http_txn_, &bufp, &hdr_loc) != TS_SUCCESS)
return std::string();
TSHttpHdrUrlGet(bufp, hdr_loc, &url_loc);
int scheme_length;
const char *scheme = TSUrlSchemeGet(bufp, url_loc, &scheme_length);
std::string ret(scheme, scheme_length);
TSHandleMLocRelease(bufp, hdr_loc, url_loc);
TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
return ret;
}
std::string ats::api::GetPristineRequestUrlScheme(Transaction &t) {
TSMBuffer bufp;
TSMLoc url_loc;
TSHttpTxnPristineUrlGet(t.ts_http_txn_, &bufp, &url_loc);
int length;
const char *scheme = TSUrlHostGet(bufp, url_loc, &length);
std::string ret(scheme, length);
TSHandleMLocRelease(bufp, TS_NULL_MLOC, url_loc);
return ret;
}
void ats::api::SetRequestUrlScheme(Transaction &t, const std::string &scheme) {
TSMBuffer bufp;
TSMLoc hdr_loc;
TSMLoc url_loc;
TSHttpTxnClientReqGet(t.ts_http_txn_, &bufp, &hdr_loc);
TSHttpHdrUrlGet(bufp, hdr_loc, &url_loc);
TSUrlHostSet(bufp, url_loc, scheme.c_str(), scheme.length());
TSHandleMLocRelease(bufp, hdr_loc, url_loc);
TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
}
std::string ats::api::GetRequestUrlQuery(Transaction &t) {
TSMBuffer bufp;
TSMLoc hdr_loc;
TSMLoc url_loc;
if (TSHttpTxnClientReqGet(t.ts_http_txn_, &bufp, &hdr_loc) != TS_SUCCESS)
return std::string();
TSHttpHdrUrlGet(bufp, hdr_loc, &url_loc);
int query_length;
const char *query = TSUrlHttpQueryGet(bufp, url_loc, &query_length);
std::string ret(query, query_length);
TSHandleMLocRelease(bufp, hdr_loc, url_loc);
TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
return ret;
}
std::string ats::api::GetPristineRequestUrlQuery(Transaction &t) {
TSMBuffer bufp;
TSMLoc url_loc;
TSHttpTxnPristineUrlGet(t.ts_http_txn_, &bufp, &url_loc);
int query_length;
const char *query = TSUrlHostGet(bufp, url_loc, &query_length);
std::string ret(query, query_length);
TSHandleMLocRelease(bufp, TS_NULL_MLOC, url_loc);
return ret;
}
void ats::api::SetRequestUrlQuery(Transaction &t, const std::string &query) {
TSMBuffer bufp;
TSMLoc hdr_loc;
TSMLoc url_loc;
TSHttpTxnClientReqGet(t.ts_http_txn_, &bufp, &hdr_loc);
TSHttpHdrUrlGet(bufp, hdr_loc, &url_loc);
TSUrlHostSet(bufp, url_loc, query.c_str(), query.length());
TSHandleMLocRelease(bufp, hdr_loc, url_loc);
TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
}
std::string ats::api::GetRequestUrlHost(Transaction &t) {
TSMBuffer bufp;
TSMLoc hdr_loc;
TSMLoc url_loc;
if (TSHttpTxnClientReqGet(t.ts_http_txn_, &bufp, &hdr_loc) != TS_SUCCESS)
return std::string();
TSHttpHdrUrlGet(bufp, hdr_loc, &url_loc);
int host_length;
const char *host = TSUrlHostGet(bufp, url_loc, &host_length);
std::string ret(host, host_length);
TSHandleMLocRelease(bufp, hdr_loc, url_loc);
TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
return ret;
}
std::string ats::api::GetPristineRequestUrlHost(Transaction &t) {
TSMBuffer bufp;
TSMLoc url_loc;
TSHttpTxnPristineUrlGet(t.ts_http_txn_, &bufp, &url_loc);
int host_length;
const char *host = TSUrlHostGet(bufp, url_loc, &host_length);
std::string ret(host, host_length);
TSHandleMLocRelease(bufp, TS_NULL_MLOC, url_loc);
return ret;
}
void ats::api::SetRequestUrlHost(Transaction &t, const std::string &host) {
TSMBuffer bufp;
TSMLoc hdr_loc;
TSMLoc url_loc;
TSHttpTxnClientReqGet(t.ts_http_txn_, &bufp, &hdr_loc);
TSHttpHdrUrlGet(bufp, hdr_loc, &url_loc);
TSUrlHostSet(bufp, url_loc, host.c_str(), host.length());
TSHandleMLocRelease(bufp, hdr_loc, url_loc);
TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
}
std::string ats::api::GetRequestUrlPath(Transaction &t) {
TSMBuffer bufp;
TSMLoc hdr_loc;
TSMLoc url_loc;
if (TSHttpTxnClientReqGet(t.ts_http_txn_, &bufp, &hdr_loc) != TS_SUCCESS)
return std::string();
TSHttpHdrUrlGet(bufp, hdr_loc, &url_loc);
int path_length;
const char *path = TSUrlPathGet(bufp, url_loc, &path_length);
std::string ret(path, path_length);
TSHandleMLocRelease(bufp, hdr_loc, url_loc);
TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
return ret;
}
unsigned int ats::api::GetRequestUrlPort(Transaction &t) {
TSMBuffer bufp;
TSMLoc hdr_loc;
TSMLoc url_loc;
TSHttpTxnClientReqGet(t.ts_http_txn_, &bufp, &hdr_loc);
TSHttpHdrUrlGet(bufp, hdr_loc, &url_loc);
int port = TSUrlPortGet(bufp, url_loc);
TSHandleMLocRelease(bufp, hdr_loc, url_loc);
TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
return port;
}
unsigned int ats::api::GetPristineRequestUrlPort(Transaction &t) {
TSMBuffer bufp;
TSMLoc url_loc;
TSHttpTxnPristineUrlGet(t.ts_http_txn_, &bufp, &url_loc);
int port = TSUrlPortGet(bufp, url_loc);
TSHandleMLocRelease(bufp, TS_NULL_MLOC, url_loc); // TODO: is this wrong?
return port;
}
void ats::api::SetRequestUrlPort(Transaction &t, unsigned int port) {
TSMBuffer bufp;
TSMLoc hdr_loc;
TSMLoc url_loc;
TSHttpTxnClientReqGet(t.ts_http_txn_, &bufp, &hdr_loc);
TSHttpHdrUrlGet(bufp, hdr_loc, &url_loc);
TSUrlPortSet(bufp, url_loc, port);
TSHandleMLocRelease(bufp, hdr_loc, url_loc);
TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
}
std::string ats::api::GetPristineRequestUrlPath(Transaction &t) {
TSMBuffer bufp;
TSMLoc url_loc;
TSHttpTxnPristineUrlGet(t.ts_http_txn_, &bufp, &url_loc);
int path_length;
const char *path = TSUrlPathGet(bufp, url_loc, &path_length);
std::string ret(path, path_length);
TSHandleMLocRelease(bufp, TS_NULL_MLOC, url_loc);
return ret;
}
void ats::api::SetRequestUrlPath(Transaction &t, const std::string &path) {
TSMBuffer bufp;
TSMLoc hdr_loc;
TSMLoc url_loc;
TSHttpTxnClientReqGet(t.ts_http_txn_, &bufp, &hdr_loc);
TSHttpHdrUrlGet(bufp, hdr_loc, &url_loc);
TSUrlPathSet(bufp, url_loc, path.c_str(), path.length());
TSHandleMLocRelease(bufp, hdr_loc, url_loc);
TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
}
static int GlobalContinuationHandler(TSCont contp, TSEvent /* event ATS_UNUSED */, void *edata) {
TSHttpTxn txnp = static_cast<TSHttpTxn>(edata);
Transaction transaction;
transaction.ts_http_txn_ = txnp;
transaction.ts_contp_ = contp;
HookContinuationData *data = static_cast<HookContinuationData*>(TSContDataGet(
contp));
ats::api::NextState ns = data->callback(transaction);
ReenableBasedOnNextState(txnp, ns);
return 0;
}
std::string ats::api::GetClientIP(Transaction &t) {
return printable_sockaddr_ip(TSHttpTxnClientAddrGet(t.ts_http_txn_));
}
unsigned int ats::api::GetClientPort(Transaction &t) {
const struct sockaddr_in * client_sockaddr =
reinterpret_cast<const struct sockaddr_in *>(TSHttpTxnClientAddrGet(
t.ts_http_txn_));
return static_cast<unsigned int>(ntohs(client_sockaddr->sin_port));
}
std::string ats::api::GetServerIncomingIP(Transaction &t) {
return printable_sockaddr_ip(TSHttpTxnIncomingAddrGet(t.ts_http_txn_));
}
unsigned int ats::api::GetServerIncomingPort(Transaction &t) {
const struct sockaddr_in * client_sockaddr =
reinterpret_cast<const struct sockaddr_in *>(TSHttpTxnIncomingAddrGet(
t.ts_http_txn_));
return static_cast<unsigned int>(ntohs(client_sockaddr->sin_port));
}
bool ats::api::IsInternalRequest(Transaction &t) {
return TSHttpIsInternalRequest(t.ts_http_txn_) == TS_SUCCESS;
}
int ats::api::GetServerResponseStatusCode(Transaction &t) {
TSMBuffer bufp;
TSMLoc hdr_loc;
TSHttpTxnServerRespGet(t.ts_http_txn_, &bufp, &hdr_loc);
int status = TSHttpHdrStatusGet(bufp, hdr_loc);
TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
return status;
}
std::string ats::api::GetRequestMethod(Transaction &t) {
TSMBuffer bufp;
TSMLoc hdr_loc;
TSHttpTxnClientReqGet(t.ts_http_txn_, &bufp, &hdr_loc);
int method_len;
const char *methodp = TSHttpHdrMethodGet(bufp, hdr_loc, &method_len);
std::string method(methodp, method_len);
TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
return method;
}
void ats::api::SetRequestMethod(Transaction &t, const std::string &method) {
TSMBuffer bufp;
TSMLoc hdr_loc;
TSHttpTxnClientReqGet(t.ts_http_txn_, &bufp, &hdr_loc);
TSHttpHdrMethodSet(bufp, hdr_loc, method.c_str(), method.length());
TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
}
void ats::api::ReenableTransaction(Transaction &t, NextState ns) {
ReenableBasedOnNextState(t.ts_http_txn_, ns);
}
static int TransactionContinuationHandler(TSCont contp, TSEvent event,
void *edata) {
TSHttpTxn txnp = static_cast<TSHttpTxn>(edata);
Transaction transaction;
transaction.ts_http_txn_ = txnp;
transaction.ts_contp_ = contp;
NextState ns = NextState::HTTP_CONTINUE;
HookContinuationData *data = static_cast<HookContinuationData*>(TSContDataGet(
contp));
if (event != TS_EVENT_HTTP_TXN_CLOSE
|| (event == TS_EVENT_HTTP_TXN_CLOSE
&& data->ts_hook_id == TS_HTTP_TXN_CLOSE_HOOK)) {
ns = data->callback(transaction);
}
// We must free the HookContinuationData structure and continuation
// If this transaction is complete
if (event == TS_EVENT_HTTP_TXN_CLOSE) {
delete data;
TSContDestroy(contp);
}
ReenableBasedOnNextState(txnp, ns);
return 0;
}
void* ats::api::GetTransactionIdentifier(Transaction &t) {
return reinterpret_cast<void *>(t.ts_http_txn_);
}
void ats::api::CreateTransactionHook(Transaction &txn,HookType hook,
GlobalHookCallback callback) {
TSHttpHookID ts_hook_id = TSHookIDFromHookType(hook);
TSCont contp = TSContCreate(TransactionContinuationHandler, NULL);
HookContinuationData *data = new HookContinuationData();
data->callback = callback;
data->hooktype = hook;
data->ts_hook_id = ts_hook_id;
TSContDataSet(contp, static_cast<void*>(data));
TSHttpTxnHookAdd(txn.ts_http_txn_, ts_hook_id, contp);
if (ts_hook_id != TS_HTTP_TXN_CLOSE_HOOK) {
TSHttpTxnHookAdd(txn.ts_http_txn_, TS_HTTP_TXN_CLOSE_HOOK, contp);
}
}
void ats::api::CreateGlobalHook(HookType hook, GlobalHookCallback callback) {
TSHttpHookID ts_hook_id = TSHookIDFromHookType(hook);
TSCont contp = TSContCreate(GlobalContinuationHandler, NULL);
HookContinuationData *data = new HookContinuationData();
data->callback = callback;
data->hooktype = hook;
TSContDataSet(contp, static_cast<void*>(data));
TSHttpHookAdd(ts_hook_id, contp);
}
/*
* Header code
*/
void SetHeader(TSMBuffer bufp, TSMLoc hdr_loc, const std::string &name,
const std::vector<std::string> &values) {
TSMLoc field_loc;
field_loc = TSMimeHdrFieldFind(bufp, hdr_loc, name.c_str(), name.length());
// if the field already existed, let's just blow it away.
if (field_loc) {
TSMimeHdrFieldDestroy(bufp, hdr_loc, field_loc);
TSHandleMLocRelease(bufp, hdr_loc, field_loc);
}
// Now it definitely doesn't exist, so add it.
TSMimeHdrFieldCreate(bufp, hdr_loc, &field_loc);
TSMimeHdrFieldNameSet(bufp, hdr_loc, field_loc, name.c_str(), name.length());
for (unsigned int i = 0; i < values.size(); ++i) {
TSMimeHdrFieldValueStringInsert(bufp, hdr_loc, field_loc, 0, values[i].c_str(),
values[i].length());
TSMimeHdrFieldAppend(bufp, hdr_loc, field_loc);
}
TSHandleMLocRelease(bufp, hdr_loc, field_loc);
}
void AppendHeader(TSMBuffer bufp, TSMLoc hdr_loc, const std::string &name,
const std::vector<std::string> &values) {
TSMLoc field_loc;
TSMimeHdrFieldCreate(bufp, hdr_loc, &field_loc);
TSMimeHdrFieldNameSet(bufp, hdr_loc, field_loc, name.c_str(), name.length());
for (unsigned int i = 0; i < values.size(); ++i) {
TSMimeHdrFieldValueStringInsert(bufp, hdr_loc, field_loc, 0, values[i].c_str(),
values[i].length());
TSMimeHdrFieldAppend(bufp, hdr_loc, field_loc);
}
TSHandleMLocRelease(bufp, hdr_loc, field_loc);
}
void DeleteHeader(TSMBuffer bufp, TSMLoc hdr_loc, const std::string &name) {
TSMLoc field_loc;
field_loc = TSMimeHdrFieldFind(bufp, hdr_loc, name.c_str(), name.length());
if (field_loc) {
TSMimeHdrFieldDestroy(bufp, hdr_loc, field_loc);
TSHandleMLocRelease(bufp, hdr_loc, field_loc);
}
}
/*
* Obviously this should be optimized to either fill in a passed vector
* or just returned a shared_ptr to the build vector, this is an exercise
* left to the reader.
*/
ats::api::headers::HeaderVector GetHeaders(TSMBuffer bufp, TSMLoc hdr_loc) {
TSMLoc field_loc;
ats::api::headers::HeaderVector hv;
field_loc = TSMimeHdrFieldGet(bufp, hdr_loc, 0);
while (field_loc) {
/* copy the header to a more friedly data structure */
int name_length;
const char *fieldName = TSMimeHdrFieldNameGet(bufp, hdr_loc, field_loc, &name_length);
ats::api::headers::Header hdr;
hdr.assignName(fieldName, name_length);
/* now we have to walk all the values and add them */
int numValues = TSMimeHdrFieldValuesCount(bufp, hdr_loc, field_loc);
for (int indx = 0; indx < numValues; ++indx) {
int val_length;
const char *value = TSMimeHdrFieldValueStringGet(bufp, hdr_loc, field_loc, indx, &val_length);
hdr.addNewValue(value, val_length);
}
hv.push_back(hdr);
/* Get the next field and release the current one */
TSMLoc next_field_loc = TSMimeHdrFieldNext(bufp, hdr_loc, field_loc);
TSHandleMLocRelease(bufp, hdr_loc, field_loc);
field_loc = next_field_loc;
}
return hv;
}
/*
* TODO: All of these can be improved by caching and then invalidating the
* header cache when a delete, append, or set occurs.
*/
void ats::api::headers::DeleteClientRequestHeader(Transaction &t, const std::string &name) {
TSMBuffer bufp;
TSMLoc hdr_loc;
if (TSHttpTxnClientReqGet(t.ts_http_txn_, &bufp, &hdr_loc) != TS_SUCCESS)
return;
DeleteHeader(bufp, hdr_loc, name);
TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
}
void ats::api::headers::DeleteClientResponseHeader(Transaction &t, const std::string &name) {
TSMBuffer bufp;
TSMLoc hdr_loc;
if (TSHttpTxnClientRespGet(t.ts_http_txn_, &bufp, &hdr_loc) != TS_SUCCESS)
return;
DeleteHeader(bufp, hdr_loc, name);
TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
}
void ats::api::headers::DeleteServerResponseHeader(Transaction &t, const std::string &name) {
TSMBuffer bufp;
TSMLoc hdr_loc;
if (TSHttpTxnServerRespGet(t.ts_http_txn_, &bufp, &hdr_loc) != TS_SUCCESS)
return;
DeleteHeader(bufp, hdr_loc, name);
TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
}
void ats::api::headers::SetClientRequestHeader(Transaction &t, const std::string &name,
const std::vector<std::string> &vals) {
TSMBuffer bufp;
TSMLoc hdr_loc;
if (TSHttpTxnClientReqGet(t.ts_http_txn_, &bufp, &hdr_loc) != TS_SUCCESS)
return;
SetHeader(bufp, hdr_loc, name, vals);
TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
}
void ats::api::headers::SetClientRequestHeader(Transaction &t, const std::string &name, const std::string &val) {
std::vector<std::string> vals;
vals.push_back(val);
SetClientRequestHeader(t, name, vals);
}
void ats::api::headers::SetClientResponseHeader(Transaction &t, const std::string &name,
const std::vector<std::string> &vals) {
TSMBuffer bufp;
TSMLoc hdr_loc;
if (TSHttpTxnClientRespGet(t.ts_http_txn_, &bufp, &hdr_loc) != TS_SUCCESS)
return;
SetHeader(bufp, hdr_loc, name, vals);
TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
}
void ats::api::headers::SetClientResponseHeader(Transaction &t, const std::string &name, const std::string &val) {
std::vector<std::string> vals;
vals.push_back(val);
SetClientResponseHeader(t, name, vals);
}
void ats::api::headers::SetServerResponseHeader(Transaction &t, const std::string &name,
const std::vector<std::string> &vals) {
TSMBuffer bufp;
TSMLoc hdr_loc;
if (TSHttpTxnServerRespGet(t.ts_http_txn_, &bufp, &hdr_loc) != TS_SUCCESS)
return;
SetHeader(bufp, hdr_loc, name, vals);
TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
}
void ats::api::headers::SetServerResponseHeader(Transaction &t, const std::string &name, const std::string &val) {
std::vector<std::string> vals;
vals.push_back(val);
SetServerResponseHeader(t, name, vals);
}
void ats::api::headers::AppendServerResponseHeader(Transaction &t, const std::string &name,
const std::vector<std::string> &vals) {
TSMBuffer bufp;
TSMLoc hdr_loc;
if (TSHttpTxnServerRespGet(t.ts_http_txn_, &bufp, &hdr_loc) != TS_SUCCESS)
return;
AppendHeader(bufp, hdr_loc, name, vals);
TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
}
void ats::api::headers::AppendServerResponseHeader(Transaction &t, const std::string &name,
const std::string &val) {
std::vector<std::string> vals;
vals.push_back(val);
AppendServerResponseHeader(t, name, vals);
}
void ats::api::headers::AppendClientRequestHeader(Transaction &t, const std::string &name,
const std::vector<std::string> &vals) {
TSMBuffer bufp;
TSMLoc hdr_loc;
if (TSHttpTxnClientReqGet(t.ts_http_txn_, &bufp, &hdr_loc) != TS_SUCCESS)
return;
AppendHeader(bufp, hdr_loc, name, vals);
TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
}
void ats::api::headers::AppendClientRequestHeader(Transaction &t, const std::string &name,
const std::string &val) {
std::vector<std::string> vals;
vals.push_back(val);
AppendClientRequestHeader(t, name, vals);
}
void ats::api::headers::AppendClientResponseHeader(Transaction &t, const std::string &name,
const std::vector<std::string> &vals) {
TSMBuffer bufp;
TSMLoc hdr_loc;
if (TSHttpTxnClientRespGet(t.ts_http_txn_, &bufp, &hdr_loc) != TS_SUCCESS)
return;
AppendHeader(bufp, hdr_loc, name, vals);
TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
}
void ats::api::headers::AppendClientResponseHeader(Transaction &t, const std::string &name,
const std::string &val) {
std::vector<std::string> vals;
vals.push_back(val);
AppendClientResponseHeader(t, name, vals);
}
ats::api::headers::HeaderVector ats::api::headers::GetClientRequestHeaders(Transaction &t) {
TSMBuffer bufp;
TSMLoc hdr_loc;
HeaderVector hv;
if (TSHttpTxnClientReqGet(t.ts_http_txn_, &bufp, &hdr_loc) != TS_SUCCESS)
return hv;
hv = GetHeaders(bufp, hdr_loc);
TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
return hv;
}
ats::api::headers::HeaderVector ats::api::headers::GetClientResponseHeaders(Transaction &t) {
TSMBuffer bufp;
TSMLoc hdr_loc;
HeaderVector hv;
if (TSHttpTxnClientRespGet(t.ts_http_txn_, &bufp, &hdr_loc) != TS_SUCCESS)
return hv;
hv = GetHeaders(bufp, hdr_loc);
TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
return hv;
}
ats::api::headers::HeaderVector ats::api::headers::GetServerResponseHeaders(Transaction &t) {
TSMBuffer bufp;
TSMLoc hdr_loc;
HeaderVector hv;
if (TSHttpTxnServerRespGet(t.ts_http_txn_, &bufp, &hdr_loc) != TS_SUCCESS)
return hv;
hv = GetHeaders(bufp, hdr_loc);
TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
return hv;
}
inline ats::api::headers::Header GetHeader(Transaction & /* t ATS_UNUSED */, const std::string& hdr_name,
const ats::api::headers::HeaderVector &hdrs) {
ats::api::headers::Header hdr;
ats::api::headers::HeaderVector::const_iterator ii = std::find_if(hdrs.begin(), hdrs.end(),
ats::api::headers::HeaderName(hdr_name));
if (ii != hdrs.end()) {
hdr = *ii;
}
return hdr;
}
ats::api::headers::Header ats::api::headers::GetClientRequestHeader(Transaction &t, const std::string& hdr_name) {
return GetHeader(t, hdr_name, GetClientRequestHeaders(t));
}
ats::api::headers::Header ats::api::headers::GetClientResponseHeader(Transaction &t, const std::string& hdr_name) {
return GetHeader(t, hdr_name, GetClientResponseHeaders(t));
}
ats::api::headers::Header ats::api::headers::GetServerResponseHeader(Transaction &t, const std::string& hdr_name) {
return GetHeader(t, hdr_name, GetServerResponseHeaders(t));
}