From 8399a9ece7a7a9754eebbad30da42afd62db6a1d Mon Sep 17 00:00:00 2001 From: yusing Date: Sat, 10 Jan 2026 18:40:53 +0800 Subject: [PATCH] fix(rules): update error handling and validate command execution order - Changed error returned for invalid arguments in CommandPass and CommandPassAlt to ErrExpectNoArg. - Added validation to ensure response handlers are the last commands in the execution order. - Updated error messages for command sequence validation to clarify requirements for terminating and bypass commands. --- internal/route/rules/do.go | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/internal/route/rules/do.go b/internal/route/rules/do.go index 4a4a17d4..65477fc3 100644 --- a/internal/route/rules/do.go +++ b/internal/route/rules/do.go @@ -524,7 +524,7 @@ func (cmd *Command) Parse(v string) error { if directive == CommandPass || directive == CommandPassAlt { if len(args) != 0 { - return ErrInvalidArguments.Subject(directive) + return ErrExpectNoArg } executors = append(executors, BypassCommand{}) continue @@ -569,12 +569,34 @@ func (cmd *Command) Parse(v string) error { } func buildCmd(executors []CommandHandler) (cmd CommandHandler, err error) { + // Validate the execution order. + // + // This allows sequences like: + // route ws-api + // log info /dev/stdout "..." + // where the first command is request-phase and the last is response-phase. + lastNonResp := -1 + seenResp := false for i, exec := range executors { + if exec.IsResponseHandler() { + seenResp = true + continue + } + if seenResp { + return nil, ErrInvalidCommandSequence.Withf("response handlers must be the last commands") + } + lastNonResp = i + } + + for i, exec := range executors { + if i > lastNonResp { + break // response-handler tail + } switch exec.(type) { case TerminatingCommand, BypassCommand: - if i != len(executors)-1 { + if i != lastNonResp { return nil, ErrInvalidCommandSequence. - Withf("a returning / bypass command must be the last command") + Withf("a response handler or terminating/bypass command must be the last command") } } }