Skip to content

Commit

Permalink
feat(path): support wildcard characters in paths (#2)
Browse files Browse the repository at this point in the history
  • Loading branch information
polebug committed Dec 15, 2023
1 parent a41aeca commit 77413a1
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 18 deletions.
4 changes: 2 additions & 2 deletions openapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ package goapi

import (
"encoding/json"
"fmt"
"net/http"
"reflect"
"strconv"

ff "github.com/NaturalSelectionLabs/goapi/lib/flat-fields"
"github.com/NaturalSelectionLabs/goapi/lib/openapi"
Expand Down Expand Up @@ -139,7 +139,7 @@ func urlParamDoc(s jschema.Schemas, p *parsedParam) []openapi.Parameter {
if len(schema.Examples) > 0 {
for i, e := range schema.Examples {
b, _ := json.Marshal(e)
k := fmt.Sprintf("%d", i)
k := strconv.Itoa(i)

examples[k] = openapi.Example{
Summary: string(b),
Expand Down
47 changes: 31 additions & 16 deletions path.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,25 @@ var regOpenAPIPath = regexp.MustCompile(`\{([^}]+)\}`)
func newPath(path string, optionalSlash bool) (*Path, error) {
params := []string{}

// Replace OpenAPI wildcards with Go RegExp named wildcards
regexPath := regOpenAPIPath.ReplaceAllStringFunc(path, func(m string) string {
param := m[1 : len(m)-1] // Strip outer braces from parameter
params = append(params, param) // Add param to list
return "(?P<" + param + ">[^/]+)" // Replace with Go Regexp named wildcard
})

// Make sure the path starts with a "^", ends with a "$", and escape slashes
regexPath = "^" + strings.ReplaceAll(regexPath, "/", "\\/") + "$"

if optionalSlash && strings.HasSuffix(regexPath, "\\/$") {
regexPath = regexPath[:len(regexPath)-3] + "\\/?$"
var regexPath string
if strings.HasSuffix(path, "/*") {
regexPath = "^" + strings.ReplaceAll(path[:len(path)-2], "/", "\\/") + "(?:\\/(?P<wildcard>.*))?$"

params = append(params, "wildcard")
} else {
// Replace OpenAPI wildcards with Go RegExp named wildcards
regexPath = regOpenAPIPath.ReplaceAllStringFunc(path, func(m string) string {
param := m[1 : len(m)-1] // Strip outer braces from parameter
params = append(params, param) // Add param to list
return "(?P<" + param + ">[^/]+)" // Replace with Go Regexp named wildcard
})

// Make sure the path starts with a "^", ends with a "$", and escape slashes
regexPath = "^" + strings.ReplaceAll(regexPath, "/", "\\/") + "$"

if optionalSlash && strings.HasSuffix(regexPath, "\\/$") {
regexPath = regexPath[:len(regexPath)-3] + "\\/?$"
}
}

// Compile the regular expression
Expand All @@ -48,13 +55,21 @@ func (p *Path) match(path string) map[string]string {
return nil
}

params := map[string]string{}
matches := map[string]string{}

for i, name := range p.reg.SubexpNames() {
if i == 0 || name == "" {
continue
}

for i, m := range ms[1:] {
params[p.names[i]] = m
if name == "wildcard" {
matches["*"] = ms[i]
} else {
matches[name] = ms[i]
}
}

return params
return matches
}

func (p *Path) contains(v string) bool {
Expand Down
5 changes: 5 additions & 0 deletions path_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,9 @@ func TestPath(t *testing.T) {
g.E(err)

g.Eq(p.match("/a/x/c/y"), map[string]string{"b": "x", "d": "y"})

p, err = newPath("/a/*", false)
g.E(err)

g.Eq(p.match("/a/x/y"), map[string]string{"*": "x/y"})
}

0 comments on commit 77413a1

Please sign in to comment.