fix: allow special characters like periods in API route paths (#4827)

This commit is contained in:
Kevin Wan
2025-05-04 11:07:43 +08:00
committed by GitHub
parent eb0d5ad3a4
commit 493f3bad0f
2 changed files with 49 additions and 5 deletions

View File

@@ -465,6 +465,20 @@ func (p *Parser) parsePathItem() []token.Token {
if !p.advanceIfPeekTokenIs(token.IDENT) {
return nil
}
list = append(list, p.curTok)
} else if p.peekTokenIs(token.DOT) {
// Allow dot (.) in path segments for file extensions like .php, .html, etc.
if !p.nextToken() {
return nil
}
list = append(list, p.curTok)
// After a dot, we expect an identifier (e.g., .php, .html)
if !p.advanceIfPeekTokenIs(token.IDENT) {
return nil
}
list = append(list, p.curTok)
} else {
if p.peekTokenIs(token.LPAREN, token.Returns, token.AT_DOC, token.AT_HANDLER, token.SEMICOLON, token.RBRACE) {

View File

@@ -760,11 +760,6 @@ func TestParser_Parse_service(t *testing.T) {
}),
},
Request: &ast.BodyStmt{
LParen: ast.NewTokenNode(token.Token{Type: token.LPAREN, Text: "("}),
RParen: ast.NewTokenNode(token.Token{Type: token.RPAREN, Text: ")"}),
},
Returns: ast.NewTokenNode(token.Token{Type: token.IDENT, Text: "returns"}),
Response: &ast.BodyStmt{
LParen: ast.NewTokenNode(token.Token{Type: token.LPAREN, Text: "("}),
Body: &ast.BodyExpr{
Value: ast.NewTokenNode(token.Token{Type: token.IDENT, Text: "Foo"}),
@@ -1031,6 +1026,7 @@ func TestParser_Parse_pathItem(t *testing.T) {
{input: "1", expected: "1"},
{input: "11", expected: "11"},
}
for _, v := range testData {
p := New("foo.api", v.input)
ok := p.nextToken()
@@ -1066,6 +1062,38 @@ func TestParser_Parse_pathItem(t *testing.T) {
})
}
func TestParser_Parse_pathItem_WithDot(t *testing.T) {
t.Run("valid with dots", func(t *testing.T) {
var testData = []struct {
input string
expected string
}{
{input: "file.php", expected: "file.php"},
{input: "api_jsonrpc.php", expected: "api_jsonrpc.php"},
{input: "index.html", expected: "index.html"},
{input: "data.json", expected: "data.json"},
{input: "style.css", expected: "style.css"},
{input: "script.js", expected: "script.js"},
{input: "document.pdf", expected: "document.pdf"},
{input: "image.png", expected: "image.png"},
{input: "api.v1", expected: "api.v1"},
{input: "resource.with.multiple.dots", expected: "resource.with.multiple.dots"},
}
for _, v := range testData {
p := New("foo.api", v.input)
ok := p.nextToken()
assert.True(t, ok)
tokens := p.parsePathItem()
var expected []string
for _, tok := range tokens {
expected = append(expected, tok.Text)
}
assert.Equal(t, strings.Join(expected, ""), v.expected)
}
})
}
func TestParser_Parse_parseTypeStmt(t *testing.T) {
assertEqual := func(t *testing.T, expected, actual ast.Stmt) {
if expected == nil {
@@ -1399,6 +1427,7 @@ func TestParser_Parse_parseTypeStmt(t *testing.T) {
assertEqual(t, val.expected, one)
}
})
t.Run("parseTypeGroupStmt", func(t *testing.T) {
var testData = []struct {
input string
@@ -1472,6 +1501,7 @@ func TestParser_Parse_parseTypeStmt(t *testing.T) {
},
},
}
for _, val := range testData {
p := New("test.api", val.input)
result := p.Parse()