Skip to content
Merged
Show file tree
Hide file tree
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
4 changes: 3 additions & 1 deletion doc/admin-guide/plugins/multiplexer.en.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@

|Name| is a remap plug-in that allows a request to be multiplexed one or more times and sent to
different remap entries. Both headers and body (in case of POST or PUT methods, only) are copied
into the new requests.
into the new requests. Optionally POST/PUT requests can be skipped via
``pparam=proxy.config.multiplexer.skip_post_put=1``.

Description
===========
Expand Down Expand Up @@ -59,6 +60,7 @@ Example remap.config::
map http://www.example.com/a http://www.example.com/ @plugin=multiplexer.so @pparam=host1.example.com
map http://www.example.com/b http://www.example.com/ @plugin=multiplexer.so @pparam=host2.example.com
map http://www.example.com/c http://www.example.com/ @plugin=multiplexer.so @pparam=host1.example.com @pparam=host2.example.com
map http://www.example.com/d http://www.example.com/ @plugin=multiplexer.so @pparam=host1.example.com @pparam=host2.example.com @pparam=proxy.config.multiplexer.skip_post_put=1


Implementation
Expand Down
69 changes: 41 additions & 28 deletions plugins/multiplexer/ats-multiplexer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,19 @@ TSReturnCode
TSRemapNewInstance(int argc, char **argv, void **i, char *, int)
{
assert(i != nullptr);
Instance *instance = new Instance;
Instance *instance = new Instance;
instance->skipPostPut = false;

if (argc > 2) {
std::copy(argv + 2, argv + argc, std::back_inserter(instance->origins));
std::copy_if(argv + 2, argv + argc, std::back_inserter(instance->origins), [&](std::string s) {
if (s == "proxy.config.multiplexer.skip_post_put=1") {
instance->skipPostPut = true;
return false;
}
return true;
});
}
TSDebug(PLUGIN_TAG, "skipPostPut is %s", (instance->skipPostPut ? "true" : "false"));

*i = static_cast<void *>(instance);

Expand Down Expand Up @@ -109,41 +117,46 @@ DoRemap(const Instance &i, TSHttpTxn t)
assert(buffer != nullptr);
assert(location != nullptr);

{
TSMLoc field;
int length;
const char *const method = TSHttpHdrMethodGet(buffer, location, &length);

CHECK(TSMimeHdrFieldCreateNamed(buffer, location, "X-Multiplexer", 13, &field));
assert(field != nullptr);
TSDebug(PLUGIN_TAG, "Method is %s.", std::string(method, length).c_str());

CHECK(TSMimeHdrFieldValueStringSet(buffer, location, field, -1, "original", 8));
if (i.skipPostPut && ((length == TS_HTTP_LEN_POST && memcmp(TS_HTTP_METHOD_POST, method, TS_HTTP_LEN_POST) == 0) ||
(length == TS_HTTP_LEN_PUT && memcmp(TS_HTTP_METHOD_PUT, method, TS_HTTP_LEN_PUT) == 0))) {
TSHandleMLocRelease(buffer, TS_NULL_MLOC, location);
} else {
{
TSMLoc field;

CHECK(TSMimeHdrFieldAppend(buffer, location, field));
CHECK(TSMimeHdrFieldCreateNamed(buffer, location, "X-Multiplexer", 13, &field));
assert(field != nullptr);

CHECK(TSHandleMLocRelease(buffer, location, field));
}
CHECK(TSMimeHdrFieldValueStringSet(buffer, location, field, -1, "original", 8));

Requests requests;
generateRequests(i.origins, buffer, location, requests);
assert(requests.size() == i.origins.size());
CHECK(TSMimeHdrFieldAppend(buffer, location, field));

int length;
const char *const method = TSHttpHdrMethodGet(buffer, location, &length);

TSDebug(PLUGIN_TAG, "Method is %s.", std::string(method, length).c_str());
CHECK(TSHandleMLocRelease(buffer, location, field));
}

if (length == TS_HTTP_LEN_POST && memcmp(TS_HTTP_METHOD_POST, method, TS_HTTP_LEN_POST) == 0) {
const TSVConn vconnection = TSTransformCreate(handlePost, t);
assert(vconnection != nullptr);
TSContDataSet(vconnection, new PostState(requests));
assert(requests.empty());
TSHttpTxnHookAdd(t, TS_HTTP_REQUEST_TRANSFORM_HOOK, vconnection);
} else {
dispatch(requests, timeout);
}
Requests requests;
generateRequests(i.origins, buffer, location, requests);
assert(requests.size() == i.origins.size());

if (length == TS_HTTP_LEN_POST && memcmp(TS_HTTP_METHOD_POST, method, TS_HTTP_LEN_POST) == 0) {
const TSVConn vconnection = TSTransformCreate(handlePost, t);
assert(vconnection != nullptr);
TSContDataSet(vconnection, new PostState(requests));
assert(requests.empty());
TSHttpTxnHookAdd(t, TS_HTTP_REQUEST_TRANSFORM_HOOK, vconnection);
} else {
dispatch(requests, timeout);
}

TSHandleMLocRelease(buffer, TS_NULL_MLOC, location);
TSHandleMLocRelease(buffer, TS_NULL_MLOC, location);

TSStatIntIncrement(statistics.requests, 1);
TSStatIntIncrement(statistics.requests, 1);
}
}

TSRemapStatus
Expand Down
1 change: 1 addition & 0 deletions plugins/multiplexer/dispatch.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ typedef std::vector<Request> Requests;

struct Instance {
Origins origins;
bool skipPostPut;
};

extern size_t timeout;
Expand Down