DarthSim 7 anni fa
parent
commit
04871c8b7f
4 ha cambiato i file con 31 aggiunte e 2 eliminazioni
  1. 1 0
      README.md
  2. 4 0
      config.go
  3. 1 0
      errors.go
  4. 25 2
      server.go

+ 1 - 0
README.md

@@ -151,6 +151,7 @@ $ xxd -g 2 -l 64 -p /dev/random | tr -d '\n'
 
 imgproxy protects you from so-called image bombs. Here is how you can specify maximum image dimensions and resolution which you consider reasonable:
 
+* `IMGPROXY_ALLOW_ORIGIN` - when set, enables CORS headers with provided origin. CORS headers are disabled by default.
 * `IMGPROXY_MAX_SRC_DIMENSION` — the maximum dimensions of the source image, in pixels, for both width and height. Images with larger real size will be rejected. Default: `8192`;
 * `IMGPROXY_MAX_SRC_RESOLUTION` — the maximum resolution of the source image, in megapixels. Images with larger real size will be rejected. Default: `16.8`;
 

+ 4 - 0
config.go

@@ -95,6 +95,8 @@ type config struct {
 
 	Secret string
 
+	AllowOrigin string
+
 	LocalFileSystemRoot string
 
 	ETagEnabled   bool
@@ -147,6 +149,8 @@ func init() {
 
 	strEnvConfig(&conf.Secret, "IMGPROXY_SECRET")
 
+	strEnvConfig(&conf.AllowOrigin, "IMGPROXY_ALLOW_ORIGIN")
+
 	strEnvConfig(&conf.LocalFileSystemRoot, "IMGPROXY_LOCAL_FILESYSTEM_ROOT")
 
 	boolEnvConfig(&conf.ETagEnabled, "IMGPROXY_USE_ETAG")

+ 1 - 0
errors.go

@@ -27,6 +27,7 @@ func newUnexpectedError(err error, skip int) imgproxyError {
 
 var (
 	invalidSecretErr = newError(403, "Invalid secret", "Forbidden")
+	invalidMethodErr = newError(422, "Invalid request method", "Method doesn't allowed")
 )
 
 func stacktrace(skip int) string {

+ 25 - 2
server.go

@@ -105,6 +105,13 @@ func logResponse(status int, msg string) {
 	log.Printf("|\033[7;%dm %d \033[0m| %s\n", color, status, msg)
 }
 
+func writeCORS(rw http.ResponseWriter) {
+	if len(conf.AllowOrigin) > 0 {
+		rw.Header().Set("Access-Control-Allow-Origin", conf.AllowOrigin)
+		rw.Header().Set("Access-Control-Allow-Methods", "GET, OPTIONs")
+	}
+}
+
 func respondWithImage(reqID string, r *http.Request, rw http.ResponseWriter, data []byte, imgURL string, po processingOptions, duration time.Duration) {
 	gzipped := strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") && conf.GZipCompression > 0
 
@@ -136,6 +143,11 @@ func respondWithError(reqID string, rw http.ResponseWriter, err imgproxyError) {
 	rw.Write([]byte(err.PublicMessage))
 }
 
+func respondWithOptions(reqID string, rw http.ResponseWriter) {
+	logResponse(200, fmt.Sprintf("[%s] Respond with options", reqID))
+	rw.WriteHeader(200)
+}
+
 func checkSecret(s string) bool {
 	if len(conf.Secret) == 0 {
 		return true
@@ -154,8 +166,6 @@ func (h *httpHandler) unlock() {
 func (h *httpHandler) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
 	reqID, _ := nanoid.Nanoid()
 
-	log.Printf("[%s] GET: %s\n", reqID, r.URL.RequestURI())
-
 	defer func() {
 		if r := recover(); r != nil {
 			if err, ok := r.(imgproxyError); ok {
@@ -166,6 +176,19 @@ func (h *httpHandler) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
 		}
 	}()
 
+	log.Printf("[%s] %s: %s\n", reqID, r.Method, r.URL.RequestURI())
+
+	writeCORS(rw)
+
+	if r.Method == http.MethodOptions {
+		respondWithOptions(reqID, rw)
+		return
+	}
+
+	if r.Method != http.MethodGet {
+		panic(invalidMethodErr)
+	}
+
 	if !checkSecret(r.Header.Get("Authorization")) {
 		panic(invalidSecretErr)
 	}