116
121
list<string> post_headers;
118
123
ContData(TSCont contptr, TSHttpTxn tx)
119
: curr_state(READING_ESI_DOC), input_vio(NULL),
124
: curr_state(READING_ESI_DOC), input_vio(NULL), output_vio(NULL),
120
125
output_buffer(NULL), output_reader(NULL),
121
esi_vars(NULL), data_fetcher(NULL), esi_proc(NULL),
126
esi_vars(NULL), data_fetcher(NULL), esi_proc(NULL), esi_gzip(NULL),
122
127
contp(contptr), txnp(tx), request_url(NULL),
123
128
input_type(DATA_TYPE_RAW_ESI), packed_node_list(""),
124
129
gzipped_data(""), gzip_output(false),
213
218
input_reader = TSVIOReaderGet(input_vio);
220
// get downstream VIO
222
output_conn = TSTransformOutputVConnGet(contp);
224
TSError("[%s] Error while getting transform VC", __FUNCTION__);
215
227
output_buffer = TSIOBufferCreate();
216
228
output_reader = TSIOBufferReaderAlloc(output_buffer);
218
string fetcher_tag, vars_tag, expr_tag, proc_tag;
230
// we don't know how much data we are going to write, so INT_MAX
231
output_vio = TSVConnWrite(output_conn, contp, output_reader, INT64_MAX);
233
string fetcher_tag, vars_tag, expr_tag, proc_tag, gzip_tag;
219
234
if (!data_fetcher) {
220
235
data_fetcher = new HttpDataFetcherImpl(contp, client_addr,
221
236
createDebugTag(FETCHER_DEBUG_TAG, contp, fetcher_tag));
228
243
createDebugTag(PARSER_DEBUG_TAG, contp, fetcher_tag),
229
244
createDebugTag(EXPR_DEBUG_TAG, contp, expr_tag),
230
245
&TSDebug, &TSError, *data_fetcher, *esi_vars, *gHandlerManager);
247
esi_gzip = new EsiGzip(createDebugTag(GZIP_DEBUG_TAG, contp, gzip_tag), &TSDebug, &TSError);
231
249
TSDebug(debug_tag, "[%s] Set input data type to [%s]", __FUNCTION__,
232
250
DATA_TYPE_NAMES_[input_type]);
807
if ((cont_data->curr_state == ContData::FETCHING_DATA) &&
808
(cont_data->option_info->first_byte_flush)) { // retest as state may have changed in previous block
809
TSDebug(cont_data->debug_tag, "[%s] trying to process doc", __FUNCTION__);
813
EsiProcessor::ReturnCode retval = cont_data->esi_proc->flush(out_data, overall_len);
815
if (cont_data->data_fetcher->isFetchComplete()) {
816
TSDebug(cont_data->debug_tag, "[%s] data ready; last process() will have finished the entire processing", __FUNCTION__);
817
cont_data->curr_state = ContData::PROCESSING_COMPLETE;
820
if (retval == EsiProcessor::SUCCESS) {
821
TSDebug(cont_data->debug_tag,
822
"[%s] ESI processor output document of size %d starting with [%.10s]",
823
__FUNCTION__, (int) out_data.size(), (out_data.size() ? out_data.data() : "(null)"));
825
TSError("[%s] ESI processor failed to process document; will return empty document", __FUNCTION__);
828
if(!cont_data->xform_closed) {
829
TSVIONBytesSet(cont_data->output_vio, 0);
830
TSVIOReenable(cont_data->output_vio);
834
// make sure transformation has not been prematurely terminated
835
if (!cont_data->xform_closed && out_data.size() > 0) {
836
if (cont_data->gzip_output) {
837
if (!cont_data->esi_gzip->stream_encode(out_data, cdata)) {
838
TSError("[%s] Error while gzipping content", __FUNCTION__);
840
TSDebug(cont_data->debug_tag, "[%s] Compressed document from size %d to %d bytes",
841
__FUNCTION__, (int) out_data.size(), (int) cdata.size());
845
if (cont_data->gzip_output) {
846
if (TSIOBufferWrite(TSVIOBufferGet(cont_data->output_vio), cdata.data(), cdata.size()) == TS_ERROR) {
847
TSError("[%s] Error while writing bytes to downstream VC", __FUNCTION__);
851
if (TSIOBufferWrite(TSVIOBufferGet(cont_data->output_vio), out_data.data(), out_data.size()) == TS_ERROR) {
852
TSError("[%s] Error while writing bytes to downstream VC", __FUNCTION__);
857
if(!cont_data->xform_closed) {
858
// should not set any fixed length
859
if(cont_data->curr_state == ContData::PROCESSING_COMPLETE) {
860
if(cont_data->gzip_output) {
862
int downstream_length;
863
if(!cont_data->esi_gzip->stream_finish(cdata, downstream_length)) {
864
TSError("[%s] Error while finishing gzip", __FUNCTION__);
867
if (TSIOBufferWrite(TSVIOBufferGet(cont_data->output_vio), cdata.data(), cdata.size()) == TS_ERROR) {
868
TSError("[%s] Error while writing bytes to downstream VC", __FUNCTION__);
871
TSDebug(cont_data->debug_tag,
872
"[%s] ESI processed overall/gzip: %d",
873
__FUNCTION__, downstream_length );
874
TSVIONBytesSet(cont_data->output_vio, downstream_length);
877
TSDebug(cont_data->debug_tag,
878
"[%s] ESI processed overall: %d",
879
__FUNCTION__, overall_len );
880
TSVIONBytesSet(cont_data->output_vio, overall_len);
884
// Reenable the output connection so it can read the data we've produced.
885
TSVIOReenable(cont_data->output_vio);
859
965
transformData(contp);
968
case TS_EVENT_VCONN_WRITE_READY:
969
TSDebug(cont_debug_tag, "[%s] WRITE_READY", __FUNCTION__);
970
if(!cont_data->option_info->first_byte_flush) {
971
TSVConnShutdown(TSTransformOutputVConnGet(contp), 0, 1);
862
975
case TS_EVENT_VCONN_WRITE_COMPLETE:
863
case TS_EVENT_VCONN_WRITE_READY: // we write only once to downstream VC
864
976
TSDebug(cont_debug_tag, "[%s] shutting down transformation", __FUNCTION__);
865
977
TSVConnShutdown(TSTransformOutputVConnGet(contp), 0, 1);
874
986
if (is_fetch_event) {
875
987
TSDebug(cont_debug_tag, "[%s] Handling fetch event %d...", __FUNCTION__, event);
876
988
if (cont_data->data_fetcher->handleFetchEvent(event, edata)) {
877
if ((cont_data->curr_state == ContData::FETCHING_DATA) &&
878
cont_data->data_fetcher->isFetchComplete()) {
989
if (cont_data->curr_state == ContData::FETCHING_DATA) {
879
990
// there's a small chance that fetcher is ready even before
880
991
// parsing is complete; hence we need to check the state too
881
TSDebug(cont_debug_tag, "[%s] fetcher is ready with data, going into process stage",
992
if(cont_data->option_info->first_byte_flush ||
993
cont_data->data_fetcher->isFetchComplete()){
994
TSDebug(cont_debug_tag, "[%s] fetcher is ready with data, going into process stage",
883
transformData(contp);
996
transformData(contp);
886
1000
TSError("[%s] Could not handle fetch event!", __FUNCTION__);
1513
1627
if (argc > 1) {
1515
1629
static const struct option longopts[] = {
1516
{ "packed-node-support", no_argument, NULL, 'n' },
1517
{ "private-response", no_argument, NULL, 'p' },
1518
{ "disable-gzip-output", no_argument, NULL, 'z' },
1519
{ "handler-filename", required_argument, NULL, 'f' },
1630
{ const_cast<char *>("packed-node-support"), no_argument, NULL, 'n' },
1631
{ const_cast<char *>("private-response"), no_argument, NULL, 'p' },
1632
{ const_cast<char *>("disable-gzip-output"), no_argument, NULL, 'z' },
1633
{ const_cast<char *>("first-byte-flush"), no_argument, NULL, 'b' },
1634
{ const_cast<char *>("handler-filename"), required_argument, NULL, 'f' },
1520
1635
{ NULL, 0, NULL, 0 }
1524
1639
optind = opterr = optopt = 0;
1525
1640
int longindex = 0;
1526
while ((c = getopt_long(argc, (char * const*) argv, "npzf:", longopts, &longindex)) != -1) {
1641
while ((c = getopt_long(argc, (char * const*) argv, "npzbf:", longopts, &longindex)) != -1) {
1529
1644
pOptionInfo->packed_node_support = true;
1562
1681
if (result == 0) {
1563
1682
TSDebug(DEBUG_TAG, "[%s] Plugin started%s, " \
1564
1683
"packed-node-support: %d, private-response: %d, " \
1565
"disable-gzip-output: %d", __FUNCTION__, bKeySet ? " and key is set" : "",
1684
"disable-gzip-output: %d, first-byte-flush: %d ", __FUNCTION__, bKeySet ? " and key is set" : "",
1566
1685
pOptionInfo->packed_node_support, pOptionInfo->private_response,
1567
pOptionInfo->disable_gzip_output);
1686
pOptionInfo->disable_gzip_output, pOptionInfo->first_byte_flush);
1600
1719
TSRemapInit(TSRemapInterface* api_info, char *errbuf, int errbuf_size)
1602
1721
if (!api_info) {
1603
TSstrlcpy(errbuf, "[TSRemapInit] - Invalid TSRemapInterface argument", errbuf_size);
1722
snprintf(errbuf, errbuf_size, "[TSRemapInit] - Invalid TSRemapInterface argument");
1723
TSError("[TSRemapInit] - Invalid TSRemapInterface argument");
1604
1724
return TS_ERROR;
1607
1727
if (api_info->size < sizeof(TSRemapInterface)) {
1608
TSstrlcpy(errbuf, "[TSRemapInit] - Incorrect size of TSRemapInterface structure", errbuf_size);
1728
snprintf(errbuf, errbuf_size, "[TSRemapInit] - Incorrect size of TSRemapInterface structure");
1729
TSError("[TSRemapInit] - Incorrect size of TSRemapInterface structure");
1609
1730
return TS_ERROR;
1612
TSDebug(DEBUG_TAG, "esi remap plugin is succesfully initialized");
1733
TSDebug(DEBUG_TAG, "esi remap plugin is successfully initialized");
1613
1734
return TS_SUCCESS;
1617
1738
TSRemapNewInstance(int argc, char* argv[], void** ih, char* errbuf, int errbuf_size)
1620
TSError("Unable to create remap instance, need configuration file");
1741
snprintf(errbuf, errbuf_size, "Unable to create remap instance, " \
1742
"argc: %d < 2", argc);
1743
TSError("Unable to create remap instance! argc: %d < 2", argc);
1621
1744
return TS_ERROR;