Skip to content

Commit a2845c0

Browse files
committed
Properly handle unversioned requests in path based version mux.
1 parent 9b96a27 commit a2845c0

File tree

2 files changed

+62
-3
lines changed

2 files changed

+62
-3
lines changed

mux.go

+8-3
Original file line numberDiff line numberDiff line change
@@ -65,25 +65,30 @@ type (
6565
)
6666

6767
// NewMux creates a top level mux using the default goa mux implementation.
68+
// The default versioning handling assumes that the base path for the API is "/api" and the
69+
// base paths for each version "/:version/api". Use SelectVersion to specify a different scheme
70+
// if the service exposes a versioned API with different base paths.
6871
func NewMux() ServeMux {
6972
return &DefaultMux{
7073
defaultVersionMux: &defaultVersionMux{
7174
router: httprouter.New(),
7275
handles: make(map[string]HandleFunc),
7376
},
74-
selectVersion: PathSelectVersionFunc("/:version/"),
77+
selectVersion: PathSelectVersionFunc("/:version/", "api"),
7578
}
7679
}
7780

7881
// PathSelectVersionFunc returns a SelectVersionFunc that uses the given path pattern to extract the
7982
// version from the request path. Use the same path pattern given in the DSL to define the API base
8083
// path, e.g. "/api/:version".
81-
func PathSelectVersionFunc(pattern string) SelectVersionFunc {
84+
// If the pattern matches zeroVersion then the empty version is returned (i.e. the unversioned
85+
// controller handles the request).
86+
func PathSelectVersionFunc(pattern, zeroVersion string) SelectVersionFunc {
8287
rgs := design.WildcardRegex.ReplaceAllLiteralString(pattern, `/([^/]+)`)
8388
rg := regexp.MustCompile("^" + rgs)
8489
return func(req *http.Request) (version string) {
8590
match := rg.FindStringSubmatch(req.URL.Path)
86-
if len(match) > 1 {
91+
if len(match) > 1 && match[1] != zeroVersion {
8792
version = match[1]
8893
}
8994
return

mux_test.go

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package goa_test
2+
3+
import (
4+
"net/http"
5+
6+
. "github.com/onsi/ginkgo"
7+
. "github.com/onsi/gomega"
8+
"github.com/raphael/goa"
9+
)
10+
11+
var _ = Describe("PathSelectVersionFunc", func() {
12+
var pattern, zeroVersion string
13+
var request *http.Request
14+
15+
var fn goa.SelectVersionFunc
16+
var version string
17+
18+
JustBeforeEach(func() {
19+
fn = goa.PathSelectVersionFunc(pattern, zeroVersion)
20+
version = fn(request)
21+
})
22+
23+
Context("using the default settings", func() {
24+
BeforeEach(func() {
25+
pattern = "/:version/"
26+
zeroVersion = "api"
27+
})
28+
29+
Context("and a versioned request", func() {
30+
BeforeEach(func() {
31+
var err error
32+
request, err = http.NewRequest("GET", "/v1/foo", nil)
33+
Ω(err).ShouldNot(HaveOccurred())
34+
})
35+
36+
It("routes to the versioned controller", func() {
37+
Ω(version).Should(Equal("v1"))
38+
})
39+
})
40+
41+
Context("and an unversioned request", func() {
42+
BeforeEach(func() {
43+
var err error
44+
request, err = http.NewRequest("GET", "/api/foo", nil)
45+
Ω(err).ShouldNot(HaveOccurred())
46+
})
47+
48+
It("routes to the unversioned controller", func() {
49+
Ω(version).Should(Equal(""))
50+
})
51+
})
52+
})
53+
54+
})

0 commit comments

Comments
 (0)