From f495d2d6adf58979fd8942753f63bc40a0d7f6c0 Mon Sep 17 00:00:00 2001 From: agravelot Date: Wed, 5 May 2021 13:46:45 +0200 Subject: [PATCH 01/10] style: remove most of linters warnings --- .golangci.toml | 1 + image_optimizer.go | 33 ++++++++++------ image_optimizer_test.go | 85 +++++++++++++++++++++++++++++------------ response-writer.go | 2 +- 4 files changed, 84 insertions(+), 37 deletions(-) diff --git a/.golangci.toml b/.golangci.toml index c9010b3..912d89e 100644 --- a/.golangci.toml +++ b/.golangci.toml @@ -36,6 +36,7 @@ "testpackage", "paralleltest", "tparallel", + "scopelint", ] [issues] diff --git a/image_optimizer.go b/image_optimizer.go index 85913aa..efc9cc9 100644 --- a/image_optimizer.go +++ b/image_optimizer.go @@ -1,6 +1,7 @@ package image_optimizer import ( + "bytes" "context" "errors" "fmt" @@ -22,7 +23,15 @@ type Config struct { // CreateConfig creates the default plugin configuration. func CreateConfig() *Config { - return &Config{} + return &Config{ + config.Config{ + Processor: "", + Cache: "", + Imaginary: config.ImaginaryProcessorConfig{Url: ""}, + Redis: config.RedisCacheConfig{Url: ""}, + File: config.FileCacheConfig{Path: ""}, + }, + } } // ImageOptimizer middleware plugin struct. @@ -35,9 +44,7 @@ type ImageOptimizer struct { // New created a new ImageOptimizer plugin. func New(ctx context.Context, next http.Handler, conf *Config, name string) (http.Handler, error) { - log.Println("Loading image optimization plugin...") - fmt.Printf("config : %+v\n", conf) if conf.Processor == "" { return nil, fmt.Errorf("processor must be defined") @@ -50,7 +57,6 @@ func New(ctx context.Context, next http.Handler, conf *Config, name string) (htt p, err := processor.New(conf.Config) if err != nil { - fmt.Println(err.Error()) panic(err) } @@ -63,12 +69,12 @@ func New(ctx context.Context, next http.Handler, conf *Config, name string) (htt } const ( - contentLength = "Content-Length" - contentType = "Content-Type" - cacheStatus = "Cache-Status" - cacheHitStatus = "hit" - cacheMissStatus = "miss" - cacheErrorStatus = "error" + contentLength = "Content-Length" + contentType = "Content-Type" + cacheStatus = "Cache-Status" + cacheHitStatus = "hit" + cacheMissStatus = "miss" + cacheExpiry = 100 * time.Second ) func (a *ImageOptimizer) ServeHTTP(rw http.ResponseWriter, req *http.Request) { @@ -86,15 +92,19 @@ func (a *ImageOptimizer) ServeHTTP(rw http.ResponseWriter, req *http.Request) { rw.Header().Set(contentLength, fmt.Sprint(len(v))) rw.Header().Add(contentType, targetFormat) _, err = rw.Write(v) + if err != nil { panic(err) } + return } wrappedWriter := &responseWriter{ ResponseWriter: rw, bypassHeader: true, + wroteHeader: false, + buffer: bytes.Buffer{}, } a.next.ServeHTTP(wrappedWriter, req) @@ -108,6 +118,7 @@ func (a *ImageOptimizer) ServeHTTP(rw http.ResponseWriter, req *http.Request) { if err != nil { panic(err) } + return } @@ -130,7 +141,7 @@ func (a *ImageOptimizer) ServeHTTP(rw http.ResponseWriter, req *http.Request) { panic(err) } - err = a.c.Set(key, optimized, 100*time.Second) + err = a.c.Set(key, optimized, cacheExpiry) if err != nil { panic(err) } diff --git a/image_optimizer_test.go b/image_optimizer_test.go index 532bf8c..e421b2d 100644 --- a/image_optimizer_test.go +++ b/image_optimizer_test.go @@ -3,7 +3,6 @@ package image_optimizer import ( "bytes" "context" - "fmt" "net/http" "net/http/httptest" "testing" @@ -15,6 +14,7 @@ func TestImageOptimizer_ServeHTTP(t *testing.T) { type args struct { config config.Config } + tests := []struct { name string args args @@ -27,8 +27,16 @@ func TestImageOptimizer_ServeHTTP(t *testing.T) { wantErr bool }{ { - name: "should pass with processor", - args: args{config: config.Config{Processor: "imaginary", Imaginary: config.ImaginaryProcessorConfig{Url: "http://localhost"}}}, + name: "should pass with processor", + args: args{ + config: config.Config{ + Processor: "imaginary", + Imaginary: config.ImaginaryProcessorConfig{Url: "http://localhost"}, + Cache: "none", + Redis: config.RedisCacheConfig{Url: ""}, + File: config.FileCacheConfig{Path: ""}, + }, + }, want: false, wantErr: false, wantedCacheStatus: "", @@ -38,8 +46,16 @@ func TestImageOptimizer_ServeHTTP(t *testing.T) { remoteResponseContent: []byte("dummy response"), }, { - name: "should not pass without processor and cache and return no cache status header", - args: args{config: config.Config{Processor: ""}}, + name: "should not pass without processor and cache and return no cache status header", + args: args{ + config: config.Config{ + Processor: "", + Cache: "", + Redis: config.RedisCacheConfig{Url: ""}, + File: config.FileCacheConfig{Path: ""}, + Imaginary: config.ImaginaryProcessorConfig{Url: ""}, + }, + }, want: false, wantedCacheStatus: "", wantedSecondCacheStatus: "", @@ -49,20 +65,28 @@ func TestImageOptimizer_ServeHTTP(t *testing.T) { remoteResponseContent: []byte("dummy response"), }, // TODO Require to save response headers in cache - //{ + // { // name: "should not modify image with none driver and cache file driver with cache status", // args: args{config: config.Config{Processor: "none", Cache: "memory"}}, // want: false, // wantErr: false, // wantedCacheStatus: "miss", - // wantedSecondCacheStatus: "hit", - // wantedContentType: "image/jpeg", - // remoteResponseContentType: "image/jpeg", - // remoteResponseContent: []byte("dummy image"), - //}, + // wantedSecondCacheStatus: "hit", + // wantedContentType: "image/jpeg", + // remoteResponseContentType: "image/jpeg", + // remoteResponseContent: []byte("dummy image"), + // }, { - name: "should not modify image with none driver and cache file driver with cache status", - args: args{config: config.Config{Processor: "local", Cache: "memory"}}, + name: "should not modify image with none driver and cache file driver with cache status", + args: args{ + config: config.Config{ + Processor: "local", + Cache: "memory", + Redis: config.RedisCacheConfig{Url: ""}, + File: config.FileCacheConfig{Path: ""}, + Imaginary: config.ImaginaryProcessorConfig{Url: ""}, + }, + }, want: false, wantErr: false, wantedCacheStatus: "miss", @@ -72,8 +96,16 @@ func TestImageOptimizer_ServeHTTP(t *testing.T) { remoteResponseContent: []byte("dummy image"), }, { - name: "should return original response if not image request and return no cache status header", - args: args{config: config.Config{Processor: "none"}}, + name: "should return original response if not image request and return no cache status header", + args: args{ + config: config.Config{ + Processor: "none", + Cache: "", + Redis: config.RedisCacheConfig{Url: ""}, + File: config.FileCacheConfig{Path: ""}, + Imaginary: config.ImaginaryProcessorConfig{Url: ""}, + }, + }, want: false, wantErr: false, wantedCacheStatus: "", @@ -83,6 +115,7 @@ func TestImageOptimizer_ServeHTTP(t *testing.T) { remoteResponseContent: []byte("dummy response"), }, } + for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { cfg := CreateConfig() @@ -127,9 +160,6 @@ func TestImageOptimizer_ServeHTTP(t *testing.T) { } if recorder.Header().Get("cache-status") != tt.wantedCacheStatus { - fmt.Printf("a:%#v\n", tt.wantedCacheStatus) - fmt.Printf("b:%#v\n", recorder.Header().Get("cache-status")) - t.Fatalf("response cache-status expected: %v got: %v", tt.wantedCacheStatus, recorder.Header().Get("cache-status")) } @@ -146,7 +176,11 @@ func TestImageOptimizer_ServeHTTP(t *testing.T) { } if recorder.Header().Get("cache-status") != tt.wantedSecondCacheStatus { - t.Fatalf("response cache-status expected: %v got: %v", tt.wantedSecondCacheStatus, recorder.Header().Get("cache-status")) + t.Fatalf( + "response cache-status expected: %v got: %v", + tt.wantedSecondCacheStatus, + recorder.Header().Get("cache-status"), + ) } }) } @@ -156,6 +190,7 @@ func TestIsImageResponse(t *testing.T) { type args struct { contentType string } + tests := []struct { name string args args @@ -187,6 +222,7 @@ func TestIsImageResponse(t *testing.T) { wantErr: false, }, } + for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { recorder := httptest.NewRecorder() @@ -202,10 +238,7 @@ func TestIsImageResponse(t *testing.T) { } func TestImageWidthRequest(t *testing.T) { - type args struct { - url string - } - ctx := context.Background() + type args struct{ url string } tests := []struct { name string @@ -214,7 +247,7 @@ func TestImageWidthRequest(t *testing.T) { wantErr bool }{ { - name: "should return error with positve width", + name: "should return error with positive width", args: args{url: "http://localhost?w=124"}, want: 124, wantErr: false, @@ -244,9 +277,11 @@ func TestImageWidthRequest(t *testing.T) { wantErr: false, }, } + for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { + ctx := context.Background() + t.Run(tt.name, func(t *testing.T) { req, err := http.NewRequestWithContext(ctx, http.MethodGet, tt.args.url, nil) if err != nil { t.Fatal(err) diff --git a/response-writer.go b/response-writer.go index 7036cc5..513ea4b 100644 --- a/response-writer.go +++ b/response-writer.go @@ -14,7 +14,6 @@ type responseWriter struct { } func (r *responseWriter) WriteHeader(statusCode int) { - if !r.bypassHeader { r.ResponseWriter.WriteHeader(statusCode) } @@ -24,6 +23,7 @@ func (r *responseWriter) Write(p []byte) (int, error) { if !r.wroteHeader { r.WriteHeader(http.StatusOK) } + return r.buffer.Write(p) } From 53dd5b6c998b40837f12d244e3f03a7690560743 Mon Sep 17 00:00:00 2001 From: agravelot Date: Wed, 5 May 2021 14:01:33 +0200 Subject: [PATCH 02/10] refactor: rename main module to imageopti --- .traefik.yml | 2 +- cache/factory.go | 2 +- cache/factory_test.go | 4 ++-- demo/frontend/docker-compose.yml | 10 +++++----- demo/gateway/docker-compose.yml | 4 ++-- demo/gateway/traefik.yml | 2 +- go.mod | 2 +- image_optimizer.go | 8 ++++---- image_optimizer_test.go | 4 ++-- processor/factory.go | 2 +- processor/factory_test.go | 4 ++-- processor/imaginary.go | 2 +- readme.md | 8 ++++---- response-writer.go | 2 +- 14 files changed, 28 insertions(+), 28 deletions(-) diff --git a/.traefik.yml b/.traefik.yml index f072e62..b2eb797 100644 --- a/.traefik.yml +++ b/.traefik.yml @@ -1,7 +1,7 @@ displayName: Image optimizer type: middleware -import: github.com/agravelot/image_optimizer +import: github.com/agravelot/imageopti summary: 'Image optimizer middleware is a middleware designed to optimize image responses on the fly.' diff --git a/cache/factory.go b/cache/factory.go index 09a3c90..2f364c8 100644 --- a/cache/factory.go +++ b/cache/factory.go @@ -5,7 +5,7 @@ import ( "sync" "time" - "github.com/agravelot/image_optimizer/config" + "github.com/agravelot/imageopti/config" ) type Cache interface { diff --git a/cache/factory_test.go b/cache/factory_test.go index d248663..048d6d2 100644 --- a/cache/factory_test.go +++ b/cache/factory_test.go @@ -4,8 +4,8 @@ import ( "reflect" "testing" - "github.com/agravelot/image_optimizer/cache" - "github.com/agravelot/image_optimizer/config" + "github.com/agravelot/imageopti/cache" + "github.com/agravelot/imageopti/config" ) func TestNew(t *testing.T) { diff --git a/demo/frontend/docker-compose.yml b/demo/frontend/docker-compose.yml index ef5509f..ed7706b 100644 --- a/demo/frontend/docker-compose.yml +++ b/demo/frontend/docker-compose.yml @@ -12,11 +12,11 @@ services: labels: - "traefik.enable=true" - "traefik.http.routers.demo.rule=Host(`demo.localhost`)" - - "traefik.http.middlewares.image_optimizer.plugin.dev.config.processor=imaginary" - - "traefik.http.middlewares.image_optimizer.plugin.dev.config.imaginary.url=http://imaginary:9000" - - "traefik.http.middlewares.image_optimizer.plugin.dev.config.cache=file" - - "traefik.http.middlewares.image_optimizer.plugin.dev.config.file.path=/root" - - "traefik.http.routers.demo.middlewares=image_optimizer" + - "traefik.http.middlewares.imageopti.plugin.dev.config.processor=imaginary" + - "traefik.http.middlewares.imageopti.plugin.dev.config.imaginary.url=http://imaginary:9000" + - "traefik.http.middlewares.imageopti.plugin.dev.config.cache=file" + - "traefik.http.middlewares.imageopti.plugin.dev.config.file.path=/root" + - "traefik.http.routers.demo.middlewares=imageopti" networks: traefik-net: diff --git a/demo/gateway/docker-compose.yml b/demo/gateway/docker-compose.yml index 2fc6b97..4f942da 100644 --- a/demo/gateway/docker-compose.yml +++ b/demo/gateway/docker-compose.yml @@ -18,13 +18,13 @@ services: - "--entryPoints.metrics.address=:8082" - "--metrics.prometheus.entryPoint=metrics" - "--experimental.devPlugin.goPath=/plugins" - - "--experimental.devPlugin.moduleName=github.com/agravelot/image_optimizer" + - "--experimental.devPlugin.moduleName=github.com/agravelot/imageopti" ports: - "80:80" - "443:443" - "8080:8080" volumes: - - "/home/agravelot/Lab/traefik-image-optimization:/plugins/src/github.com/agravelot/image_optimizer:rw,delegated" + - "/home/agravelot/Lab/traefik-image-optimization:/plugins/src/github.com/agravelot/imageopti:rw,delegated" # - "./gateway/traefik.yml:/etc/traefik/traefik.yml:ro,delegated" - "letsencrypt:/letsencrypt:rw,delegated" - "/var/run/docker.sock:/var/run/docker.sock:ro" diff --git a/demo/gateway/traefik.yml b/demo/gateway/traefik.yml index 3567569..9a72e1e 100644 --- a/demo/gateway/traefik.yml +++ b/demo/gateway/traefik.yml @@ -4,7 +4,7 @@ global: experimental: devPlugin: goPath: /plugins - moduleName: image_optimizer + moduleName: imageopti entryPoints: web: diff --git a/go.mod b/go.mod index 68b0d03..529ec15 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,3 @@ -module github.com/agravelot/image_optimizer +module github.com/agravelot/imageopti go 1.16 diff --git a/image_optimizer.go b/image_optimizer.go index efc9cc9..bed23c7 100644 --- a/image_optimizer.go +++ b/image_optimizer.go @@ -1,4 +1,4 @@ -package image_optimizer +package imageopti import ( "bytes" @@ -11,9 +11,9 @@ import ( "strings" "time" - "github.com/agravelot/image_optimizer/cache" - "github.com/agravelot/image_optimizer/config" - "github.com/agravelot/image_optimizer/processor" + "github.com/agravelot/imageopti/cache" + "github.com/agravelot/imageopti/config" + "github.com/agravelot/imageopti/processor" ) // Config the plugin configuration. diff --git a/image_optimizer_test.go b/image_optimizer_test.go index e421b2d..bbd8451 100644 --- a/image_optimizer_test.go +++ b/image_optimizer_test.go @@ -1,4 +1,4 @@ -package image_optimizer +package imageopti import ( "bytes" @@ -7,7 +7,7 @@ import ( "net/http/httptest" "testing" - "github.com/agravelot/image_optimizer/config" + "github.com/agravelot/imageopti/config" ) func TestImageOptimizer_ServeHTTP(t *testing.T) { diff --git a/processor/factory.go b/processor/factory.go index ba58802..f1ae9e2 100644 --- a/processor/factory.go +++ b/processor/factory.go @@ -3,7 +3,7 @@ package processor import ( "fmt" - "github.com/agravelot/image_optimizer/config" + "github.com/agravelot/imageopti/config" ) type Processor interface { diff --git a/processor/factory_test.go b/processor/factory_test.go index ca50635..4abc3ad 100644 --- a/processor/factory_test.go +++ b/processor/factory_test.go @@ -4,8 +4,8 @@ import ( "reflect" "testing" - "github.com/agravelot/image_optimizer/config" - "github.com/agravelot/image_optimizer/processor" + "github.com/agravelot/imageopti/config" + "github.com/agravelot/imageopti/processor" ) func TestNew(t *testing.T) { diff --git a/processor/imaginary.go b/processor/imaginary.go index b2bb878..90cef49 100644 --- a/processor/imaginary.go +++ b/processor/imaginary.go @@ -9,7 +9,7 @@ import ( "net/http" "net/url" - "github.com/agravelot/image_optimizer/config" + "github.com/agravelot/imageopti/config" ) type pipelineOperationParams struct { diff --git a/readme.md b/readme.md index 1e7b5cc..db1a67c 100644 --- a/readme.md +++ b/readme.md @@ -28,8 +28,8 @@ pilot: experimental: plugins: - image_optimizer: - moduleName: github.com/agravelot/image_optimizer + imageopti: + moduleName: github.com/agravelot/imageopti version: v0.1.0 ``` @@ -46,7 +46,7 @@ http: entryPoints: - web middlewares: - - image_optimizer + - imageopti services: service-foo: @@ -55,7 +55,7 @@ http: - url: http://127.0.0.1:5000 middlewares: - image_optimizer: + imageopti: plugin: config: processor: diff --git a/response-writer.go b/response-writer.go index 513ea4b..ca4964a 100644 --- a/response-writer.go +++ b/response-writer.go @@ -1,4 +1,4 @@ -package image_optimizer +package imageopti import ( "bytes" From 694ab0a3493fda405bd8fe8c6fa8f4c35894d5d2 Mon Sep 17 00:00:00 2001 From: agravelot Date: Wed, 5 May 2021 14:16:24 +0200 Subject: [PATCH 03/10] style: more cleanup for linter --- image_optimizer.go | 31 ++++++++++++++++--------------- response-writer.go | 10 +++++++++- 2 files changed, 25 insertions(+), 16 deletions(-) diff --git a/image_optimizer.go b/image_optimizer.go index bed23c7..3f64347 100644 --- a/image_optimizer.go +++ b/image_optimizer.go @@ -1,3 +1,4 @@ +// Package imageopti Image optimizer plugin package imageopti import ( @@ -75,24 +76,18 @@ const ( cacheHitStatus = "hit" cacheMissStatus = "miss" cacheExpiry = 100 * time.Second + targetFormat = "image/webp" ) func (a *ImageOptimizer) ServeHTTP(rw http.ResponseWriter, req *http.Request) { // TODO Check if cacheable - - targetFormat := "image/webp" - // Return cached result here. key, err := cache.Tokenize(req) if err != nil { panic(err) } - + // Return cached result here. if v, err := a.c.Get(key); err == nil { - rw.Header().Set(cacheStatus, cacheHitStatus) - rw.Header().Set(contentLength, fmt.Sprint(len(v))) - rw.Header().Add(contentType, targetFormat) - _, err = rw.Write(v) - + err = writeResponse(rw, targetFormat, cacheHitStatus, v) if err != nil { panic(err) } @@ -132,11 +127,7 @@ func (a *ImageOptimizer) ServeHTTP(rw http.ResponseWriter, req *http.Request) { panic(err) } - rw.Header().Set(contentLength, fmt.Sprint(len(optimized))) - rw.Header().Set(contentType, ct) - rw.Header().Set(cacheStatus, cacheMissStatus) - - _, err = rw.Write(optimized) + err = writeResponse(rw, ct, cacheMissStatus, optimized) if err != nil { panic(err) } @@ -147,6 +138,16 @@ func (a *ImageOptimizer) ServeHTTP(rw http.ResponseWriter, req *http.Request) { } } +func writeResponse(rw http.ResponseWriter, ct, cs string, b []byte) error { + rw.Header().Set(contentLength, fmt.Sprint(len(b))) + rw.Header().Set(contentType, ct) + rw.Header().Set(cacheStatus, cs) + + _, err := rw.Write(b) + + return fmt.Errorf("unable to send response: %w", err) +} + func imageWidthRequest(req *http.Request) (int, error) { w := req.URL.Query().Get("w") @@ -157,7 +158,7 @@ func imageWidthRequest(req *http.Request) (int, error) { v, err := strconv.Atoi(w) if err != nil { - return 0, err + return 0, fmt.Errorf("unable to convert w query param to int: %w", err) } if v < 0 { diff --git a/response-writer.go b/response-writer.go index ca4964a..61fb4f7 100644 --- a/response-writer.go +++ b/response-writer.go @@ -1,7 +1,9 @@ +// Package imageopti Bypass default response writer to override headers and body package imageopti import ( "bytes" + "fmt" "net/http" ) @@ -24,7 +26,13 @@ func (r *responseWriter) Write(p []byte) (int, error) { r.WriteHeader(http.StatusOK) } - return r.buffer.Write(p) + i, err := r.buffer.Write(p) + + if err != nil { + return i, fmt.Errorf("unable to write response body: %w", err) + } + + return i, nil } func (r *responseWriter) Flush() { From 4ad00765332acd4b48563ecaabb995ae12c58c98 Mon Sep 17 00:00:00 2001 From: agravelot Date: Wed, 5 May 2021 18:16:07 +0200 Subject: [PATCH 04/10] style: run gofumpt --- response-writer.go | 1 - 1 file changed, 1 deletion(-) diff --git a/response-writer.go b/response-writer.go index 61fb4f7..1babba6 100644 --- a/response-writer.go +++ b/response-writer.go @@ -27,7 +27,6 @@ func (r *responseWriter) Write(p []byte) (int, error) { } i, err := r.buffer.Write(p) - if err != nil { return i, fmt.Errorf("unable to write response body: %w", err) } From 8dd8ef02222f82ec48f50444247d76b396ef870d Mon Sep 17 00:00:00 2001 From: agravelot Date: Wed, 5 May 2021 18:18:22 +0200 Subject: [PATCH 05/10] style: config linter to ignore todo messages --- .golangci.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.golangci.toml b/.golangci.toml index 912d89e..54b5780 100644 --- a/.golangci.toml +++ b/.golangci.toml @@ -37,6 +37,10 @@ "paralleltest", "tparallel", "scopelint", + "godox", + "funlen", # Re-enable it + "gocognit", # Re-enable it + "cyclop", # Re-enable it ] [issues] From eb9d726045976440cbf40ae0ca932c9a44d6949b Mon Sep 17 00:00:00 2001 From: agravelot Date: Wed, 5 May 2021 18:35:51 +0200 Subject: [PATCH 06/10] fix: remove writeResponse func to avoid nil pointer dereference --- image_optimizer.go | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/image_optimizer.go b/image_optimizer.go index 3f64347..2d50942 100644 --- a/image_optimizer.go +++ b/image_optimizer.go @@ -87,7 +87,11 @@ func (a *ImageOptimizer) ServeHTTP(rw http.ResponseWriter, req *http.Request) { } // Return cached result here. if v, err := a.c.Get(key); err == nil { - err = writeResponse(rw, targetFormat, cacheHitStatus, v) + rw.Header().Set(contentLength, fmt.Sprint(len(v))) + rw.Header().Set(contentType, targetFormat) + rw.Header().Set(cacheStatus, cacheHitStatus) + _, err = rw.Write(v) + if err != nil { panic(err) } @@ -127,7 +131,11 @@ func (a *ImageOptimizer) ServeHTTP(rw http.ResponseWriter, req *http.Request) { panic(err) } - err = writeResponse(rw, ct, cacheMissStatus, optimized) + rw.Header().Set(contentLength, fmt.Sprint(len(optimized))) + rw.Header().Set(contentType, ct) + rw.Header().Set(cacheStatus, cacheMissStatus) + + _, err = rw.Write(optimized) if err != nil { panic(err) } @@ -138,16 +146,6 @@ func (a *ImageOptimizer) ServeHTTP(rw http.ResponseWriter, req *http.Request) { } } -func writeResponse(rw http.ResponseWriter, ct, cs string, b []byte) error { - rw.Header().Set(contentLength, fmt.Sprint(len(b))) - rw.Header().Set(contentType, ct) - rw.Header().Set(cacheStatus, cs) - - _, err := rw.Write(b) - - return fmt.Errorf("unable to send response: %w", err) -} - func imageWidthRequest(req *http.Request) (int, error) { w := req.URL.Query().Get("w") From f2ae25a335e18ad216dd931fcec192fca4fc02af Mon Sep 17 00:00:00 2001 From: agravelot Date: Wed, 5 May 2021 18:42:11 +0200 Subject: [PATCH 07/10] ci: update golangci lint and golang version --- .github/workflows/go-cross.yml | 2 +- .github/workflows/main.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/go-cross.yml b/.github/workflows/go-cross.yml index f579d66..91eb0c6 100644 --- a/.github/workflows/go-cross.yml +++ b/.github/workflows/go-cross.yml @@ -11,7 +11,7 @@ jobs: strategy: matrix: - go-version: [ 1.15, 1.x ] + go-version: [ 1.16, 1.x ] os: [ubuntu-latest, macos-latest, windows-latest] steps: diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 630b69a..52c7ad2 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -14,8 +14,8 @@ jobs: name: Main Process runs-on: ubuntu-latest env: - GO_VERSION: 1.15 - GOLANGCI_LINT_VERSION: v1.33.0 + GO_VERSION: 1.16 + GOLANGCI_LINT_VERSION: v1.39.0 YAEGI_VERSION: v0.9.8 CGO_ENABLED: 0 defaults: From 16417bb5378ec7261a158709f7f0b5e2a70eaea3 Mon Sep 17 00:00:00 2001 From: agravelot Date: Wed, 5 May 2021 18:48:17 +0200 Subject: [PATCH 08/10] style: run gofumpt --- cache/none.go | 3 +-- processor/factory.go | 1 - processor/imaginary.go | 4 ---- processor/local.go | 4 +--- processor/none.go | 3 +-- 5 files changed, 3 insertions(+), 12 deletions(-) diff --git a/cache/none.go b/cache/none.go index 1bde8f2..4b713dd 100644 --- a/cache/none.go +++ b/cache/none.go @@ -5,8 +5,7 @@ import ( "time" ) -type NoneCache struct { -} +type NoneCache struct{} func (c *NoneCache) Get(key string) ([]byte, error) { return nil, fmt.Errorf("no result found with key = %s", key) diff --git a/processor/factory.go b/processor/factory.go index f1ae9e2..5648c1c 100644 --- a/processor/factory.go +++ b/processor/factory.go @@ -11,7 +11,6 @@ type Processor interface { } func New(conf config.Config) (Processor, error) { - if conf.Processor == "imaginary" { p, err := NewImaginary(conf) if err != nil { diff --git a/processor/imaginary.go b/processor/imaginary.go index 90cef49..0b937e6 100644 --- a/processor/imaginary.go +++ b/processor/imaginary.go @@ -35,7 +35,6 @@ type ImaginaryProcessor struct { } func isValidUrl(s string) error { - if s == "" { return fmt.Errorf("url cannot be empty") } @@ -53,7 +52,6 @@ func isValidUrl(s string) error { } func NewImaginary(conf config.Config) (*ImaginaryProcessor, error) { - err := isValidUrl(conf.Imaginary.Url) if err != nil { return nil, err @@ -66,7 +64,6 @@ func NewImaginary(conf config.Config) (*ImaginaryProcessor, error) { } func (ip *ImaginaryProcessor) Optimize(media []byte, originalFormat string, targetFormat string, quality, width int) ([]byte, string, error) { - ope := []pipelineOperation{ {Operation: "convert", Params: pipelineOperationParams{Type: "webp", StripMeta: true}}, } @@ -101,7 +98,6 @@ func (ip *ImaginaryProcessor) Optimize(media []byte, originalFormat string, targ } req, err := http.NewRequest(method, u, payload) - if err != nil { return nil, "", err } diff --git a/processor/local.go b/processor/local.go index e27dcf8..db6271e 100644 --- a/processor/local.go +++ b/processor/local.go @@ -1,10 +1,8 @@ package processor -type LocalProcessor struct { -} +type LocalProcessor struct{} func (lp *LocalProcessor) Optimize(media []byte, originalFormat string, targetFormat string, quality, width int) ([]byte, string, error) { - // newImage, err := bimg.NewImage(media).Convert(bimg.WEBP) // if err != nil { // return nil, err diff --git a/processor/none.go b/processor/none.go index 7fecc28..9ed6ffb 100644 --- a/processor/none.go +++ b/processor/none.go @@ -1,7 +1,6 @@ package processor -type NoneProcessor struct { -} +type NoneProcessor struct{} func (lp *NoneProcessor) Optimize(media []byte, originalFormat string, targetFormat string, quality, width int) ([]byte, string, error) { return media, originalFormat, nil From 839f5517a65d014db58d24fcc68622a7aadd2041 Mon Sep 17 00:00:00 2001 From: agravelot Date: Wed, 5 May 2021 20:18:48 +0200 Subject: [PATCH 09/10] style: make linter happy --- .golangci.toml | 2 ++ cache/factory.go | 9 ++++++-- cache/factory_test.go | 47 ++++++++------------------------------- cache/file_test.go | 8 +++---- cache/memory.go | 4 ++++ cache/memory_test.go | 8 ++++++- cache/none.go | 3 +++ cache/redis.go | 10 ++++----- cache/tokenizer.go | 1 + cache/tokenizer_test.go | 2 ++ processor/factory.go | 3 +++ processor/factory_test.go | 38 ++++++++++++++++++++++--------- processor/imaginary.go | 42 +++++++++++++++++++++------------- processor/local.go | 10 ++++----- processor/none.go | 6 +++-- 15 files changed, 108 insertions(+), 85 deletions(-) diff --git a/.golangci.toml b/.golangci.toml index 54b5780..7ffdeb4 100644 --- a/.golangci.toml +++ b/.golangci.toml @@ -41,6 +41,8 @@ "funlen", # Re-enable it "gocognit", # Re-enable it "cyclop", # Re-enable it + "exhaustivestruct", + "nilerr", ] [issues] diff --git a/cache/factory.go b/cache/factory.go index 2f364c8..05afc4a 100644 --- a/cache/factory.go +++ b/cache/factory.go @@ -1,3 +1,4 @@ +// Package cache provide caching systems for images. package cache import ( @@ -8,14 +9,18 @@ import ( "github.com/agravelot/imageopti/config" ) +// Cache Define cache system interface. type Cache interface { Get(key string) ([]byte, error) Set(key string, val []byte, expiry time.Duration) error } +const defaultCacheExpiry = 100 * time.Second + +// New is the cache factory to instantiate a new instance of cache. func New(conf config.Config) (Cache, error) { // if conf.Processor == "redis" { - // opt, err := redis.ParseURL(conf.Redis.Url) + // opt, err := redis.ParseURL(conf.Redis.URL) // if err != nil { // return nil, err // } @@ -28,7 +33,7 @@ func New(conf config.Config) (Cache, error) { // } if conf.Cache == "file" { - return newFileCache(conf.File.Path, 100*time.Second) + return newFileCache(conf.File.Path, defaultCacheExpiry) } if conf.Cache == "memory" { diff --git a/cache/factory_test.go b/cache/factory_test.go index 048d6d2..dc322a6 100644 --- a/cache/factory_test.go +++ b/cache/factory_test.go @@ -12,6 +12,7 @@ func TestNew(t *testing.T) { type args struct { conf config.Config } + tests := []struct { name string args args @@ -31,47 +32,17 @@ func TestNew(t *testing.T) { wantErr: false, }, { - name: "should not be able to init cache without valid driver", - args: args{config.Config{Processor: "imaginary", Imaginary: config.ImaginaryProcessorConfig{Url: "http://localhost"}, Cache: "unsupported"}}, + name: "should not be able to init cache without valid driver", + args: args{ + config.Config{ + Processor: "imaginary", + Imaginary: config.ImaginaryProcessorConfig{Url: "http://localhost"}, + Cache: "unsupported", + }, + }, want: nil, wantErr: true, }, - // { - // name: "should not be able to init imaginary without valid url", - // args: args{config.Config{Processor: "imaginary", Imaginary: config.ImaginaryConfig{Url: "localhost"}, Cache: "memory"}}, - // want: nil, - // wantErr: true, - // }, - // { - // name: "should not be able to init imaginary without valid url 2 ", - // args: args{config.Config{Processor: "imaginary", Imaginary: config.ImaginaryConfig{Url: "htt://localhost"}}}, - // want: nil, - // wantErr: true, - // }, - // { - // name: "should not be able to init imaginary without url", - // args: args{config.Config{Processor: "imaginary"}}, - // want: nil, - // wantErr: true, - // }, - // { - // name: "should be able to return local optimizer", - // args: args{config.Config{Processor: "local"}}, - // want: &processor.LocalProcessor{}, - // wantErr: false, - // }, - // { - // name: "should return error with unsupported processor", - // args: args{config.Config{Processor: "unsupported"}}, - // want: nil, - // wantErr: true, - // }, - // { - // name: "should return error with empty processor", - // args: args{config.Config{Processor: "unsupported"}}, - // want: nil, - // wantErr: true, - // }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/cache/file_test.go b/cache/file_test.go index 59b041a..e2c0f0b 100644 --- a/cache/file_test.go +++ b/cache/file_test.go @@ -159,15 +159,15 @@ func BenchmarkFileCache_Get(b *testing.B) { } } -func createTempDir(t testing.TB) string { +func createTempDir(tb testing.TB) string { dir, err := ioutil.TempDir("./", "example") if err != nil { - t.Fatal(err) + tb.Fatal(err) } - t.Cleanup(func() { + tb.Cleanup(func() { if err = os.RemoveAll(dir); err != nil { - t.Fatal(err) + tb.Fatal(err) } }) diff --git a/cache/memory.go b/cache/memory.go index 2057ba8..139f53f 100644 --- a/cache/memory.go +++ b/cache/memory.go @@ -6,11 +6,13 @@ import ( "time" ) +// MemoryCache in-memory cache system struct. type MemoryCache struct { mtx sync.RWMutex m map[string][]byte } +// Get return cached image with given key. func (c *MemoryCache) Get(key string) ([]byte, error) { c.mtx.Lock() defer c.mtx.Unlock() @@ -19,9 +21,11 @@ func (c *MemoryCache) Get(key string) ([]byte, error) { if !ok { return nil, fmt.Errorf("no result found with key = %s", key) } + return v, nil } +// Set add a value into in-memory with custom expiry. func (c *MemoryCache) Set(key string, v []byte, expiry time.Duration) error { c.mtx.Lock() defer c.mtx.Unlock() diff --git a/cache/memory_test.go b/cache/memory_test.go index 3a49853..43830f0 100644 --- a/cache/memory_test.go +++ b/cache/memory_test.go @@ -13,9 +13,11 @@ func TestMemoryCache_Get(t *testing.T) { type fields struct { m map[string][]byte } + type args struct { key string } + tests := []struct { name string fields fields @@ -62,10 +64,12 @@ func TestMemoryCache_Set(t *testing.T) { type fields struct { m map[string][]byte } + type args struct { key string v []byte } + tests := []struct { name string fields fields @@ -108,7 +112,7 @@ func TestMemoryCache_Set(t *testing.T) { time.Sleep(1 * time.Second) - v, err = c.Get(tt.args.key) + _, err = c.Get(tt.args.key) if err == nil { t.Errorf("value must be deleted after expiry") } @@ -174,9 +178,11 @@ func TestMemoryCache_delete(t *testing.T) { type fields struct { m map[string][]byte } + type args struct { key string } + tests := []struct { name string fields fields diff --git a/cache/none.go b/cache/none.go index 4b713dd..01636d1 100644 --- a/cache/none.go +++ b/cache/none.go @@ -5,12 +5,15 @@ import ( "time" ) +// NoneCache dummy cache system. type NoneCache struct{} +// Get always return nil with not found error. func (c *NoneCache) Get(key string) ([]byte, error) { return nil, fmt.Errorf("no result found with key = %s", key) } +// Set always return nil. func (c *NoneCache) Set(_ string, _ []byte, _ time.Duration) error { return nil } diff --git a/cache/redis.go b/cache/redis.go index 9170614..f762590 100644 --- a/cache/redis.go +++ b/cache/redis.go @@ -2,14 +2,11 @@ package cache import "time" -// var ctx = context.Background() - -type RedisCache struct { - // client *redis.Client -} +// RedisCache hold redis client. +type RedisCache struct{} // client *redis.Client +// Get return cached media with given key from redis. func (c *RedisCache) Get(key string) ([]byte, error) { - // v, err := c.client.Get(ctx, key).Bytes() // if err == redis.Nil { @@ -23,6 +20,7 @@ func (c *RedisCache) Get(key string) ([]byte, error) { return []byte("unsafe not supported by yaegi"), nil } +// Set add a new image in cache with custom expiry. func (c *RedisCache) Set(key string, v []byte, expiry time.Duration) error { // return c.client.Set(ctx, key, v, expiry).Err() return nil diff --git a/cache/tokenizer.go b/cache/tokenizer.go index ab7be62..b0ab5fb 100644 --- a/cache/tokenizer.go +++ b/cache/tokenizer.go @@ -5,6 +5,7 @@ import ( "net/http" ) +// Tokenize generate unique key for request caching strategy. func Tokenize(req *http.Request) (string, error) { width := req.URL.Query().Get("w") diff --git a/cache/tokenizer_test.go b/cache/tokenizer_test.go index 33a43d0..1155f79 100644 --- a/cache/tokenizer_test.go +++ b/cache/tokenizer_test.go @@ -14,12 +14,14 @@ func TestTokenize(t *testing.T) { if err != nil { t.Fatal(err) } + return req } type args struct { req *http.Request } + tests := []struct { name string args args diff --git a/processor/factory.go b/processor/factory.go index 5648c1c..0354fa1 100644 --- a/processor/factory.go +++ b/processor/factory.go @@ -1,3 +1,4 @@ +// Package processor Handle image processing, including resizing, converting and stripping unwanted metadata. package processor import ( @@ -6,10 +7,12 @@ import ( "github.com/agravelot/imageopti/config" ) +// Processor Define processor interface. type Processor interface { Optimize(media []byte, originalFormat string, targetFormat string, quality, width int) ([]byte, string, error) } +// New Processor factory from dynamic configurations. func New(conf config.Config) (Processor, error) { if conf.Processor == "imaginary" { p, err := NewImaginary(conf) diff --git a/processor/factory_test.go b/processor/factory_test.go index 4abc3ad..4b18f19 100644 --- a/processor/factory_test.go +++ b/processor/factory_test.go @@ -1,27 +1,39 @@ -package processor_test +package processor import ( + "net/http" "reflect" "testing" + "time" "github.com/agravelot/imageopti/config" - "github.com/agravelot/imageopti/processor" ) +const defaultTimeout = 1 * time.Second + func TestNew(t *testing.T) { type args struct { conf config.Config } + tests := []struct { name string args args - want processor.Processor + want Processor wantErr bool }{ { - name: "should be able to return imaginary optimizer", - args: args{config.Config{Processor: "imaginary", Imaginary: config.ImaginaryProcessorConfig{Url: "http://localhost"}}}, - want: &processor.ImaginaryProcessor{}, + name: "should be able to return imaginary optimizer", + args: args{ + config.Config{ + Processor: "imaginary", + Imaginary: config.ImaginaryProcessorConfig{Url: "http://localhost"}, + Cache: "none", + Redis: config.RedisCacheConfig{Url: ""}, + File: config.FileCacheConfig{Path: ""}, + }, + }, + want: &ImaginaryProcessor{"", http.Client{Timeout: defaultTimeout}}, wantErr: false, }, { @@ -31,8 +43,13 @@ func TestNew(t *testing.T) { wantErr: true, }, { - name: "should not be able to init imaginary without valid url 2 ", - args: args{config.Config{Processor: "imaginary", Imaginary: config.ImaginaryProcessorConfig{Url: "htt://localhost"}}}, + name: "should not be able to init imaginary without valid url 2 ", + args: args{ + config.Config{ + Processor: "imaginary", + Imaginary: config.ImaginaryProcessorConfig{Url: "htt://localhost"}, + }, + }, want: nil, wantErr: true, }, @@ -45,7 +62,7 @@ func TestNew(t *testing.T) { { name: "should be able to return local optimizer", args: args{config.Config{Processor: "local"}}, - want: &processor.LocalProcessor{}, + want: &LocalProcessor{}, wantErr: false, }, { @@ -61,9 +78,10 @@ func TestNew(t *testing.T) { wantErr: true, }, } + for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := processor.New(tt.args.conf) + got, err := New(tt.args.conf) if (err != nil) != tt.wantErr { t.Fatalf("New() error = %v, wantErr %v", err, tt.wantErr) } diff --git a/processor/imaginary.go b/processor/imaginary.go index 0b937e6..6789e9a 100644 --- a/processor/imaginary.go +++ b/processor/imaginary.go @@ -1,3 +1,4 @@ +// Package processor Add support for imaginary imge processing service. package processor import ( @@ -8,10 +9,13 @@ import ( "mime/multipart" "net/http" "net/url" + "time" "github.com/agravelot/imageopti/config" ) +const httpTimeout = 5 * time.Second + type pipelineOperationParams struct { Font string `json:"font,omitempty"` Height int `json:"height,omitempty"` @@ -29,19 +33,20 @@ type pipelineOperation struct { Params pipelineOperationParams `json:"params"` } +// ImaginaryProcessor define imaginary processor settings. type ImaginaryProcessor struct { - Url string + URL string client http.Client } -func isValidUrl(s string) error { +func isValidURL(s string) error { if s == "" { return fmt.Errorf("url cannot be empty") } u, err := url.ParseRequestURI(s) if err != nil { - return err + return fmt.Errorf("unable to parse imaginary url: %w", err) } if u.Scheme != "http" && u.Scheme != "https" { @@ -51,19 +56,23 @@ func isValidUrl(s string) error { return nil } +// NewImaginary instantiate a new imaginary instance with given config. func NewImaginary(conf config.Config) (*ImaginaryProcessor, error) { - err := isValidUrl(conf.Imaginary.Url) + err := isValidURL(conf.Imaginary.Url) if err != nil { return nil, err } return &ImaginaryProcessor{ - client: http.Client{}, - Url: conf.Imaginary.Url, + client: http.Client{ + Timeout: httpTimeout, + }, + URL: conf.Imaginary.Url, }, nil } -func (ip *ImaginaryProcessor) Optimize(media []byte, originalFormat string, targetFormat string, quality, width int) ([]byte, string, error) { +// Optimize method to process image with imaginary with given parameters. +func (ip *ImaginaryProcessor) Optimize(media []byte, of string, tf string, q, width int) ([]byte, string, error) { ope := []pipelineOperation{ {Operation: "convert", Params: pipelineOperationParams{Type: "webp", StripMeta: true}}, } @@ -74,47 +83,48 @@ func (ip *ImaginaryProcessor) Optimize(media []byte, originalFormat string, targ opString, err := json.Marshal(ope) if err != nil { - return nil, "", err + return nil, "", fmt.Errorf("unable generate imaginary operations: %w", err) } - u := fmt.Sprintf("%s/pipeline?operations=%s", ip.Url, url.QueryEscape(string(opString))) + u := fmt.Sprintf("%s/pipeline?operations=%s", ip.URL, url.QueryEscape(string(opString))) method := "POST" payload := &bytes.Buffer{} writer := multipart.NewWriter(payload) fileWriter, err := writer.CreateFormFile("file", "tmp.jpg") if err != nil { - return nil, "", err + return nil, "", fmt.Errorf("unable to create file to imaginary file writer: %w", err) } _, err = fileWriter.Write(media) if err != nil { - return nil, "", err + return nil, "", fmt.Errorf("unable to write file to imaginary file writer: %w", err) } err = writer.Close() if err != nil { - return nil, "", err + return nil, "", fmt.Errorf("unable to close imaginary file writer: %w", err) } req, err := http.NewRequest(method, u, payload) if err != nil { - return nil, "", err + return nil, "", fmt.Errorf("unable to create imaginary request: %w", err) } + req.Header.Set("Content-Type", writer.FormDataContentType()) res, err := ip.client.Do(req) if err != nil { - return nil, "", err + return nil, "", fmt.Errorf("unable to send imaginary request: %w", err) } body, err := ioutil.ReadAll(res.Body) if err != nil { - return nil, "", err + return nil, "", fmt.Errorf("unable to read imaginary response body: %w", err) } err = res.Body.Close() if err != nil { - return nil, "", err + return nil, "", fmt.Errorf("unable to close imaginary body response: %w", err) } return body, "image/webp", nil diff --git a/processor/local.go b/processor/local.go index db6271e..7ede9a9 100644 --- a/processor/local.go +++ b/processor/local.go @@ -1,16 +1,14 @@ package processor +// LocalProcessor process images directly in traefik itself, unsupported with interpreter limitations. type LocalProcessor struct{} -func (lp *LocalProcessor) Optimize(media []byte, originalFormat string, targetFormat string, quality, width int) ([]byte, string, error) { +// Optimize optimize image with given params. +func (lp *LocalProcessor) Optimize(media []byte, of string, tf string, q, w int) ([]byte, string, error) { // newImage, err := bimg.NewImage(media).Convert(bimg.WEBP) // if err != nil { // return nil, err // } - // if bimg.NewImage(newImage).Type() == "webp" { - // fmt.Fprintln(os.Stderr, "The image was converted into webp") - // } - - return media, targetFormat, nil + return media, tf, nil } diff --git a/processor/none.go b/processor/none.go index 9ed6ffb..eacdfcb 100644 --- a/processor/none.go +++ b/processor/none.go @@ -1,7 +1,9 @@ package processor +// NoneProcessor dummy processor, using null pattern. type NoneProcessor struct{} -func (lp *NoneProcessor) Optimize(media []byte, originalFormat string, targetFormat string, quality, width int) ([]byte, string, error) { - return media, originalFormat, nil +// Optimize return same data from media. +func (lp *NoneProcessor) Optimize(media []byte, of string, tf string, q, w int) ([]byte, string, error) { + return media, of, nil } From 7b11924130c890609e933256835e9421f87c4e57 Mon Sep 17 00:00:00 2001 From: agravelot Date: Wed, 5 May 2021 20:24:32 +0200 Subject: [PATCH 10/10] style: rename Url to URL --- cache/factory_test.go | 2 +- config/config.go | 8 ++++++-- image_optimizer.go | 4 ++-- image_optimizer_test.go | 16 ++++++++-------- processor/factory_test.go | 8 ++++---- processor/imaginary.go | 4 ++-- processor/local.go | 1 - 7 files changed, 23 insertions(+), 20 deletions(-) diff --git a/cache/factory_test.go b/cache/factory_test.go index dc322a6..310e3f2 100644 --- a/cache/factory_test.go +++ b/cache/factory_test.go @@ -36,7 +36,7 @@ func TestNew(t *testing.T) { args: args{ config.Config{ Processor: "imaginary", - Imaginary: config.ImaginaryProcessorConfig{Url: "http://localhost"}, + Imaginary: config.ImaginaryProcessorConfig{URL: "http://localhost"}, Cache: "unsupported", }, }, diff --git a/config/config.go b/config/config.go index c575007..8ee9e34 100644 --- a/config/config.go +++ b/config/config.go @@ -1,13 +1,17 @@ +// Package config provide configurations structs for imageopti middleware. package config +// ImaginaryProcessorConfig define imaginary image processor configurations. type ImaginaryProcessorConfig struct { - Url string `json:"url" yaml:"url" toml:"url"` + URL string `json:"url" yaml:"url" toml:"url"` } +// RedisCacheConfig define redis cache system configurations. type RedisCacheConfig struct { - Url string `json:"url" yaml:"url" toml:"url"` + URL string `json:"url" yaml:"url" toml:"url"` } +// FileCacheConfig define file cache system configurations. type FileCacheConfig struct { Path string `json:"path" yaml:"path" toml:"path"` } diff --git a/image_optimizer.go b/image_optimizer.go index 2d50942..389042a 100644 --- a/image_optimizer.go +++ b/image_optimizer.go @@ -28,8 +28,8 @@ func CreateConfig() *Config { config.Config{ Processor: "", Cache: "", - Imaginary: config.ImaginaryProcessorConfig{Url: ""}, - Redis: config.RedisCacheConfig{Url: ""}, + Imaginary: config.ImaginaryProcessorConfig{URL: ""}, + Redis: config.RedisCacheConfig{URL: ""}, File: config.FileCacheConfig{Path: ""}, }, } diff --git a/image_optimizer_test.go b/image_optimizer_test.go index bbd8451..74b848e 100644 --- a/image_optimizer_test.go +++ b/image_optimizer_test.go @@ -31,9 +31,9 @@ func TestImageOptimizer_ServeHTTP(t *testing.T) { args: args{ config: config.Config{ Processor: "imaginary", - Imaginary: config.ImaginaryProcessorConfig{Url: "http://localhost"}, + Imaginary: config.ImaginaryProcessorConfig{URL: "http://localhost"}, Cache: "none", - Redis: config.RedisCacheConfig{Url: ""}, + Redis: config.RedisCacheConfig{URL: ""}, File: config.FileCacheConfig{Path: ""}, }, }, @@ -51,9 +51,9 @@ func TestImageOptimizer_ServeHTTP(t *testing.T) { config: config.Config{ Processor: "", Cache: "", - Redis: config.RedisCacheConfig{Url: ""}, + Redis: config.RedisCacheConfig{URL: ""}, File: config.FileCacheConfig{Path: ""}, - Imaginary: config.ImaginaryProcessorConfig{Url: ""}, + Imaginary: config.ImaginaryProcessorConfig{URL: ""}, }, }, want: false, @@ -82,9 +82,9 @@ func TestImageOptimizer_ServeHTTP(t *testing.T) { config: config.Config{ Processor: "local", Cache: "memory", - Redis: config.RedisCacheConfig{Url: ""}, + Redis: config.RedisCacheConfig{URL: ""}, File: config.FileCacheConfig{Path: ""}, - Imaginary: config.ImaginaryProcessorConfig{Url: ""}, + Imaginary: config.ImaginaryProcessorConfig{URL: ""}, }, }, want: false, @@ -101,9 +101,9 @@ func TestImageOptimizer_ServeHTTP(t *testing.T) { config: config.Config{ Processor: "none", Cache: "", - Redis: config.RedisCacheConfig{Url: ""}, + Redis: config.RedisCacheConfig{URL: ""}, File: config.FileCacheConfig{Path: ""}, - Imaginary: config.ImaginaryProcessorConfig{Url: ""}, + Imaginary: config.ImaginaryProcessorConfig{URL: ""}, }, }, want: false, diff --git a/processor/factory_test.go b/processor/factory_test.go index 4b18f19..dc4c41c 100644 --- a/processor/factory_test.go +++ b/processor/factory_test.go @@ -27,9 +27,9 @@ func TestNew(t *testing.T) { args: args{ config.Config{ Processor: "imaginary", - Imaginary: config.ImaginaryProcessorConfig{Url: "http://localhost"}, + Imaginary: config.ImaginaryProcessorConfig{URL: "http://localhost"}, Cache: "none", - Redis: config.RedisCacheConfig{Url: ""}, + Redis: config.RedisCacheConfig{URL: ""}, File: config.FileCacheConfig{Path: ""}, }, }, @@ -38,7 +38,7 @@ func TestNew(t *testing.T) { }, { name: "should not be able to init imaginary without valid url", - args: args{config.Config{Processor: "imaginary", Imaginary: config.ImaginaryProcessorConfig{Url: "localhost"}}}, + args: args{config.Config{Processor: "imaginary", Imaginary: config.ImaginaryProcessorConfig{URL: "localhost"}}}, want: nil, wantErr: true, }, @@ -47,7 +47,7 @@ func TestNew(t *testing.T) { args: args{ config.Config{ Processor: "imaginary", - Imaginary: config.ImaginaryProcessorConfig{Url: "htt://localhost"}, + Imaginary: config.ImaginaryProcessorConfig{URL: "htt://localhost"}, }, }, want: nil, diff --git a/processor/imaginary.go b/processor/imaginary.go index 6789e9a..89345ad 100644 --- a/processor/imaginary.go +++ b/processor/imaginary.go @@ -58,7 +58,7 @@ func isValidURL(s string) error { // NewImaginary instantiate a new imaginary instance with given config. func NewImaginary(conf config.Config) (*ImaginaryProcessor, error) { - err := isValidURL(conf.Imaginary.Url) + err := isValidURL(conf.Imaginary.URL) if err != nil { return nil, err } @@ -67,7 +67,7 @@ func NewImaginary(conf config.Config) (*ImaginaryProcessor, error) { client: http.Client{ Timeout: httpTimeout, }, - URL: conf.Imaginary.Url, + URL: conf.Imaginary.URL, }, nil } diff --git a/processor/local.go b/processor/local.go index 7ede9a9..1e2a97a 100644 --- a/processor/local.go +++ b/processor/local.go @@ -9,6 +9,5 @@ func (lp *LocalProcessor) Optimize(media []byte, of string, tf string, q, w int) // if err != nil { // return nil, err // } - return media, tf, nil }