CORS support for go-muxer (issue 6820117)

25 views
Skip to first unread message

al...@cloudware.it

unread,
Nov 8, 2012, 4:58:26 AM11/8/12
to al...@cloudware.it, appengine-co...@googlegroups.com, re...@codereview-hr.appspotmail.com
Reviewers: ,

Description:
CORS support for go-muxer

Please review this at http://codereview.appspot.com/6820117/

Affected files:
M README.txt
M muxer.go
M muxer_test.go


Index: README.txt
diff --git a/README.txt b/README.txt
index
02cd69a5476d984900707ecfb4de694be9ed0db5..6c628f4717d9bd4a93b1c5de957dadcb8bc0cca9
100644
--- a/README.txt
+++ b/README.txt
@@ -13,12 +13,18 @@ Simple muxer for a Go app.
// v.Get("action")
}

+ var m = muxer.NewMux("/api", nil)
+
func init() {
- m := muxer.NewMux("/api", nil)
m.Add("GET", "users/{id}", handler1).As("profile")
m.Add("GET", "products", handler2)
m.Add("PUT", "products/{id}/do", handler3)
m.Add("POST", "{domain}/{action}/{id}", handler4).As("whatever")
+
+ // Enable CORS support (optional)
+ m.SetCORS("*", "true", "")
}

See muxer_test.go for more.
+
+GoPkgDoc: http://go.pkgdoc.org/code.google.com/p/go-muxer
Index: muxer.go
diff --git a/muxer.go b/muxer.go
index
28e4d0bbc13a7d09627dc6dfe87d61b0415325f7..a078c1ff2fe1daa2ca39dd3af96ba59b281e1791
100644
--- a/muxer.go
+++ b/muxer.go
@@ -15,12 +15,15 @@ Usage example:
// v.Get("action")
}

+ var m = muxer.NewMux("/api", nil)
+
func init() {
- m := muxer.NewMux("/api", nil)
m.Add("GET", "users/{id}", handler1).As("profile")
m.Add("GET", "products", handler2)
m.Add("PUT", "products/{id}/do", handler3)
m.Add("POST", "{domain}/{action}/{id}", handler4).As("whatever")
+ // Enable CORS support (optional)
+ m.SetCORS("*", "true", "")
}

See muxer_test.go for more.
@@ -35,12 +38,28 @@ import (
"strings"
)

+const (
+ CORS_ALLOW_ORIGIN = "Access-Control-Allow-Origin"
+ CORS_ALLOW_CREDENTIALS = "Access-Control-Allow-Credentials"
+ CORS_EXPOSE_HEADERS = "Access-Control-Expose-Headers"
+)
+
type Mux interface {
+ // Returns the base path of this muxer.
+ // Useful for an API manifest generation.
BasePath() string
+ // Returns the slice of all routes that's been added to this muxer.
Routes() []*Route
+ // Adds a new route to this muxer.
Add(method string, pattern string, h HandlerFunc) *Route
+ // Reconstructs a URL path from an existing route (previously added).
+ // The route should have a name.
BuildPath(routeName string, params ...interface{}) string
+ // http's package interface method that serves HTTP requests.
ServeHTTP(w http.ResponseWriter, req *http.Request)
+ // CORS support.
+ // Example: mux.SetCORS("*", "true", "")
+ SetCORS(origin, credentials, headers string)
}

// NewMux creates a new muxer and hooks it up with provided http.ServeMux.
@@ -72,6 +91,17 @@ type defaultMux struct {
base string
baseLen int
routes []*Route
+ // CORS support
+ origin string
+ credentials string
+ headers string
+}
+
+// CORS support
+func (dm *defaultMux) SetCORS(origin, credentials, headers string) {
+ dm.origin = origin
+ dm.credentials = credentials
+ dm.headers = headers
}

// Returns base path of this mux.
@@ -142,6 +172,13 @@ func (m *defaultMux) ServeHTTP(w http.ResponseWriter,
req *http.Request) {
http.NotFound(w, req)
return
}
+ if m.origin != "" {
+ w.Header().Set(CORS_ALLOW_ORIGIN, m.origin)
+ w.Header().Set(CORS_ALLOW_CREDENTIALS, m.credentials)
+ if m.headers != "" {
+ w.Header().Set(CORS_EXPOSE_HEADERS, m.headers)
+ }
+ }
h(w, req, v)
}

Index: muxer_test.go
diff --git a/muxer_test.go b/muxer_test.go
index
89028beedf1dcb3d6e88c01aeddbe31129ea086c..4ff62b297c61d0228e5992caf3e61c3b0cfadf2a
100644
--- a/muxer_test.go
+++ b/muxer_test.go
@@ -102,6 +102,36 @@ func TestServeHttp(t *testing.T) {
}
}

+func TestCORS(t *testing.T) {
+ h := http.NewServeMux()
+ m := NewMux("/api", h)
+ m.Add("GET", "path", dummy)
+ m.SetCORS("*", "true", "")
+
+ req, err := http.NewRequest("GET", "/api/path", nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ w := httptest.NewRecorder()
+ h.ServeHTTP(w, req)
+ if w.Code != 200 {
+ t.Fatalf("Expected 200 OK; got %d\n%s", w.Code, w.Body.String())
+ }
+ assertEqual(t, w.HeaderMap.Get(CORS_ALLOW_ORIGIN), "*")
+ assertEqual(t, w.HeaderMap.Get(CORS_ALLOW_CREDENTIALS), "true")
+ exposeCan := http.CanonicalHeaderKey(CORS_EXPOSE_HEADERS)
+ if header, exists := w.HeaderMap[exposeCan]; exists {
+ t.Fatalf("Didn't expected expose headers header: %s", header)
+ }
+
+ m.SetCORS("http://test", "false", "FooBar BarFoo")
+ w = httptest.NewRecorder()
+ h.ServeHTTP(w, req)
+ assertEqual(t, w.HeaderMap.Get(CORS_ALLOW_ORIGIN), "http://test")
+ assertEqual(t, w.HeaderMap.Get(CORS_ALLOW_CREDENTIALS), "false")
+ assertEqual(t, w.HeaderMap.Get(CORS_EXPOSE_HEADERS), "FooBar BarFoo")
+}
+

//////////////////////////////////////////////////////////////////////////////
// Examples



Reply all
Reply to author
Forward
0 new messages