Skip to content
Open
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
25 changes: 25 additions & 0 deletions plugins/authproxy/authproxy.cc
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,16 @@ AuthWriteHeadRequest(AuthRequestContext *auth)
// Next, we need to rewrite the client request URL to be a HEAD request.
TSReleaseAssert(TSHttpHdrMethodSet(rq.buffer, rq.header, TS_HTTP_METHOD_HEAD, -1) == TS_SUCCESS);

// This sub-request is bodyless (HEAD + Content-Length: 0), but the copied
// client request may carry request-body framing (e.g. a chunked POST or
// Expect: 100-continue). Left in place it is self-contradictory: ATS sets up
// a request-body tunnel for a body that never arrives (stalling the probe
// until timeout), and proxy.config.http.reject_head_with_content rejects a
// HEAD that declares content. Strip the framing when forcing Content-Length: 0.
HttpRemoveMimeHeader(rq.buffer, rq.header, TS_MIME_FIELD_TRANSFER_ENCODING);
HttpRemoveMimeHeader(rq.buffer, rq.header, "Trailer");
HttpRemoveMimeHeader(rq.buffer, rq.header, TS_MIME_FIELD_EXPECT);

HttpSetMimeHeader(rq.buffer, rq.header, TS_MIME_FIELD_CONTENT_LENGTH, 0u);
Comment thread
moonchen marked this conversation as resolved.
HttpSetMimeHeader(rq.buffer, rq.header, TS_MIME_FIELD_CACHE_CONTROL, "no-cache");

Expand Down Expand Up @@ -333,6 +343,13 @@ AuthWriteRangeRequest(AuthRequestContext *auth)
TSReleaseAssert(TSHttpHdrMethodSet(rq.buffer, rq.header, TS_HTTP_METHOD_GET, -1) == TS_SUCCESS);
}

// The body is dropped (Content-Length: 0), so strip any request-body framing
// (Transfer-Encoding/Trailer/Expect) copied from the client request to keep
// the sub-request well-formed.
HttpRemoveMimeHeader(rq.buffer, rq.header, TS_MIME_FIELD_TRANSFER_ENCODING);
HttpRemoveMimeHeader(rq.buffer, rq.header, "Trailer");
HttpRemoveMimeHeader(rq.buffer, rq.header, TS_MIME_FIELD_EXPECT);

HttpSetMimeHeader(rq.buffer, rq.header, TS_MIME_FIELD_CONTENT_LENGTH, 0u);
Comment thread
moonchen marked this conversation as resolved.
HttpSetMimeHeader(rq.buffer, rq.header, TS_MIME_FIELD_RANGE, "bytes=0-0");
HttpSetMimeHeader(rq.buffer, rq.header, TS_MIME_FIELD_CACHE_CONTROL, "no-cache");
Expand Down Expand Up @@ -386,6 +403,14 @@ AuthWriteRedirectedRequest(AuthRequestContext *auth)
TSHandleMLocRelease(rq.buffer, rq.header, murl);

HttpSetMimeHeader(rq.buffer, rq.header, TS_MIME_FIELD_HOST, hostbuf);

// The body is dropped (Content-Length: 0), so strip any request-body framing
// (Transfer-Encoding/Trailer/Expect) copied from the client request to keep
// the sub-request well-formed.
HttpRemoveMimeHeader(rq.buffer, rq.header, TS_MIME_FIELD_TRANSFER_ENCODING);
HttpRemoveMimeHeader(rq.buffer, rq.header, "Trailer");
HttpRemoveMimeHeader(rq.buffer, rq.header, TS_MIME_FIELD_EXPECT);

HttpSetMimeHeader(rq.buffer, rq.header, TS_MIME_FIELD_CONTENT_LENGTH, 0u);
Comment thread
moonchen marked this conversation as resolved.
HttpSetMimeHeader(rq.buffer, rq.header, TS_MIME_FIELD_CACHE_CONTROL, "no-cache");

Expand Down
12 changes: 12 additions & 0 deletions plugins/authproxy/utils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,18 @@ HttpSetMimeHeader(TSMBuffer mbuf, TSMLoc mhdr, const std::string_view name, cons
TSHandleMLocRelease(mbuf, mhdr, mloc);
}

void
HttpRemoveMimeHeader(TSMBuffer mbuf, TSMLoc mhdr, const char *name)
{
TSMLoc mloc;

// A field may be repeated on multiple lines; destroy every instance.
while ((mloc = TSMimeHdrFieldFind(mbuf, mhdr, name, -1)) != TS_NULL_MLOC) {
TSReleaseAssert(TSMimeHdrFieldDestroy(mbuf, mhdr, mloc) == TS_SUCCESS);
TSHandleMLocRelease(mbuf, mhdr, mloc);
}
}

unsigned
HttpGetContentLength(TSMBuffer mbuf, TSMLoc mhdr)
{
Expand Down
3 changes: 3 additions & 0 deletions plugins/authproxy/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ void HttpSetMimeHeader(TSMBuffer mbuf, TSMLoc mhdr, const char *name, const char
void HttpSetMimeHeader(TSMBuffer mbuf, TSMLoc mhdr, const char *name, unsigned value);
void HttpSetMimeHeader(TSMBuffer mbuf, TSMLoc mhdr, const std::string_view name, const std::string_view value);

// Remove every instance of an HTTP header.
void HttpRemoveMimeHeader(TSMBuffer mbuf, TSMLoc mhdr, const char *name);

// Dump the given HTTP header to the debug log.
void HttpDebugHeader(TSMBuffer mbuf, TSMLoc mhdr);

Expand Down