Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

annotate_client did not annotate error:* transactions #256

Open
wants to merge 12 commits into
base: master
Choose a base branch
from

Conversation

eduard-bagdasaryan
Copy link

@eduard-bagdasaryan eduard-bagdasaryan commented Jun 10, 2024

cc71dd7 introduced an admin-level BUG requirement that a non-empty
message pipeline means an existing HttpRequest object. That requirement
was incorrect because when the pipeline receives the HttpStream object
(returned by ConnStateData::parseOneRequest()), the corresponding
HttpRequest is not created yet (an may be not created at all, depending
on further checks). Now, instead of demanding HttpRequest
presence in annotate_client, we annotate requests if/when they get
created (and imported into ClientHttpRequest) by copying the existing
connection annotation. That copying already worked for successfully
parsed and fake HttpRequests, but was missing for error-uri requests
(such as "error:invalid-request").

Also create an HttpRequest object for 'error:' and other
tunnelOnError()-related cases as soon as possible because some
directives require it. For example, if HttpRequest is missing,
access_log fails to match some ACLs (such as 'src') and the
'error:
' transaction is not logged. Another problem caused by
missing request was that %>handshake annotations were empty
(logged as a "-") because it Format::assemble() needs an existing
ALE::request to fill this format code.

Also, on the tunnelOnError() path, do not abandon the existing
HttpRequest (and its ClientHttpRequest) in favor of the new one created
by buildFakeRequest(). Before this fix, the tunneled transaction was
represented by two 'CONNECT' access.log entries, instead of a single
one without any fake method.

cc71dd7 introduced an admin-level BUG requirement that a non-empty
message pipeline means an existing HttpRequest object. That requirement
was incorrect because when the pipeline receives the HttpStream object
(returned by ConnStateData::parseOneRequest()), the corresponding
HttpRequest is not created yet (an may be not created at all, depending
on further checks). Now, instead of demanding HttpRequest
presence in annotate_client, we annotate requests if/when they get
created (and imported into ClientHttpRequest) by copying the existing
connection annotation. That copying already worked for successfully
parsed and fake HttpRequests, but was missing for error-uri requests
(such as "error:invalid-request").

Also fill these 'error:*' HttpRequests with connection-level
information. For example, access_log takes this information from
the request, and fails to match some ACLs, such as 'src'.
clientConnectionManager = aMgr;

if (!clientConnectionManager.valid())
return;

// TODO: We fill request notes here until we find a way to verify whether
// no ACL checking is performed before ClientHttpRequest::doCallouts().
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I copied this TODO from buildHttpRequest(), for now. I'm not sure whether it is relevant now, there are some ACL checking before ClientHttpRequest::doCallouts().

if (!request) {
debugs(33, 5, "Invalid URL: " << http->uri);
// setReplyToError() requires log_uri
http->setLogUriToRawUri(http->uri, parser_->method());

const char * requestErrorBytes = inBuf.c_str();
if (!tunnelOnError(ERR_INVALID_URL)) {
setReplyError(context, request, ERR_INVALID_URL, Http::scBadRequest, requestErrorBytes);
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The request passed to all setReplyError() was either nil or it got deleted once buildHttpRequest() returned.

@@ -773,11 +773,19 @@ UpdateRequestNotes(ConnStateData *csd, HttpRequest &request, NotePairs const &he
void
HttpRequest::manager(const CbcPointer<ConnStateData> &aMgr, const AccessLogEntryPointer &al)
{
if (clientConnectionManager == aMgr)
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like that HttpRequest::manager() should not allow overwrite with the same aMgr. We can even require it with an 'Assure'.

On splice() path, we always create fake request (with SNI, if needed)
On tunnelOnError() path, the request must be created beforehand
(e.g., one of the "error:*" requests).
tunnelStart() needs an HttpRequest object initalized with the correct
destination port/host values (the fake 'error:*" is not enough). For
example, ConnStateData::borrowPinnedConnection() checks the port before
providing pinned connection.
We can create "error:*" requests even earlier than it was done
in 3b70fb3 - just after the parsing code detects an error and
aborts parsing.
This annotation is calculated via Format::assemble() and gets
an empty (dash) value if ALE::request is missing. Previous branch
commits guaranteed earlier HttpRequest creation, and now
ALE::request got the correct value.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant