mirror of
https://github.com/yusing/godoxy.git
synced 2025-06-09 13:02:33 +02:00
add help messages to rules, updat url validation
This commit is contained in:
parent
4aee44fe11
commit
9d701ad671
4 changed files with 126 additions and 8 deletions
|
@ -36,10 +36,18 @@ const (
|
|||
)
|
||||
|
||||
var commands = map[string]struct {
|
||||
help Help
|
||||
validate ValidateFunc
|
||||
build func(args any) *CommandExecutor
|
||||
}{
|
||||
CommandRewrite: {
|
||||
help: Help{
|
||||
command: CommandRewrite,
|
||||
args: map[string]string{
|
||||
"from": "the path to rewrite, must start with /",
|
||||
"to": "the path to rewrite to, must start with /",
|
||||
},
|
||||
},
|
||||
validate: func(args []string) (any, E.Error) {
|
||||
if len(args) != 2 {
|
||||
return nil, ErrExpectTwoArgs
|
||||
|
@ -68,6 +76,12 @@ var commands = map[string]struct {
|
|||
},
|
||||
},
|
||||
CommandServe: {
|
||||
help: Help{
|
||||
command: CommandServe,
|
||||
args: map[string]string{
|
||||
"root": "the file system path to serve, must be an existing directory",
|
||||
},
|
||||
},
|
||||
validate: validateFSPath,
|
||||
build: func(args any) *CommandExecutor {
|
||||
root := args.(string)
|
||||
|
@ -80,6 +94,12 @@ var commands = map[string]struct {
|
|||
},
|
||||
},
|
||||
CommandRedirect: {
|
||||
help: Help{
|
||||
command: CommandRedirect,
|
||||
args: map[string]string{
|
||||
"to": "the url to redirect to, can be relative or absolute URL",
|
||||
},
|
||||
},
|
||||
validate: validateURL,
|
||||
build: func(args any) *CommandExecutor {
|
||||
target := args.(types.URL).String()
|
||||
|
@ -92,6 +112,13 @@ var commands = map[string]struct {
|
|||
},
|
||||
},
|
||||
CommandError: {
|
||||
help: Help{
|
||||
command: CommandError,
|
||||
args: map[string]string{
|
||||
"code": "the http status code to return",
|
||||
"text": "the error message to return",
|
||||
},
|
||||
},
|
||||
validate: func(args []string) (any, E.Error) {
|
||||
if len(args) != 2 {
|
||||
return nil, ErrExpectTwoArgs
|
||||
|
@ -118,7 +145,13 @@ var commands = map[string]struct {
|
|||
},
|
||||
},
|
||||
CommandProxy: {
|
||||
validate: validateURL,
|
||||
help: Help{
|
||||
command: CommandProxy,
|
||||
args: map[string]string{
|
||||
"to": "the url to proxy to, must be an absolute URL",
|
||||
},
|
||||
},
|
||||
validate: validateAbsoluteURL,
|
||||
build: func(args any) *CommandExecutor {
|
||||
target := args.(types.URL)
|
||||
if target.Scheme == "" {
|
||||
|
@ -166,7 +199,7 @@ func (cmd *Command) Parse(v string) error {
|
|||
}
|
||||
validArgs, err := builder.validate(args)
|
||||
if err != nil {
|
||||
return err.Subject(directive)
|
||||
return err.Subject(directive).Withf("%s", builder.help.String())
|
||||
}
|
||||
|
||||
exec := builder.build(validArgs)
|
||||
|
|
35
internal/route/rules/help.go
Normal file
35
internal/route/rules/help.go
Normal file
|
@ -0,0 +1,35 @@
|
|||
package rules
|
||||
|
||||
import "strings"
|
||||
|
||||
type Help struct {
|
||||
command string
|
||||
args map[string]string // args[arg] -> description
|
||||
}
|
||||
|
||||
/*
|
||||
Generate help string, e.g.
|
||||
|
||||
rewrite <from> <to>
|
||||
from: the path to rewrite, must start with /
|
||||
to: the path to rewrite to, must start with /
|
||||
*/
|
||||
func (h *Help) String() string {
|
||||
var sb strings.Builder
|
||||
sb.WriteString(h.command)
|
||||
sb.WriteString(" ")
|
||||
for arg := range h.args {
|
||||
sb.WriteRune('<')
|
||||
sb.WriteString(arg)
|
||||
sb.WriteString("> ")
|
||||
}
|
||||
sb.WriteRune('\n')
|
||||
for arg, desc := range h.args {
|
||||
sb.WriteRune('\t')
|
||||
sb.WriteString(arg)
|
||||
sb.WriteString(": ")
|
||||
sb.WriteString(desc)
|
||||
sb.WriteRune('\n')
|
||||
}
|
||||
return sb.String()
|
||||
}
|
|
@ -26,28 +26,55 @@ const (
|
|||
)
|
||||
|
||||
var checkers = map[string]struct {
|
||||
help Help
|
||||
validate ValidateFunc
|
||||
check func(r *http.Request, args any) bool
|
||||
}{
|
||||
OnHeader: { // header <key> <value>
|
||||
OnHeader: {
|
||||
help: Help{
|
||||
command: OnHeader,
|
||||
args: map[string]string{
|
||||
"key": "the header key",
|
||||
"value": "the header value",
|
||||
},
|
||||
},
|
||||
validate: toStrTuple,
|
||||
check: func(r *http.Request, args any) bool {
|
||||
return r.Header.Get(args.(StrTuple).First) == args.(StrTuple).Second
|
||||
},
|
||||
},
|
||||
OnQuery: { // query <key> <value>
|
||||
OnQuery: {
|
||||
help: Help{
|
||||
command: OnQuery,
|
||||
args: map[string]string{
|
||||
"key": "the query key",
|
||||
"value": "the query value",
|
||||
},
|
||||
},
|
||||
validate: toStrTuple,
|
||||
check: func(r *http.Request, args any) bool {
|
||||
return r.URL.Query().Get(args.(StrTuple).First) == args.(StrTuple).Second
|
||||
},
|
||||
},
|
||||
OnMethod: { // method <method>
|
||||
OnMethod: {
|
||||
help: Help{
|
||||
command: OnMethod,
|
||||
args: map[string]string{
|
||||
"method": "the http method",
|
||||
},
|
||||
},
|
||||
validate: validateMethod,
|
||||
check: func(r *http.Request, method any) bool {
|
||||
return r.Method == method.(string)
|
||||
},
|
||||
},
|
||||
OnPath: { // path <path>
|
||||
OnPath: {
|
||||
help: Help{
|
||||
command: OnPath,
|
||||
args: map[string]string{
|
||||
"path": "the request path, must start with /",
|
||||
},
|
||||
},
|
||||
validate: validateURLPath,
|
||||
check: func(r *http.Request, globPath any) bool {
|
||||
reqPath := r.URL.Path
|
||||
|
@ -57,7 +84,13 @@ var checkers = map[string]struct {
|
|||
return strutils.GlobMatch(globPath.(string), reqPath)
|
||||
},
|
||||
},
|
||||
OnRemote: { // remote <ip|cidr>
|
||||
OnRemote: {
|
||||
help: Help{
|
||||
command: OnRemote,
|
||||
args: map[string]string{
|
||||
"ip|cidr": "the remote ip or cidr",
|
||||
},
|
||||
},
|
||||
validate: validateCIDR,
|
||||
check: func(r *http.Request, cidr any) bool {
|
||||
host, _, err := net.SplitHostPort(r.RemoteAddr)
|
||||
|
@ -137,7 +170,7 @@ func parseOn(line string) (Checkers, E.Error) {
|
|||
|
||||
validArgs, err := checker.validate(args)
|
||||
if err != nil {
|
||||
return nil, err.Subject(subject)
|
||||
return nil, err.Subject(subject).Withf("%s", checker.help.String())
|
||||
}
|
||||
|
||||
return Checkers{
|
||||
|
|
|
@ -35,6 +35,23 @@ func validateURL(args []string) (any, E.Error) {
|
|||
return u, nil
|
||||
}
|
||||
|
||||
func validateAbsoluteURL(args []string) (any, E.Error) {
|
||||
if len(args) != 1 {
|
||||
return nil, ErrExpectOneArg
|
||||
}
|
||||
u, err := types.ParseURL(args[0])
|
||||
if err != nil {
|
||||
return nil, ErrInvalidArguments.With(err)
|
||||
}
|
||||
if u.Scheme == "" {
|
||||
u.Scheme = "http"
|
||||
}
|
||||
if u.Host == "" {
|
||||
return nil, ErrInvalidArguments.Withf("missing host")
|
||||
}
|
||||
return u, nil
|
||||
}
|
||||
|
||||
func validateCIDR(args []string) (any, E.Error) {
|
||||
if len(args) != 1 {
|
||||
return nil, ErrExpectOneArg
|
||||
|
|
Loading…
Add table
Reference in a new issue