emicklei / go-restful

package for building REST-style Web Services using Go
MIT License
5.02k stars 691 forks source link

detectWebService biased against webServices without path or rootpath #560

Open haitch opened 2 months ago

haitch commented 2 months ago

When there are mix use of default webService and regexPath webService, the default webService may get biased and its route won't get selected.

with 2 webService setup like this:

since I have fix on this part with issue #547 and PR #549 , I would image the fix is remove the default score for any regex routeToken, but that would definitely be a breaking change.

reproduce, also here is go playground link: https://go.dev/play/p/xbpUnvAETio

package main

import (
    "fmt"
    "io"
    "net/http/httptest"

    restful "github.com/emicklei/go-restful/v3"
)

func main() {
    defaultWS := new(restful.WebService) // or .Path("/")
    helloWS := new(restful.WebService).Path("/{:hello}")

    defaultWS.Route(defaultWS.GET("/{:robot.txt}").To(robotFile))
    restful.DefaultContainer.Add(defaultWS)

    helloWS.Route(helloWS.GET("/{name:*}").To(hello))
    restful.DefaultContainer.Add(helloWS) // comment out this line, and robot.txt will be served

    helloRequest := httptest.NewRequest("GET", "/hello/Juan", nil)
    helloRespWriter := httptest.NewRecorder()
    restful.DefaultContainer.ServeHTTP(helloRespWriter, helloRequest)

    robotRequest := httptest.NewRequest("GET", "/robot.txt", nil)
    robotRespWriter := httptest.NewRecorder()
    restful.DefaultContainer.ServeHTTP(robotRespWriter, robotRequest)

    fmt.Println(helloRequest.Method, helloRequest.URL.Path, "-", helloRespWriter.Result().Status, helloRespWriter.Body.String())
    fmt.Println(robotRequest.Method, robotRequest.URL.Path, "-", robotRespWriter.Result().Status, robotRespWriter.Body.String())
}

func hello(req *restful.Request, resp *restful.Response) {
    io.WriteString(resp, "hello "+req.PathParameter("name"))
}

func robotFile(req *restful.Request, resp *restful.Response) {
    io.WriteString(resp, "User-agent: *\nDisallow: /\n")
}
emicklei commented 1 month ago

"a breaking change" is what will prevent me from making a change in v3. We could add the v4 label to this issue.