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: 4 additions & 0 deletions doc/admin-guide/plugins/slice.en.rst
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,10 @@ The slice plugin supports the following options::
can improve cache miss latency.
-f for short

--strip-range-for-head (optional)
Enable slice plugin to strip Range header for HEAD requests.
-h for short

Examples::

@plugin=slice.so @pparam=--blockbytes=1000000 @plugin=cache_range_requests.so
Expand Down
4 changes: 4 additions & 0 deletions plugins/experimental/slice/Config.cc
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ Config::fromArgs(int const argc, char const *const argv[])
{const_cast<char *>("skip-header"), required_argument, nullptr, 's'},
{const_cast<char *>("blockbytes-test"), required_argument, nullptr, 't'},
{const_cast<char *>("prefetch-count"), required_argument, nullptr, 'f'},
{const_cast<char *>("strip-range-for-head"), no_argument, nullptr, 'h'},
{nullptr, 0, nullptr, 0},
};

Expand Down Expand Up @@ -226,6 +227,9 @@ Config::fromArgs(int const argc, char const *const argv[])
case 'f': {
m_prefetchcount = atoi(optarg);
} break;
case 'h': {
m_head_strip_range = true;
} break;
default:
break;
}
Expand Down
5 changes: 3 additions & 2 deletions plugins/experimental/slice/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,9 @@ struct Config {
int m_paceerrsecs{0}; // -1 disable logging, 0 no pacing, max 60s
int m_prefetchcount{0}; // 0 disables prefetching
enum RefType { First, Relative };
RefType m_reftype{First}; // reference slice is relative to request
bool m_head_req{false}; // HEAD request
RefType m_reftype{First}; // reference slice is relative to request
bool m_head_req{false}; // HEAD request
bool m_head_strip_range{false}; // strip range header for head requests

std::string m_skip_header;
std::string m_crr_ims_header;
Expand Down
8 changes: 8 additions & 0 deletions plugins/experimental/slice/server.cc
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,14 @@ handleFirstServerHeader(Data *const data, TSCont const contp)
// Should run TSVIONSetBytes(output_io, hlen + bodybytes);
int64_t const hlen = TSHttpHdrLengthGet(header.m_buffer, header.m_lochdr);
int64_t const clen = contentLengthFrom(header);
if (data->m_config->m_head_req && TS_HTTP_STATUS_OK == header.status()) {
DEBUG_LOG("HEAD request stripped Range header: expects 200");
TSVIONBytesSet(output_vio, hlen);
TSHttpHdrPrint(header.m_buffer, header.m_lochdr, output_buf);
data->m_bytessent = hlen;
TSVIOReenable(output_vio);
return HeaderState::Good;
}
DEBUG_LOG("Passthru bytes: header: %" PRId64 " body: %" PRId64, hlen, clen);
if (clen != INT64_MAX) {
TSVIONBytesSet(output_vio, hlen + clen);
Expand Down
17 changes: 11 additions & 6 deletions plugins/experimental/slice/util.cc
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,17 @@ request_block(TSCont contp, Data *const data)
// reuse the incoming client header, just change the range
HttpHeader header(data->m_req_hdrmgr.m_buffer, data->m_req_hdrmgr.m_lochdr);

// add/set sub range key and add slicer tag
bool const rangestat = header.setKeyVal(TS_MIME_FIELD_RANGE, TS_MIME_LEN_RANGE, rangestr, rangelen);

if (!rangestat) {
ERROR_LOG("Error trying to set range request header %s", rangestr);
return false;
// if configured, remove range header from head requests
if (data->m_config->m_head_req && data->m_config->m_head_strip_range) {
header.removeKey(TS_MIME_FIELD_RANGE, TS_MIME_LEN_RANGE);
} else {
// add/set sub range key and add slicer tag
bool const rangestat = header.setKeyVal(TS_MIME_FIELD_RANGE, TS_MIME_LEN_RANGE, rangestr, rangelen);

if (!rangestat) {
ERROR_LOG("Error trying to set range request header %s", rangestr);
return false;
}
}

header.removeKey(SLICE_CRR_HEADER.data(), SLICE_CRR_HEADER.size());
Expand Down
83 changes: 83 additions & 0 deletions tests/gold_tests/pluginTest/slice/replay/slice_range.replay.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# 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.

meta:
version: "1.0"

sessions:
- transactions:
- client-request:
method: "HEAD"
version: "1.1"
url: /no/range
headers:
fields:
- [ Host, example.com ]
- [ X-Request, request ]
- [ Range, bytes=0-5 ]
- [ uuid, 1 ]

proxy-request:
headers:
fields:
- [ Range, { as: absent } ]

server-response:
status: 200
reason: OK
headers:
fields:
- [ Content-Length, 16 ]
- [ X-Response, response ]

proxy-response:
status: 200
headers:
fields:
- [ X-Response, { value: response, as: equal } ]
- [ Content-Length, { value: "16", as: equal} ]

- client-request:
method: "HEAD"
version: "1.1"
url: /with/range
headers:
fields:
- [ Host, example.com ]
- [ X-Request, request ]
- [ Range, bytes=0-5 ]
- [ uuid, 2 ]

proxy-request:
headers:
fields:
- [ Range, { as: present } ]

server-response:
status: 206
headers:
fields:
- [ Content-Length, 6 ]
- [ X-Response, response ]
- [ Content-Range, bytes 0-5/16 ]

proxy-response:
status: 206
headers:
fields:
- [ Content-Length, { value: "6", as: equal} ]
- [ Content-Range, { value: "bytes 0-5/16", as: equal} ]
- [ X-Response, { value: response, as: equal } ]
70 changes: 70 additions & 0 deletions tests/gold_tests/pluginTest/slice/slice_rm_range.test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
'''
Verify ATS slice plugin config: @pparam=--strip-range-for-head
'''
# 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.

Test.Summary = '''
Verify ATS slice plugin config: @pparam=--strip-range-for-head
'''
Test.SkipUnless(
Condition.PluginExists('slice.so'),
Condition.PluginExists('cache_range_requests.so'),
)


class SliceStripRangeForHeadRequestTest:
replay_file = "replay/slice_range.replay.yaml"

def __init__(self):
"""Initialize the Test processes for the test runs."""
self._server = Test.MakeVerifierServerProcess("server", SliceStripRangeForHeadRequestTest.replay_file)
self._configure_trafficserver()

def _configure_trafficserver(self):
"""Configure Traffic Server."""
self._ts = Test.MakeATSProcess("ts", enable_cache=False)

self._ts.Disk.remap_config.AddLines([
f"map /no/range http://127.0.0.1:{self._server.Variables.http_port} \
@plugin=slice.so @pparam=--blockbytes-test=10 @pparam=--strip-range-for-head \
@plugin=cache_range_requests.so",
f"map /with/range http://127.0.0.1:{self._server.Variables.http_port} \
@plugin=slice.so @pparam=--blockbytes-test=10 \
@plugin=cache_range_requests.so",
])

self._ts.Disk.records_config.update({
'proxy.config.diags.debug.enabled': 1,
'proxy.config.diags.debug.tags': 'http|slice|cache_range_requests',
})

def _test_head_request_range_header(self):
tr = Test.AddTestRun()

tr.AddVerifierClientProcess(
"client",
SliceStripRangeForHeadRequestTest.replay_file,
http_ports=[self._ts.Variables.port])

tr.Processes.Default.StartBefore(self._server)
tr.Processes.Default.StartBefore(self._ts)

def run(self):
self._test_head_request_range_header()


SliceStripRangeForHeadRequestTest().run()