summaryrefslogtreecommitdiff
path: root/system/api/cors.go
diff options
context:
space:
mode:
authorSteve Manuel <nilslice@gmail.com>2017-02-13 09:18:36 -0800
committerSteve Manuel <nilslice@gmail.com>2017-02-13 09:18:36 -0800
commitf47826071f1e6d7b048d1304d8435a347f9b412a (patch)
tree1990862ba77dfce49325cc39c017a76a97c366c5 /system/api/cors.go
parent6ea648ae4306e64f5562ca363e0cdea494ba8d46 (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.go74
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)
+ }))
+}