github.com/bosssauce/ponzu@v0.11.1-0.20200102001432-9bc41b703131/system/api/cors.go (about)

     1  package api
     2  
     3  import (
     4  	"log"
     5  	"net/http"
     6  	"net/url"
     7  
     8  	"github.com/ponzu-cms/ponzu/system/db"
     9  )
    10  
    11  // sendPreflight is used to respond to a cross-origin "OPTIONS" request
    12  func sendPreflight(res http.ResponseWriter) {
    13  	res.Header().Set("Access-Control-Allow-Headers", "Accept, Authorization, Content-Type")
    14  	res.Header().Set("Access-Control-Allow-Origin", "*")
    15  	res.WriteHeader(200)
    16  	return
    17  }
    18  
    19  func responseWithCORS(res http.ResponseWriter, req *http.Request) (http.ResponseWriter, bool) {
    20  	if db.ConfigCache("cors_disabled").(bool) == true {
    21  		// check origin matches config domain
    22  		domain := db.ConfigCache("domain").(string)
    23  		origin := req.Header.Get("Origin")
    24  		u, err := url.Parse(origin)
    25  		if err != nil {
    26  			log.Println("Error parsing URL from request Origin header:", origin)
    27  			return res, false
    28  		}
    29  
    30  		// hack to get dev environments to bypass cors since u.Host (below) will
    31  		// be empty, based on Go's url.Parse function
    32  		if domain == "localhost" {
    33  			domain = ""
    34  		}
    35  		origin = u.Host
    36  
    37  		// currently, this will check for exact match. will need feedback to
    38  		// determine if subdomains should be allowed or allow multiple domains
    39  		// in config
    40  		if origin == domain {
    41  			// apply limited CORS headers and return
    42  			res.Header().Set("Access-Control-Allow-Headers", "Accept, Authorization, Content-Type")
    43  			res.Header().Set("Access-Control-Allow-Origin", domain)
    44  			return res, true
    45  		}
    46  
    47  		// disallow request
    48  		res.WriteHeader(http.StatusForbidden)
    49  		return res, false
    50  	}
    51  
    52  	// apply full CORS headers and return
    53  	res.Header().Set("Access-Control-Allow-Headers", "Accept, Authorization, Content-Type")
    54  	res.Header().Set("Access-Control-Allow-Origin", "*")
    55  
    56  	return res, true
    57  }
    58  
    59  // CORS wraps a HandlerFunc to respond to OPTIONS requests properly
    60  func CORS(next http.HandlerFunc) http.HandlerFunc {
    61  	return db.CacheControl(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
    62  		res, cors := responseWithCORS(res, req)
    63  		if !cors {
    64  			return
    65  		}
    66  
    67  		if req.Method == http.MethodOptions {
    68  			sendPreflight(res)
    69  			return
    70  		}
    71  
    72  		next.ServeHTTP(res, req)
    73  	}))
    74  }