mirror of
https://github.com/yusing/godoxy.git
synced 2026-03-31 22:23:14 +02:00
refactor(rules): introduce block DSL, phase-based execution, and flow validation
- add block syntax parser/scanner with nested @blocks and elif/else support - restructure rule execution into explicit pre/post phases with phase flags - classify commands by phase and termination behavior - enforce flow semantics (default rule handling, dead-rule detection) - expand HTTP flow coverage with block + YAML parity tests and benches - refresh rules README/spec and update playground/docs integration
This commit is contained in:
@@ -1,79 +1,62 @@
|
||||
package rules
|
||||
|
||||
import "net/http"
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
httputils "github.com/yusing/goutils/http"
|
||||
)
|
||||
|
||||
var errTerminateRule = errors.New("terminate rule")
|
||||
|
||||
type (
|
||||
handlerFunc func(w http.ResponseWriter, r *http.Request) error
|
||||
HandlerFunc func(w *httputils.ResponseModifier, r *http.Request, upstream http.HandlerFunc) error
|
||||
Handler struct {
|
||||
fn HandlerFunc
|
||||
phase PhaseFlag
|
||||
terminate bool
|
||||
}
|
||||
|
||||
CommandHandler interface {
|
||||
// CommandHandler can read and modify the values
|
||||
// then handle the request
|
||||
// finally proceed to next command (or return) base on situation
|
||||
Handle(w http.ResponseWriter, r *http.Request) error
|
||||
IsResponseHandler() bool
|
||||
ServeHTTP(w *httputils.ResponseModifier, r *http.Request, upstream http.HandlerFunc) error
|
||||
Phase() PhaseFlag
|
||||
}
|
||||
// NonTerminatingCommand will run then proceed to next command or reverse proxy.
|
||||
NonTerminatingCommand handlerFunc
|
||||
// TerminatingCommand will run then return immediately.
|
||||
TerminatingCommand handlerFunc
|
||||
// OnResponseCommand will run then return based on the response.
|
||||
OnResponseCommand handlerFunc
|
||||
// BypassCommand will skip all the following commands
|
||||
// and directly return to reverse proxy.
|
||||
BypassCommand struct{}
|
||||
|
||||
// Commands is a slice of CommandHandler.
|
||||
Commands []CommandHandler
|
||||
)
|
||||
|
||||
func (c NonTerminatingCommand) Handle(w http.ResponseWriter, r *http.Request) error {
|
||||
return c(w, r)
|
||||
func (h Handler) ServeHTTP(w *httputils.ResponseModifier, r *http.Request, upstream http.HandlerFunc) error {
|
||||
return h.fn(w, r, upstream)
|
||||
}
|
||||
|
||||
func (c NonTerminatingCommand) IsResponseHandler() bool {
|
||||
return false
|
||||
func (h Handler) Phase() PhaseFlag {
|
||||
return h.phase
|
||||
}
|
||||
|
||||
func (c TerminatingCommand) Handle(w http.ResponseWriter, r *http.Request) error {
|
||||
if err := c(w, r); err != nil {
|
||||
return err
|
||||
}
|
||||
return errTerminated
|
||||
func (h Handler) Terminates() bool {
|
||||
return h.terminate
|
||||
}
|
||||
|
||||
func (c TerminatingCommand) IsResponseHandler() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (c OnResponseCommand) Handle(w http.ResponseWriter, r *http.Request) error {
|
||||
return c(w, r)
|
||||
}
|
||||
|
||||
func (c OnResponseCommand) IsResponseHandler() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (c BypassCommand) Handle(w http.ResponseWriter, r *http.Request) error {
|
||||
return errTerminated
|
||||
}
|
||||
|
||||
func (c BypassCommand) IsResponseHandler() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (c Commands) Handle(w http.ResponseWriter, r *http.Request) error {
|
||||
func (c Commands) ServeHTTP(w *httputils.ResponseModifier, r *http.Request, upstream http.HandlerFunc) error {
|
||||
for _, cmd := range c {
|
||||
if err := cmd.Handle(w, r); err != nil {
|
||||
err := cmd.ServeHTTP(w, r, upstream)
|
||||
if err != nil {
|
||||
// Terminating actions stop the command chain immediately.
|
||||
// Will be handled by the caller.
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c Commands) IsResponseHandler() bool {
|
||||
func (c Commands) Phase() PhaseFlag {
|
||||
req := PhaseNone
|
||||
for _, cmd := range c {
|
||||
if cmd.IsResponseHandler() {
|
||||
return true
|
||||
}
|
||||
req |= cmd.Phase()
|
||||
}
|
||||
return false
|
||||
return req
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user