@@ -20,12 +20,69 @@ import (
20
20
"context"
21
21
"fmt"
22
22
"maps"
23
+ "net/url"
24
+ "strings"
23
25
24
26
"github.com/firebase/genkit/go/core"
25
27
"github.com/firebase/genkit/go/core/api"
26
- coreresource "github.com/firebase/genkit/go/core/resource "
28
+ "github.com/yosida95/uritemplate/v3 "
27
29
)
28
30
31
+ // normalizeURI normalizes a URI for template matching by removing query parameters,
32
+ // fragments, and trailing slashes from the path.
33
+ func normalizeURI (rawURI string ) string {
34
+ // Parse the URI
35
+ u , err := url .Parse (rawURI )
36
+ if err != nil {
37
+ // If parsing fails, return the original URI
38
+ return rawURI
39
+ }
40
+
41
+ // Remove query parameters and fragment
42
+ u .RawQuery = ""
43
+ u .Fragment = ""
44
+
45
+ // Remove trailing slash from path (but not from the root path)
46
+ if len (u .Path ) > 1 && strings .HasSuffix (u .Path , "/" ) {
47
+ u .Path = strings .TrimSuffix (u .Path , "/" )
48
+ }
49
+
50
+ return u .String ()
51
+ }
52
+
53
+ // matches checks if a URI matches the given URI template.
54
+ func matches (templateStr , uri string ) (bool , error ) {
55
+ template , err := uritemplate .New (templateStr )
56
+ if err != nil {
57
+ return false , fmt .Errorf ("invalid URI template %q: %w" , templateStr , err )
58
+ }
59
+
60
+ normalizedURI := normalizeURI (uri )
61
+ values := template .Match (normalizedURI )
62
+ return len (values ) > 0 , nil
63
+ }
64
+
65
+ // extractVariables extracts variables from a URI using the given URI template.
66
+ func extractVariables (templateStr , uri string ) (map [string ]string , error ) {
67
+ template , err := uritemplate .New (templateStr )
68
+ if err != nil {
69
+ return nil , fmt .Errorf ("invalid URI template %q: %w" , templateStr , err )
70
+ }
71
+
72
+ normalizedURI := normalizeURI (uri )
73
+ values := template .Match (normalizedURI )
74
+ if len (values ) == 0 {
75
+ return nil , fmt .Errorf ("URI %q does not match template" , uri )
76
+ }
77
+
78
+ // Convert uritemplate.Values to string map
79
+ result := make (map [string ]string )
80
+ for name , value := range values {
81
+ result [name ] = value .String ()
82
+ }
83
+ return result , nil
84
+ }
85
+
29
86
// ResourceInput represents the input to a resource function.
30
87
type ResourceInput struct {
31
88
URI string `json:"uri"` // The resource URI
@@ -129,11 +186,11 @@ func (r *resource) Matches(uri string) bool {
129
186
130
187
// Check template
131
188
if template , ok := resourceMeta ["template" ].(string ); ok && template != "" {
132
- matcher , err := coreresource . NewTemplateMatcher (template )
189
+ matches , err := matches (template , uri )
133
190
if err != nil {
134
191
return false
135
192
}
136
- return matcher . Matches ( uri )
193
+ return matches
137
194
}
138
195
139
196
return false
@@ -156,11 +213,7 @@ func (r *resource) ExtractVariables(uri string) (map[string]string, error) {
156
213
157
214
// Extract from template
158
215
if template , ok := resourceMeta ["template" ].(string ); ok && template != "" {
159
- matcher , err := coreresource .NewTemplateMatcher (template )
160
- if err != nil {
161
- return nil , fmt .Errorf ("invalid template %q: %w" , template , err )
162
- }
163
- return matcher .ExtractVariables (uri )
216
+ return extractVariables (template , uri )
164
217
}
165
218
166
219
return nil , fmt .Errorf ("no URI or template found in resource metadata" )
0 commit comments