Skip to content

Commit 23bbb42

Browse files
committed
Unify VersionMux and ServeMux interfaces
1 parent 7fb83aa commit 23bbb42

File tree

2 files changed

+146
-143
lines changed

2 files changed

+146
-143
lines changed

mux.go

+31-67
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
package goa
22

33
import (
4-
"encoding/json"
5-
"fmt"
64
"net/http"
75
"net/url"
86
"regexp"
@@ -12,25 +10,11 @@ import (
1210
)
1311

1412
type (
15-
// ServeMux is the interface implemented by the goa HTTP request mux. The goa package
16-
// provides a default implementation with DefaultMux.
17-
//
18-
// The goa mux allows for routing to controllers serving different API versions. Each
19-
// version has is own mux accessed via Version. Upon receving a HTTP request the ServeMux
20-
// ServeHTTP method looks up the targetted API version and dispatches the request to the
21-
// corresponding mux.
22-
ServeMux interface {
23-
VersionMux
24-
// Version returns the mux for the given API version.
25-
Version(version string) VersionMux
26-
// HandleMissingVersion handles requests that specify a non-existing API version.
27-
HandleMissingVersion(rw http.ResponseWriter, req *http.Request, version string)
28-
}
29-
30-
// VersionMux is the interface implemented by API version specific request mux.
13+
// ServeMux is the interface implemented by the service request muxes. There is one instance
14+
// of ServeMux per service version and one for requests targetting no version.
3115
// It implements http.Handler and makes it possible to register request handlers for
3216
// specific HTTP methods and request path via the Handle method.
33-
VersionMux interface {
17+
ServeMux interface {
3418
http.Handler
3519
// Handle sets the HandleFunc for a given HTTP method and path.
3620
Handle(method, path string, handle HandleFunc)
@@ -47,8 +31,9 @@ type (
4731
// SelectVersion.
4832
DefaultMux struct {
4933
*defaultVersionMux
50-
selectVersion SelectVersionFunc
51-
muxes map[string]VersionMux
34+
SelectVersionFunc SelectVersionFunc
35+
missingVerFunc handleMissingVersionFunc
36+
muxes map[string]ServeMux
5237
}
5338

5439
// SelectVersionFunc is used by the default goa mux to compute the API version targetted by
@@ -57,26 +42,16 @@ type (
5742
// Alternate implementations can be set using the DefaultMux SelectVersion method.
5843
SelectVersionFunc func(*http.Request) string
5944

60-
// defaultVersionMux is the default goa API version specific mux.
45+
// defaultVersionMux is the default API version specific mux implementation.
6146
defaultVersionMux struct {
6247
router *httprouter.Router
6348
handles map[string]HandleFunc
6449
}
65-
)
6650

67-
// 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.
71-
func NewMux() ServeMux {
72-
return &DefaultMux{
73-
defaultVersionMux: &defaultVersionMux{
74-
router: httprouter.New(),
75-
handles: make(map[string]HandleFunc),
76-
},
77-
selectVersion: PathSelectVersionFunc("/:version/", "api"),
78-
}
79-
}
51+
// HandleMissingVersionFunc is the signature of the function called back when requests
52+
// target an unsupported API version.
53+
handleMissingVersionFunc func(rw http.ResponseWriter, req *http.Request, version string)
54+
)
8055

8156
// PathSelectVersionFunc returns a SelectVersionFunc that uses the given path pattern to extract the
8257
// version from the request path. Use the same path pattern given in the DSL to define the API base
@@ -124,36 +99,9 @@ func CombineSelectVersionFunc(funcs ...SelectVersionFunc) SelectVersionFunc {
12499
}
125100
}
126101

127-
// Version returns the mux addressing the given version if any.
128-
func (m *DefaultMux) Version(version string) VersionMux {
129-
if m.muxes == nil {
130-
m.muxes = make(map[string]VersionMux)
131-
}
132-
if mux, ok := m.muxes[version]; ok {
133-
return mux
134-
}
135-
mux := &defaultVersionMux{
136-
router: httprouter.New(),
137-
handles: make(map[string]HandleFunc),
138-
}
139-
m.muxes[version] = mux
140-
return mux
141-
}
142-
143102
// SelectVersion sets the func used to compute the API version targetted by a request.
144103
func (m *DefaultMux) SelectVersion(sv SelectVersionFunc) {
145-
m.selectVersion = sv
146-
}
147-
148-
// HandleMissingVersion handles requests that specify a non-existing API version.
149-
func (m *DefaultMux) HandleMissingVersion(rw http.ResponseWriter, req *http.Request, version string) {
150-
rw.WriteHeader(400)
151-
resp := TypedError{ID: ErrInvalidVersion, Mesg: fmt.Sprintf(`API does not support version %s`, version)}
152-
b, err := json.Marshal(resp)
153-
if err != nil {
154-
b = []byte("API does not support version")
155-
}
156-
rw.Write(b)
104+
m.SelectVersionFunc = sv
157105
}
158106

159107
// ServeHTTP is the function called back by the underlying HTTP server to handle incoming requests.
@@ -163,21 +111,37 @@ func (m *DefaultMux) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
163111
m.router.ServeHTTP(rw, req)
164112
return
165113
}
166-
var mux VersionMux
167-
version := m.selectVersion(req)
114+
var mux ServeMux
115+
version := m.SelectVersionFunc(req)
168116
if version == "" {
169117
mux = m.defaultVersionMux
170118
} else {
171119
var ok bool
172120
mux, ok = m.muxes[version]
173121
if !ok {
174-
m.HandleMissingVersion(rw, req, version)
122+
m.missingVerFunc(rw, req, version)
175123
return
176124
}
177125
}
178126
mux.ServeHTTP(rw, req)
179127
}
180128

129+
// version returns the mux addressing the given version if any.
130+
func (m *DefaultMux) version(version string) ServeMux {
131+
if m.muxes == nil {
132+
m.muxes = make(map[string]ServeMux)
133+
}
134+
if mux, ok := m.muxes[version]; ok {
135+
return mux
136+
}
137+
mux := &defaultVersionMux{
138+
router: httprouter.New(),
139+
handles: make(map[string]HandleFunc),
140+
}
141+
m.muxes[version] = mux
142+
return mux
143+
}
144+
181145
// Handle sets the handler for the given verb and path.
182146
func (m *defaultVersionMux) Handle(method, path string, handle HandleFunc) {
183147
hthandle := func(rw http.ResponseWriter, req *http.Request, htparams httprouter.Params) {

0 commit comments

Comments
 (0)