This is an automated email from the ASF dual-hosted git repository.
zwoop pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
The following commit(s) were added to refs/heads/master by this push:
new 627f5071ea hrw4u: Fix section placement for hookless rules in u4wrh
(#12956)
627f5071ea is described below
commit 627f5071ea83c1a2c06292e4abdb2daaa17e4119
Author: Leif Hedstrom <[email protected]>
AuthorDate: Tue Mar 17 09:12:52 2026 -0700
hrw4u: Fix section placement for hookless rules in u4wrh (#12956)
Old header_rewrite rules without an explicit hook condition
default to REMAP. When u4wrh converted these, the section
opened inside the if-block instead of wrapping it. Also emit
comments inline inside if-blocks instead of deferring them
to after the section closes, and remove the now-unused
deferred comment machinery. In the forward direction, indent
block-level comments at the statement level.
Co-Authored-By: Keele Clendenin
---
tools/hrw4u/src/hrw_visitor.py | 38 +++++++++++++---------
tools/hrw4u/src/visitor.py | 2 +-
tools/hrw4u/tests/data/conds/exceptions.txt | 2 ++
tools/hrw4u/tests/data/conds/no-hook.input.txt | 6 ++++
tools/hrw4u/tests/data/conds/no-hook.output.txt | 3 ++
.../tests/data/examples/all-nonsense.output.txt | 8 ++---
6 files changed, 39 insertions(+), 20 deletions(-)
diff --git a/tools/hrw4u/src/hrw_visitor.py b/tools/hrw4u/src/hrw_visitor.py
index 3dbdfd6208..2878da0be2 100644
--- a/tools/hrw4u/src/hrw_visitor.py
+++ b/tools/hrw4u/src/hrw_visitor.py
@@ -57,7 +57,8 @@ class HRWInverseVisitor(u4wrhVisitor, BaseHRWVisitor):
self._if_depth = 0 # Track nesting depth of if blocks
self._in_elif_mode = False
self._just_closed_nested = False
- self._deferred_comments: list[str] = []
+
+ self._pre_section_if_start: int | None = None
@lru_cache(maxsize=128)
def _cached_percent_parsing(self, pct_text: str) -> tuple[str, str | None]:
@@ -84,12 +85,6 @@ class HRWInverseVisitor(u4wrhVisitor, BaseHRWVisitor):
self._in_group = False
self._group_terms.clear()
- def _flush_deferred_comments(self) -> None:
- """Emit comments that were deferred while inside a rule's if-block."""
- for comment in self._deferred_comments:
- self.output.append(comment)
- self._deferred_comments.clear()
-
def _start_new_section(self, section_type: SectionType) -> None:
"""Start a new section, handling continuation of existing sections."""
with self.debug_context(f"start_section {section_type.value}"):
@@ -100,12 +95,10 @@ class HRWInverseVisitor(u4wrhVisitor, BaseHRWVisitor):
self.emit("}")
self._if_depth -= 1
self._reset_condition_state()
- self._flush_deferred_comments()
if self.output and self.output[-1] != "":
self.output.append("")
return
- prev = bool(self.output)
had_section = self._section_opened
self._close_if_and_section()
self._reset_condition_state()
@@ -113,8 +106,6 @@ class HRWInverseVisitor(u4wrhVisitor, BaseHRWVisitor):
if had_section and self.output and self.output[-1] != "":
self.output.append("")
- self._flush_deferred_comments()
-
self._section_label = section_type
self.emit(f"{section_type.value} {{")
self._section_opened = True
@@ -162,7 +153,6 @@ class HRWInverseVisitor(u4wrhVisitor, BaseHRWVisitor):
for line in ctx.line():
self.visit(line)
self._close_if_and_section()
- self._flush_deferred_comments()
var_declarations = self.symbol_resolver.get_var_declarations()
if var_declarations:
@@ -178,9 +168,7 @@ class HRWInverseVisitor(u4wrhVisitor, BaseHRWVisitor):
with self.debug_context("visitCommentLine"):
comment_text = ctx.COMMENT().getText()
self._flush_pending_condition()
- if self._if_depth > 0:
- self._deferred_comments.append(comment_text)
- elif self._section_opened:
+ if self._if_depth > 0 or self._section_opened:
self.emit(comment_text)
else:
self.output.append(comment_text)
@@ -407,10 +395,27 @@ class HRWInverseVisitor(u4wrhVisitor, BaseHRWVisitor):
def _ensure_section_open(self, section_label: SectionType) -> None:
"""Ensure a section is open for statements."""
if not self._section_opened:
+ relocated_lines = None
+ relocated_if_depth = 0
+ if self._if_depth > 0 and self._pre_section_if_start is not None:
+ relocated_lines = self.output[self._pre_section_if_start:]
+ relocated_if_depth = self._if_depth
+ self.output = self.output[:self._pre_section_if_start]
+ self.stmt_indent -= self._if_depth
+ self._if_depth = 0
+ self._pre_section_if_start = None
+
self.emit(f"{section_label.value} {{")
self._section_opened = True
self.increase_indent()
+ if relocated_lines:
+ indent_prefix = " " * SystemDefaults.INDENT_SPACES
+ for line in relocated_lines:
+ self.output.append(indent_prefix + line if line.strip()
else line)
+ self._if_depth = relocated_if_depth
+ self.stmt_indent += relocated_if_depth
+
def _start_elif_mode(self) -> None:
"""Handle elif line transitions."""
# After endif, we need to close the parent if-statement
@@ -432,6 +437,9 @@ class HRWInverseVisitor(u4wrhVisitor, BaseHRWVisitor):
def _start_if_block(self, condition_expr: str) -> None:
"""Start a new if block."""
+ if not self._section_opened and self._pre_section_if_start is None:
+ self._pre_section_if_start = len(self.output)
+
if self._in_elif_mode:
self.emit(f"}} elif {condition_expr} {{")
self._in_elif_mode = False
diff --git a/tools/hrw4u/src/visitor.py b/tools/hrw4u/src/visitor.py
index 90ea932e68..68182fb2b9 100644
--- a/tools/hrw4u/src/visitor.py
+++ b/tools/hrw4u/src/visitor.py
@@ -830,7 +830,7 @@ class HRW4UVisitor(hrw4uVisitor, BaseHRWVisitor):
with self.debug_context("visitCommentLine"):
comment_text = ctx.COMMENT().getText()
self.debug(f"preserving comment: {comment_text}")
- self.output.append(comment_text)
+ self.emit_line(comment_text, self.stmt_indent)
def visitStatement(self, ctx) -> None:
with self.debug_context("visitStatement"), self.trap(ctx):
diff --git a/tools/hrw4u/tests/data/conds/exceptions.txt
b/tools/hrw4u/tests/data/conds/exceptions.txt
index 86e44106ba..fd12cfd4a0 100644
--- a/tools/hrw4u/tests/data/conds/exceptions.txt
+++ b/tools/hrw4u/tests/data/conds/exceptions.txt
@@ -5,3 +5,5 @@
implicit-cmp.input: u4wrh
# Double negation !(x != y) emits GROUP/GROUP:END [NOT] pairs; reverse can't
reconstruct the original form
double-negation.input: hrw4u
+# Old format without explicit hook defaults to REMAP; hrw4u always emits
explicit sections
+no-hook.input: u4wrh
diff --git a/tools/hrw4u/tests/data/conds/no-hook.input.txt
b/tools/hrw4u/tests/data/conds/no-hook.input.txt
new file mode 100644
index 0000000000..603acdb71a
--- /dev/null
+++ b/tools/hrw4u/tests/data/conds/no-hook.input.txt
@@ -0,0 +1,6 @@
+REMAP {
+ if inbound.req.Debug {
+ # to return the debug header if http header debug: on
+ inbound.req.@DebugHeader = "TRUE";
+ }
+}
diff --git a/tools/hrw4u/tests/data/conds/no-hook.output.txt
b/tools/hrw4u/tests/data/conds/no-hook.output.txt
new file mode 100644
index 0000000000..c57dcec7e5
--- /dev/null
+++ b/tools/hrw4u/tests/data/conds/no-hook.output.txt
@@ -0,0 +1,3 @@
+cond %{CLIENT-HEADER:Debug} ="" [NOT]
+# to return the debug header if http header debug: on
+set-header @DebugHeader "TRUE"
diff --git a/tools/hrw4u/tests/data/examples/all-nonsense.output.txt
b/tools/hrw4u/tests/data/examples/all-nonsense.output.txt
index bb15eb068e..c8672c1f28 100644
--- a/tools/hrw4u/tests/data/examples/all-nonsense.output.txt
+++ b/tools/hrw4u/tests/data/examples/all-nonsense.output.txt
@@ -93,7 +93,7 @@ cond %{GROUP}
cond %{GROUP:END}
skip-remap TRUE
no-op [L]
-# like [L]
+ # like [L]
cond %{READ_REQUEST_HDR_HOOK} [AND]
# Header presence / equality and capture groups
@@ -132,9 +132,9 @@ cond %{GROUP}
cond %{GROUP:END}
counter "write_methods_seen"
set-state-int8 0 42
-# assign int8
+ # assign int8
set-state-int16 0 6553
-# assign int16
+ # assign int16
cond %{SEND_REQUEST_HDR_HOOK} [AND]
# Use server URL information to adjust Host header
@@ -174,7 +174,7 @@ elif
cond %{CACHE} ("miss","skipped")
cond %{GROUP:END}
set-header X-Cache "%{CACHE}"
-# echo the value
+ # echo the value
# Status transforms + reason
cond %{READ_RESPONSE_HDR_HOOK} [AND]