diff options
author | Steve Manuel <nilslice@gmail.com> | 2017-02-13 09:18:36 -0800 |
---|---|---|
committer | Steve Manuel <nilslice@gmail.com> | 2017-02-13 09:18:36 -0800 |
commit | f47826071f1e6d7b048d1304d8435a347f9b412a (patch) | |
tree | 1990862ba77dfce49325cc39c017a76a97c366c5 /system/api/cors.go | |
parent | 6ea648ae4306e64f5562ca363e0cdea494ba8d46 (diff) |
adding item.Omittable interface for field-level omission of data in responses, implementation in handler and separating source into individual files for other interface impls
Diffstat (limited to 'system/api/cors.go')
-rw-r--r-- | system/api/cors.go | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/system/api/cors.go b/system/api/cors.go new file mode 100644 index 0000000..249a378 --- /dev/null +++ b/system/api/cors.go @@ -0,0 +1,74 @@ +package api + +import ( + "log" + "net/http" + "net/url" + + "github.com/ponzu-cms/ponzu/system/db" +) + +// sendPreflight is used to respond to a cross-origin "OPTIONS" request +func sendPreflight(res http.ResponseWriter) { + res.Header().Set("Access-Control-Allow-Headers", "Accept, Authorization, Content-Type") + res.Header().Set("Access-Control-Allow-Origin", "*") + res.WriteHeader(200) + return +} + +func responseWithCORS(res http.ResponseWriter, req *http.Request) (http.ResponseWriter, bool) { + if db.ConfigCache("cors_disabled").(bool) == true { + // check origin matches config domain + domain := db.ConfigCache("domain").(string) + origin := req.Header.Get("Origin") + u, err := url.Parse(origin) + if err != nil { + log.Println("Error parsing URL from request Origin header:", origin) + return res, false + } + + // hack to get dev environments to bypass cors since u.Host (below) will + // be empty, based on Go's url.Parse function + if domain == "localhost" { + domain = "" + } + origin = u.Host + + // currently, this will check for exact match. will need feedback to + // determine if subdomains should be allowed or allow multiple domains + // in config + if origin == domain { + // apply limited CORS headers and return + res.Header().Set("Access-Control-Allow-Headers", "Accept, Authorization, Content-Type") + res.Header().Set("Access-Control-Allow-Origin", domain) + return res, true + } + + // disallow request + res.WriteHeader(http.StatusForbidden) + return res, false + } + + // apply full CORS headers and return + res.Header().Set("Access-Control-Allow-Headers", "Accept, Authorization, Content-Type") + res.Header().Set("Access-Control-Allow-Origin", "*") + + return res, true +} + +// CORS wraps a HandlerFunc to respond to OPTIONS requests properly +func CORS(next http.HandlerFunc) http.HandlerFunc { + return db.CacheControl(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { + res, cors := responseWithCORS(res, req) + if !cors { + return + } + + if req.Method == http.MethodOptions { + sendPreflight(res) + return + } + + next.ServeHTTP(res, req) + })) +} |