blob: 4317d9da5d8a2f6de81cfb0dec28891f29b4d468 [file] [log] [blame]
/** @file
Plugin to perform background fetches of certain content that would
otherwise not be cached. For example, Range: requests / responses.
@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 <cstdlib>
#include "configs.h"
#include "headers.h"
///////////////////////////////////////////////////////////////////////////
// Remove a header (fully) from an TSMLoc / TSMBuffer. Return the number
// of fields (header values) we removed.
int
remove_header(TSMBuffer bufp, TSMLoc hdr_loc, const char *header, int len)
{
TSMLoc field = TSMimeHdrFieldFind(bufp, hdr_loc, header, len);
int cnt = 0;
while (field) {
TSMLoc tmp = TSMimeHdrFieldNextDup(bufp, hdr_loc, field);
++cnt;
TSMimeHdrFieldDestroy(bufp, hdr_loc, field);
TSHandleMLocRelease(bufp, hdr_loc, field);
field = tmp;
}
return cnt;
}
///////////////////////////////////////////////////////////////////////////
// Set a header to a specific value. This will avoid going to through a
// remove / add sequence in case of an existing header.
// but clean.
bool
set_header(TSMBuffer bufp, TSMLoc hdr_loc, const char *header, int len, const char *val, int val_len)
{
if (!bufp || !hdr_loc || !header || len <= 0 || !val || val_len <= 0) {
return false;
}
bool ret = false;
TSMLoc field_loc = TSMimeHdrFieldFind(bufp, hdr_loc, header, len);
if (!field_loc) {
// No existing header, so create one
if (TS_SUCCESS == TSMimeHdrFieldCreateNamed(bufp, hdr_loc, header, len, &field_loc)) {
if (TS_SUCCESS == TSMimeHdrFieldValueStringSet(bufp, hdr_loc, field_loc, -1, val, val_len)) {
TSMimeHdrFieldAppend(bufp, hdr_loc, field_loc);
ret = true;
}
TSHandleMLocRelease(bufp, hdr_loc, field_loc);
}
} else {
TSMLoc tmp = nullptr;
bool first = true;
while (field_loc) {
if (first) {
first = false;
if (TS_SUCCESS == TSMimeHdrFieldValueStringSet(bufp, hdr_loc, field_loc, -1, val, val_len)) {
ret = true;
}
} else {
TSMimeHdrFieldDestroy(bufp, hdr_loc, field_loc);
}
tmp = TSMimeHdrFieldNextDup(bufp, hdr_loc, field_loc);
TSHandleMLocRelease(bufp, hdr_loc, field_loc);
field_loc = tmp;
}
}
return ret;
}
///////////////////////////////////////////////////////////////////////////
// Dump a header on stderr, useful together with TSDebug().
void
dump_headers(TSMBuffer bufp, TSMLoc hdr_loc)
{
TSIOBuffer output_buffer;
TSIOBufferReader reader;
TSIOBufferBlock block;
int64_t block_avail;
output_buffer = TSIOBufferCreate();
reader = TSIOBufferReaderAlloc(output_buffer);
/* This will print just MIMEFields and not the http request line */
TSMimeHdrPrint(bufp, hdr_loc, output_buffer);
/* We need to loop over all the buffer blocks, there can be more than 1 */
block = TSIOBufferReaderStart(reader);
do {
const char *block_start = TSIOBufferBlockReadStart(block, reader, &block_avail);
if (block_avail > 0) {
TSDebug(PLUGIN_NAME, "Headers are:\n%.*s", static_cast<int>(block_avail), block_start);
}
TSIOBufferReaderConsume(reader, block_avail);
block = TSIOBufferReaderStart(reader);
} while (block && block_avail != 0);
/* Free up the TSIOBuffer that we used to print out the header */
TSIOBufferReaderFree(reader);
TSIOBufferDestroy(output_buffer);
}