mirror of
				https://github.com/imgproxy/imgproxy.git
				synced 2025-10-30 23:08:02 +02:00 
			
		
		
		
	Polish cookies passthrough
This commit is contained in:
		| @@ -3,6 +3,7 @@ | ||||
| ## [Unreleased] | ||||
| ### Added | ||||
| - Add `X-Origin-Width` and `X-Origin-Height` to debug headers. | ||||
| - Add `IMGPROXY_COOKIE_PASSTHROUGH` and `IMGPROXY_COOKIE_BASE_URL` configs. | ||||
|  | ||||
| ### Change | ||||
| - `dpr` processing option doesn't enlarge image unless `enlarge` is true. | ||||
|   | ||||
| @@ -27,7 +27,6 @@ var ( | ||||
|  | ||||
| 	TTL                     int | ||||
| 	CacheControlPassthrough bool | ||||
| 	CookiePassthrough       bool | ||||
| 	SetCanonicalHeader      bool | ||||
|  | ||||
| 	SoReuseport bool | ||||
| @@ -74,7 +73,11 @@ var ( | ||||
| 	IgnoreSslVerification bool | ||||
| 	DevelopmentErrorsMode bool | ||||
|  | ||||
| 	AllowedSources      []*regexp.Regexp | ||||
| 	AllowedSources []*regexp.Regexp | ||||
|  | ||||
| 	CookiePassthrough bool | ||||
| 	CookieBaseURL     string | ||||
|  | ||||
| 	LocalFileSystemRoot string | ||||
| 	S3Enabled           bool | ||||
| 	S3Region            string | ||||
| @@ -88,8 +91,7 @@ var ( | ||||
|  | ||||
| 	ETagEnabled bool | ||||
|  | ||||
| 	BaseURL       string | ||||
| 	CookieBaseURL string | ||||
| 	BaseURL string | ||||
|  | ||||
| 	Presets     []string | ||||
| 	OnlyPresets bool | ||||
| @@ -157,7 +159,6 @@ func Reset() { | ||||
|  | ||||
| 	TTL = 3600 | ||||
| 	CacheControlPassthrough = false | ||||
| 	CookiePassthrough = false | ||||
| 	SetCanonicalHeader = false | ||||
|  | ||||
| 	SoReuseport = false | ||||
| @@ -205,6 +206,10 @@ func Reset() { | ||||
| 	DevelopmentErrorsMode = false | ||||
|  | ||||
| 	AllowedSources = make([]*regexp.Regexp, 0) | ||||
|  | ||||
| 	CookiePassthrough = false | ||||
| 	CookieBaseURL = "" | ||||
|  | ||||
| 	LocalFileSystemRoot = "" | ||||
| 	S3Enabled = false | ||||
| 	S3Region = "" | ||||
| @@ -219,7 +224,6 @@ func Reset() { | ||||
| 	ETagEnabled = false | ||||
|  | ||||
| 	BaseURL = "" | ||||
| 	CookieBaseURL = "" | ||||
|  | ||||
| 	Presets = make([]string, 0) | ||||
| 	OnlyPresets = false | ||||
| @@ -283,7 +287,6 @@ func Configure() error { | ||||
|  | ||||
| 	configurators.Int(&TTL, "IMGPROXY_TTL") | ||||
| 	configurators.Bool(&CacheControlPassthrough, "IMGPROXY_CACHE_CONTROL_PASSTHROUGH") | ||||
| 	configurators.Bool(&CookiePassthrough, "IMGPROXY_COOKIE_PASSTHROUGH") | ||||
| 	configurators.Bool(&SetCanonicalHeader, "IMGPROXY_SET_CANONICAL_HEADER") | ||||
|  | ||||
| 	configurators.Bool(&SoReuseport, "IMGPROXY_SO_REUSEPORT") | ||||
| @@ -348,6 +351,9 @@ func Configure() error { | ||||
| 	configurators.Bool(&IgnoreSslVerification, "IMGPROXY_IGNORE_SSL_VERIFICATION") | ||||
| 	configurators.Bool(&DevelopmentErrorsMode, "IMGPROXY_DEVELOPMENT_ERRORS_MODE") | ||||
|  | ||||
| 	configurators.Bool(&CookiePassthrough, "IMGPROXY_COOKIE_PASSTHROUGH") | ||||
| 	configurators.String(&CookieBaseURL, "IMGPROXY_COOKIE_BASE_URL") | ||||
|  | ||||
| 	configurators.String(&LocalFileSystemRoot, "IMGPROXY_LOCAL_FILESYSTEM_ROOT") | ||||
|  | ||||
| 	configurators.Bool(&S3Enabled, "IMGPROXY_USE_S3") | ||||
| @@ -365,7 +371,6 @@ func Configure() error { | ||||
| 	configurators.Bool(&ETagEnabled, "IMGPROXY_USE_ETAG") | ||||
|  | ||||
| 	configurators.String(&BaseURL, "IMGPROXY_BASE_URL") | ||||
| 	configurators.String(&CookieBaseURL, "IMGPROXY_COOKIE_BASE_URL") | ||||
|  | ||||
| 	configurators.StringSlice(&Presets, "IMGPROXY_PRESETS") | ||||
| 	if err := configurators.StringSliceFile(&Presets, *presetsPath); err != nil { | ||||
|   | ||||
							
								
								
									
										61
									
								
								cookies/cookies.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								cookies/cookies.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,61 @@ | ||||
| package cookies | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"net/http" | ||||
| 	"net/http/cookiejar" | ||||
| 	"net/url" | ||||
|  | ||||
| 	"golang.org/x/net/publicsuffix" | ||||
|  | ||||
| 	"github.com/imgproxy/imgproxy/v3/config" | ||||
| ) | ||||
|  | ||||
| func JarFromRequest(r *http.Request) (*cookiejar.Jar, error) { | ||||
| 	jar, err := cookiejar.New(&cookiejar.Options{PublicSuffixList: publicsuffix.List}) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	if r == nil { | ||||
| 		return jar, nil | ||||
| 	} | ||||
|  | ||||
| 	var cookieBase *url.URL | ||||
|  | ||||
| 	if len(config.CookieBaseURL) > 0 { | ||||
| 		if cookieBase, err = url.Parse(config.CookieBaseURL); err != nil { | ||||
| 			return nil, fmt.Errorf("can't parse cookie base URL: %s", err) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if cookieBase == nil { | ||||
| 		scheme := r.Header.Get("X-Forwarded-Proto") | ||||
| 		if len(scheme) == 0 { | ||||
| 			scheme = "http" | ||||
| 		} | ||||
|  | ||||
| 		host := r.Header.Get("X-Forwarded-Host") | ||||
| 		if len(host) == 0 { | ||||
| 			host = r.Header.Get("Host") | ||||
| 		} | ||||
|  | ||||
| 		if len(host) == 0 { | ||||
| 			return jar, nil | ||||
| 		} | ||||
|  | ||||
| 		port := r.Header.Get("X-Forwarded-Port") | ||||
| 		if len(port) > 0 { | ||||
| 			host = host + ":" + port | ||||
| 		} | ||||
|  | ||||
| 		cookieBase = &url.URL{ | ||||
| 			Scheme: scheme, | ||||
| 			Host:   host, | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	jar.SetCookies(cookieBase, r.Cookies()) | ||||
|  | ||||
| 	return jar, nil | ||||
| } | ||||
| @@ -3,10 +3,8 @@ package main | ||||
| import ( | ||||
| 	"context" | ||||
| 	"fmt" | ||||
| 	"net/url" | ||||
| 	"net/http" | ||||
| 	"net/http/cookiejar" | ||||
| 	"golang.org/x/net/publicsuffix" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| 	"time" | ||||
| @@ -14,6 +12,7 @@ import ( | ||||
| 	log "github.com/sirupsen/logrus" | ||||
|  | ||||
| 	"github.com/imgproxy/imgproxy/v3/config" | ||||
| 	"github.com/imgproxy/imgproxy/v3/cookies" | ||||
| 	"github.com/imgproxy/imgproxy/v3/errorreport" | ||||
| 	"github.com/imgproxy/imgproxy/v3/etag" | ||||
| 	"github.com/imgproxy/imgproxy/v3/ierrors" | ||||
| @@ -138,48 +137,6 @@ func respondWithNotModified(reqID string, r *http.Request, rw http.ResponseWrite | ||||
| 	) | ||||
| } | ||||
|  | ||||
| func cookieJarFromRequest(r *http.Request) (*cookiejar.Jar, error) { | ||||
| 	jar, err := cookiejar.New(&cookiejar.Options{PublicSuffixList: publicsuffix.List}) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	if config.CookiePassthrough && r != nil { | ||||
| 		cookieBase := config.CookieBaseURL | ||||
|  | ||||
| 		if len(cookieBase) == 0 { | ||||
| 			scheme := r.Header.Get("X-Forwarded-Proto") | ||||
| 			if len(scheme) == 0 { | ||||
| 				scheme = "http" | ||||
| 			} | ||||
| 			host := r.Header.Get("X-Forwarded-Host") | ||||
| 			if len(host) == 0 { | ||||
| 				host = r.Header.Get("Host") | ||||
| 			} | ||||
| 			if len(host) == 0 { | ||||
| 				cookieBase = "" | ||||
| 			} else { | ||||
| 				port := r.Header.Get("X-Forwarded-Port") | ||||
| 				if len(port) > 0 { | ||||
| 					host = host + ":" + port | ||||
| 				} | ||||
| 				cookieBase = scheme + "://" + host + "/" | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		if len(cookieBase) > 0 { | ||||
| 			cookieBaseURL, err := url.Parse(cookieBase) | ||||
|  | ||||
| 			if err != nil { | ||||
| 				return nil, err | ||||
| 			} | ||||
|  | ||||
| 			jar.SetCookies(cookieBaseURL, r.Cookies()) | ||||
| 		} | ||||
| 	} | ||||
| 	return jar, nil | ||||
| } | ||||
|  | ||||
| func handleProcessing(reqID string, rw http.ResponseWriter, r *http.Request) { | ||||
| 	ctx, timeoutCancel := context.WithTimeout(r.Context(), time.Duration(config.WriteTimeout)*time.Second) | ||||
| 	defer timeoutCancel() | ||||
| @@ -220,11 +177,6 @@ func handleProcessing(reqID string, rw http.ResponseWriter, r *http.Request) { | ||||
| 		panic(ierrors.New(404, fmt.Sprintf("Source URL is not allowed: %s", imageURL), "Invalid source")) | ||||
| 	} | ||||
|  | ||||
| 	jar, err := cookieJarFromRequest(r) | ||||
| 	if err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
|  | ||||
| 	// SVG is a special case. Though saving to svg is not supported, SVG->SVG is. | ||||
| 	if !vips.SupportsSave(po.Format) && po.Format != imagetype.Unknown && po.Format != imagetype.SVG { | ||||
| 		panic(ierrors.New( | ||||
| @@ -263,7 +215,16 @@ func handleProcessing(reqID string, rw http.ResponseWriter, r *http.Request) { | ||||
|  | ||||
| 	originData, err := func() (*imagedata.ImageData, error) { | ||||
| 		defer metrics.StartDownloadingSegment(ctx)() | ||||
| 		return imagedata.Download(imageURL, "source image", imgRequestHeader, jar) | ||||
|  | ||||
| 		var cookieJar *cookiejar.Jar | ||||
|  | ||||
| 		if config.CookiePassthrough { | ||||
| 			if cookieJar, err = cookies.JarFromRequest(r); err != nil { | ||||
| 				panic(err) | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		return imagedata.Download(imageURL, "source image", imgRequestHeader, cookieJar) | ||||
| 	}() | ||||
|  | ||||
| 	if err == nil { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user