Copilot commented on code in PR #13420:
URL: https://github.com/apache/trafficserver/pull/13420#discussion_r4137534868


##########
src/proxy/http/HttpSM.cc:
##########
@@ -7196,7 +7213,15 @@ HttpSM::setup_server_send_request()
   // We need a reader so bytes don't fall off the end of
   //  the buffer
   IOBufferReader *buf_start = server_entry->write_buffer->alloc_reader();
-  server_request_hdr_bytes = hdr_length = 
write_header_into_buffer(&t_state.hdr_info.server_request, 
server_entry->write_buffer);
+
+  if (server_txn->supports_direct_header_passing()) {
+    _server_request_header_is_ready = true;
+    // Only the write buffer is empty; retry decisions and stats need the real 
size.
+    server_request_hdr_bytes = t_state.hdr_info.server_request.length_get();
+    hdr_length               = 0;

Review Comment:
   For an outbound HTTP/2 request without a buffered body, `hdr_length = 0` 
makes the write VIO's `nbytes` zero even while its HEADERS frame is still 
pending. If inactivity times out before the stream emits HEADERS, 
`handle_server_setup_error()` checks `nbytes > 0` and labels it 
`INACTIVE_TIMEOUT`; `is_request_retryable()` then refuses to retry a POST 
because `server_request_hdr_bytes` is nonzero, although nothing reached the 
origin. Track whether the outbound header was actually emitted and use that 
state for timeout classification, while retaining the no-retry behavior once it 
has been sent.



##########
src/proxy/http2/Http2Stream.cc:
##########
@@ -327,6 +372,70 @@ Http2Stream::send_headers(Http2ConnectionState & /* cstate 
ATS_UNUSED */)
     this->_http_sm_id = this->_sm->sm_id;
   }
 
+  // parse_req is skipped here, so re-apply its checks. Both run after the 
REQUEST type check
+  // below, since the accessors assert that polarity.
+  auto uri_ok = [&]() {
+    int const level = this->_sm->t_state.http_config_param->strict_uri_parsing;
+
+    return level == 0 ||
+           (url_is_uri_compliant(level, _receive_header.path_get()) && 
url_is_uri_compliant(level, _receive_header.query_get()) &&
+            url_is_uri_compliant(level, _receive_header.fragment_get()));
+  };
+
+  auto parse_req_would_accept = [&]() {
+    auto const *config    = this->_sm->t_state.http_config_param;
+    auto const  line_max  = 
static_cast<size_t>(config->http_request_line_max_size);
+    auto const  field_max = 
static_cast<size_t>(config->http_hdr_field_max_size);
+    auto        method{_receive_header.method_get()};
+
+    if (method.empty() || std::any_of(method.begin(), method.end(), [](char c) 
{ return !ParseRules::is_token(c); })) {
+      return false;
+    }
+    // Upper bound of the serialized "METHOD URL HTTP/1.1\r\n", so parse_req 
makes the exact call.
+    if (method.size() + 
static_cast<size_t>(_receive_header.url_get()->length_get()) + 12 > line_max) {
+      return false;
+    }
+    for (auto const &field : _receive_header) {
+      auto name{field.name_get()};
+      auto value{field.value_get()};
+
+      // parse_req drops a line whose name starts with a non-token and trims 
whitespace around values.
+      if (name.empty() || name.size() + value.size() > field_max || 
(!ParseRules::is_token(name.front()) && name.front() != '@') ||
+          (!value.empty() && (ParseRules::is_ws(value.front()) || 
ParseRules::is_ws(value.back())))) {

Review Comment:
   Checking only the first character lets an HTTP/2 field such as `x(foo` take 
the direct path. The old `parse_req()` path calls `mime_parser_parse()`, which 
rejects `(` in a field name via `ParseRules::is_http_field_name()` 
(`src/proxy/hdrs/MIME.cc:2602-2607`); the new `(foo` test covers only invalid 
*first* characters. Validate every character before passing the decoded header 
to HttpSM so this malformed field falls back to the former parser/rejection 
path.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to