package rewriter import ( "context" "fmt" "forge.cadoles.com/cadoles/bouncer/internal/rule" "github.com/expr-lang/expr" "github.com/pkg/errors" ) type errRedirect struct { statusCode int url string } func (e *errRedirect) StatusCode() int { return e.statusCode } func (e *errRedirect) URL() string { return e.url } func (e *errRedirect) Error() string { return fmt.Sprintf("redirect %d %s", e.statusCode, e.url) } func newErrRedirect(statusCode int, url string) *errRedirect { return &errRedirect{ url: url, statusCode: statusCode, } } var _ error = &errRedirect{} func redirectFunc() expr.Option { return expr.Function( "redirect", func(params ...any) (any, error) { _, err := rule.Assert[context.Context](params[0]) if err != nil { return nil, errors.WithStack(err) } statusCode, err := rule.Assert[int](params[1]) if err != nil { return nil, errors.WithStack(err) } if statusCode < 300 || statusCode >= 400 { return nil, errors.Errorf("unexpected redirect status code '%d'", statusCode) } url, err := rule.Assert[string](params[2]) if err != nil { return nil, errors.WithStack(err) } return nil, newErrRedirect(statusCode, url) }, new(func(context.Context, int, string) bool), ) } func WithRewriterFuncs() rule.OptionFunc { return func(opts *rule.Options) { funcs := []expr.Option{ redirectFunc(), } if len(opts.Expr) == 0 { opts.Expr = make([]expr.Option, 0) } opts.Expr = append(opts.Expr, funcs...) } }