router/core/attribute_expressions.go (76 lines of code) (raw):

package core import ( "fmt" "github.com/expr-lang/expr/ast" "github.com/expr-lang/expr/vm" "github.com/wundergraph/cosmo/router/internal/expr" "github.com/wundergraph/cosmo/router/pkg/config" "go.opentelemetry.io/otel/attribute" ) // attributeExpressions maps context attributes to custom attributes. type attributeExpressions struct { // expressions is a map of expressions that can be used to resolve dynamic attributes expressions map[string]*vm.Program // expressionsWithAuth is a map of expressions that can be used to resolve dynamic attributes and acces the auth // argument expressionsWithAuth map[string]*vm.Program } type VisitorCheckForRequestAuthAccess struct { HasAuth bool } func (v *VisitorCheckForRequestAuthAccess) Visit(node *ast.Node) { if node == nil { return } if v.HasAuth { return } switch n := (*node).(type) { case *ast.MemberNode: property, propertyOk := n.Property.(*ast.StringNode) node, nodeOk := n.Node.(*ast.IdentifierNode) if propertyOk && nodeOk { if node.Value == expr.ExprRequestKey && property.Value == expr.ExprRequestAuthKey { v.HasAuth = true } } } } func newAttributeExpressions(attr []config.CustomAttribute) (*attributeExpressions, error) { attrExprMap := make(map[string]*vm.Program) attrExprMapWithAuth := make(map[string]*vm.Program) for _, a := range attr { if a.ValueFrom != nil && a.ValueFrom.Expression != "" { usesAuth := VisitorCheckForRequestAuthAccess{} prog, err := expr.CompileStringExpressionWithPatch(a.ValueFrom.Expression, &usesAuth) if err != nil { return nil, fmt.Errorf("custom attribute error, unable to compile '%s' with expression '%s': %s", a.Key, a.ValueFrom.Expression, err) } if usesAuth.HasAuth { attrExprMapWithAuth[a.Key] = prog } else { attrExprMap[a.Key] = prog } } } return &attributeExpressions{ expressions: attrExprMap, expressionsWithAuth: attrExprMapWithAuth, }, nil } func expressionAttributes(expressions map[string]*vm.Program, reqCtx *requestContext) ([]attribute.KeyValue, error) { if reqCtx == nil { return nil, nil } var result []attribute.KeyValue for exprKey, exprVal := range expressions { val, err := reqCtx.ResolveStringExpression(exprVal) if err != nil { return nil, err } result = append(result, attribute.String(exprKey, val)) } return result, nil } func (r *attributeExpressions) expressionsAttributes(reqCtx *requestContext) ([]attribute.KeyValue, error) { return expressionAttributes(r.expressions, reqCtx) } func (r *attributeExpressions) expressionsAttributesWithAuth(reqCtx *requestContext) ([]attribute.KeyValue, error) { return expressionAttributes(r.expressionsWithAuth, reqCtx) }