From 705606fcf5ba7217726710d9ea4d04d30e7547d2 Mon Sep 17 00:00:00 2001 From: Dmitry Pokidov <124110+dooman87@users.noreply.github.com> Date: Wed, 29 Jan 2025 22:51:44 +1100 Subject: [PATCH 01/12] Proxying Accept-Encoding and Accept headers for /asis --- img/loader/http.go | 21 ++++++++++++++++++++- img/service.go | 6 +++++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/img/loader/http.go b/img/loader/http.go index 5ac4147..db9872b 100644 --- a/img/loader/http.go +++ b/img/loader/http.go @@ -33,7 +33,7 @@ var client = &http.Client{ }, } -func (r *Http) Load(url string, _ context.Context) (*img.Image, error) { +func (r *Http) Load(url string, ctx context.Context) (*img.Image, error) { req, err := http.NewRequest("GET", url, nil) if err != nil { return nil, err @@ -44,6 +44,14 @@ func (r *Http) Load(url string, _ context.Context) (*img.Image, error) { } } + if moreHeaders, ok := headerFromContext(ctx); ok { + for k, v := range *moreHeaders { + for _, headerVal := range v { + req.Header.Add(k, headerVal) + } + } + } + resp, err := client.Do(req) if err != nil { return nil, err @@ -70,3 +78,14 @@ func (r *Http) Load(url string, _ context.Context) (*img.Image, error) { MimeType: contentType, }, nil } + +type headersKey int + +func NewContextWithHeaders(ctx context.Context, headers *http.Header) context.Context { + return context.WithValue(ctx, headersKey(0), headers) +} + +func headerFromContext(ctx context.Context) (*http.Header, bool) { + header, ok := ctx.Value(headersKey(0)).(*http.Header) + return header, ok +} diff --git a/img/service.go b/img/service.go index 6313218..a1a43a5 100644 --- a/img/service.go +++ b/img/service.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "github.com/Pixboost/transformimgs/v8/img/loader" "github.com/dooman87/glogi" "github.com/gorilla/mux" "net/http" @@ -192,7 +193,10 @@ func (r *Service) AsIs(resp http.ResponseWriter, req *http.Request) { Log.Printf("Requested image %s as is\n", imgUrl) - result, err := r.Loader.Load(imgUrl, req.Context()) + var proxyHeaders http.Header + proxyHeaders.Add("Accept", req.Header.Get("Accept")) + proxyHeaders.Add("Accept-Encoding", req.Header.Get("Accept-Encoding")) + result, err := r.Loader.Load(imgUrl, loader.NewContextWithHeaders(req.Context(), &proxyHeaders)) if err != nil { sendError(resp, err) From 837ff1b0314bcd974e8072cd118233d3b6824991 Mon Sep 17 00:00:00 2001 From: Dmitry Pokidov <124110+dooman87@users.noreply.github.com> Date: Thu, 30 Jan 2025 22:45:37 +1100 Subject: [PATCH 02/12] Proxying Accept-Encoding and Accept headers for /asis --- img/loader/http.go | 13 +---------- img/loader/http_test.go | 29 +++++++++++++++++++++++-- img/service.go | 27 ++++++++++++++++++----- img/service_test.go | 48 +++++++++++++++++++++++++++++++++++------ 4 files changed, 92 insertions(+), 25 deletions(-) diff --git a/img/loader/http.go b/img/loader/http.go index db9872b..511017d 100644 --- a/img/loader/http.go +++ b/img/loader/http.go @@ -44,7 +44,7 @@ func (r *Http) Load(url string, ctx context.Context) (*img.Image, error) { } } - if moreHeaders, ok := headerFromContext(ctx); ok { + if moreHeaders, ok := img.HeaderFromContext(ctx); ok { for k, v := range *moreHeaders { for _, headerVal := range v { req.Header.Add(k, headerVal) @@ -78,14 +78,3 @@ func (r *Http) Load(url string, ctx context.Context) (*img.Image, error) { MimeType: contentType, }, nil } - -type headersKey int - -func NewContextWithHeaders(ctx context.Context, headers *http.Header) context.Context { - return context.WithValue(ctx, headersKey(0), headers) -} - -func headerFromContext(ctx context.Context) (*http.Header, bool) { - header, ok := ctx.Value(headersKey(0)).(*http.Header) - return header, ok -} diff --git a/img/loader/http_test.go b/img/loader/http_test.go index 971714a..2074add 100644 --- a/img/loader/http_test.go +++ b/img/loader/http_test.go @@ -2,6 +2,7 @@ package loader_test import ( "context" + "github.com/Pixboost/transformimgs/v8/img" "github.com/Pixboost/transformimgs/v8/img/loader" "github.com/dooman87/kolibri/test" "net/http" @@ -72,7 +73,7 @@ func TestHttp_LoadImgErrorResponseStatus(t *testing.T) { ) } -func TestHttp_LoadCustomHeaders(t *testing.T) { +func TestHttp_LoadCustomGlobalHeaders(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Header.Get("this-is-header") != "wow" { w.WriteHeader(http.StatusInternalServerError) @@ -100,7 +101,7 @@ func TestHttp_LoadCustomHeaders(t *testing.T) { ) } -func FuzzHttp_LoadCustomHeaders(f *testing.F) { +func FuzzHttp_LoadCustomGlobalHeaders(f *testing.F) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Add("Content-Type", "cool/stuff") w.Write([]byte("123")) @@ -137,3 +138,27 @@ func FuzzHttp_LoadCustomHeaders(f *testing.F) { } }) } + +func TestHttp_LoadCustomContextHeaders(t *testing.T) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Header.Get("this-is-header") != "wow" { + w.WriteHeader(http.StatusInternalServerError) + } else { + w.Header().Add("Content-Type", "cool/stuff") + w.Write([]byte("123")) + } + })) + defer server.Close() + + httpLoader := &loader.Http{} + + image, err := httpLoader.Load(server.URL, img.NewContextWithHeaders(context.Background(), &http.Header{ + "This-Is-Header": []string{"wow"}, + })) + + test.Error(t, + test.Nil(err, "error"), + test.Equal("cool/stuff", image.MimeType, "content type"), + test.Equal("123", string(image.Data), "resulted image"), + ) +} diff --git a/img/service.go b/img/service.go index a1a43a5..7c175dd 100644 --- a/img/service.go +++ b/img/service.go @@ -4,7 +4,6 @@ import ( "context" "errors" "fmt" - "github.com/Pixboost/transformimgs/v8/img/loader" "github.com/dooman87/glogi" "github.com/gorilla/mux" "net/http" @@ -193,10 +192,17 @@ func (r *Service) AsIs(resp http.ResponseWriter, req *http.Request) { Log.Printf("Requested image %s as is\n", imgUrl) - var proxyHeaders http.Header - proxyHeaders.Add("Accept", req.Header.Get("Accept")) - proxyHeaders.Add("Accept-Encoding", req.Header.Get("Accept-Encoding")) - result, err := r.Loader.Load(imgUrl, loader.NewContextWithHeaders(req.Context(), &proxyHeaders)) + var proxyHeaders = make(http.Header) + + accept := req.Header.Get("Accept") + if len(accept) > 0 { + proxyHeaders.Add("Accept", accept) + } + acceptEncoding := req.Header.Get("Accept-Encoding") + if len(acceptEncoding) > 0 { + proxyHeaders.Add("Accept-Encoding", acceptEncoding) + } + result, err := r.Loader.Load(imgUrl, NewContextWithHeaders(req.Context(), &proxyHeaders)) if err != nil { sendError(resp, err) @@ -395,3 +401,14 @@ func sendError(resp http.ResponseWriter, err error) { } } } + +type headersKey int + +func NewContextWithHeaders(ctx context.Context, headers *http.Header) context.Context { + return context.WithValue(ctx, headersKey(0), headers) +} + +func HeaderFromContext(ctx context.Context) (*http.Header, bool) { + header, ok := ctx.Value(headersKey(0)).(*http.Header) + return header, ok +} diff --git a/img/service_test.go b/img/service_test.go index fe52c3f..afba6c4 100644 --- a/img/service_test.go +++ b/img/service_test.go @@ -24,6 +24,7 @@ const ( ImgLowQualityOut = "12" ImgLowerQualityOut = "1" ImgBorderTrimmed = "777" + ImgGzipSvg = "888" EmptyGifBase64Out = "R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" ) @@ -122,23 +123,40 @@ func (r *resizerMock) resultImage(config *img.TransformationConfig) *img.Image { type loaderMock struct{} -func (l *loaderMock) Load(url string, _ context.Context) (*img.Image, error) { - if url == "http://site.com/img.png" { +func (l *loaderMock) Load(url string, ctx context.Context) (*img.Image, error) { + switch url { + case "http://site.com/img.png": return &img.Image{ Data: []byte(ImgSrc), MimeType: "image/png", Id: url, }, nil - } - if url == "http://site.com/img2.png" { + case "http://site.com/img2.png": return &img.Image{ Data: []byte(NoContentTypeImgSrc), MimeType: "image/png", Id: url, }, nil - } - if url == "http://site.com/custom_error.png" { + case "http://site.com/custom_error.png": return nil, img.NewHttpError(http.StatusTeapot, "Uh oh :(") + + case "http://site.com/img.svg": + if acceptEncoding, ok := img.HeaderFromContext(ctx); ok && acceptEncoding.Get("Accept-Encoding") == "gzip" { + return &img.Image{ + Data: []byte(ImgSrc), + MimeType: "svg/gzip", + Id: url, + }, nil + } + } + + if url == "http://site.com/img.png" { + } + + if url == "" { + } + if url == "" { + } return nil, errors.New("read_error") } @@ -575,6 +593,24 @@ func TestService_AsIs(t *testing.T) { ) }, }, + { + Description: "Success with custom accept encoding", + Request: &http.Request{ + Method: "GET", + URL: parseUrl("http://localhost/img/http%3A%2F%2Fsite.com/img.svg/asis", t), + Header: map[string][]string{ + "Accept-Encoding": {"gzip"}, + }, + }, + Handler: func(w *httptest.ResponseRecorder, t *testing.T) { + test.Error(t, + test.Equal("public, max-age=86400", w.Header().Get("Cache-Control"), "Cache-Control header"), + test.Equal("3", w.Header().Get("Content-Length"), "Content-Length header"), + test.Equal("svg/gzip", w.Header().Get("Content-Type"), "Content-Type header"), + test.Equal("", w.Header().Get("Vary"), "No Vary header"), + ) + }, + }, { Request: &http.Request{ Method: "GET", From 92921a1b5d4375687d4620732a7e4e25cd2d3e19 Mon Sep 17 00:00:00 2001 From: Dmitry Pokidov <124110+dooman87@users.noreply.github.com> Date: Fri, 31 Jan 2025 22:18:59 +1100 Subject: [PATCH 03/12] Proxying Accept-Encoding and Accept headers for /asis --- img/loader/http.go | 8 +++++--- img/service.go | 16 ++++++++-------- img/service_test.go | 20 ++++++++++++++++---- img/types.go | 3 +++ run.sh | 9 +-------- test.sh | 1 + 6 files changed, 34 insertions(+), 23 deletions(-) diff --git a/img/loader/http.go b/img/loader/http.go index 511017d..ded6d8d 100644 --- a/img/loader/http.go +++ b/img/loader/http.go @@ -66,6 +66,7 @@ func (r *Http) Load(url string, ctx context.Context) (*img.Image, error) { } contentType := resp.Header.Get("Content-Type") + contentEncoding := resp.Header.Get("Content-Encoding") result, err := ioutil.ReadAll(resp.Body) if err != nil { @@ -73,8 +74,9 @@ func (r *Http) Load(url string, ctx context.Context) (*img.Image, error) { } return &img.Image{ - Id: url, - Data: result, - MimeType: contentType, + Id: url, + Data: result, + MimeType: contentType, + ContentEncoding: contentEncoding, }, nil } diff --git a/img/service.go b/img/service.go index 7c175dd..0a86dab 100644 --- a/img/service.go +++ b/img/service.go @@ -193,7 +193,6 @@ func (r *Service) AsIs(resp http.ResponseWriter, req *http.Request) { Log.Printf("Requested image %s as is\n", imgUrl) var proxyHeaders = make(http.Header) - accept := req.Header.Get("Accept") if len(accept) > 0 { proxyHeaders.Add("Accept", accept) @@ -202,6 +201,7 @@ func (r *Service) AsIs(resp http.ResponseWriter, req *http.Request) { if len(acceptEncoding) > 0 { proxyHeaders.Add("Accept-Encoding", acceptEncoding) } + result, err := r.Loader.Load(imgUrl, NewContextWithHeaders(req.Context(), &proxyHeaders)) if err != nil { @@ -209,10 +209,6 @@ func (r *Service) AsIs(resp http.ResponseWriter, req *http.Request) { return } - if len(result.MimeType) > 0 { - resp.Header().Add("Content-Type", result.MimeType) - } - r.execOp(&Command{ Config: &TransformationConfig{ Src: &Image{ @@ -249,11 +245,15 @@ func (r *Service) getQueue() *Queue { // Adds Content-Length and Cache-Control headers func addHeaders(resp http.ResponseWriter, image *Image) { + headers := resp.Header() if len(image.MimeType) != 0 { - resp.Header().Add("Content-Type", image.MimeType) + headers.Add("Content-Type", image.MimeType) + } + if len(image.ContentEncoding) != 0 { + headers.Add("Content-Encoding", image.ContentEncoding) } - resp.Header().Add("Content-Length", strconv.Itoa(len(image.Data))) - resp.Header().Add("Cache-Control", fmt.Sprintf("public, max-age=%d", CacheTTL)) + headers.Add("Content-Length", strconv.Itoa(len(image.Data))) + headers.Add("Cache-Control", fmt.Sprintf("public, max-age=%d", CacheTTL)) } func getQueryParam(url *url.URL, name string) (string, bool) { diff --git a/img/service_test.go b/img/service_test.go index afba6c4..b7d6b73 100644 --- a/img/service_test.go +++ b/img/service_test.go @@ -143,9 +143,10 @@ func (l *loaderMock) Load(url string, ctx context.Context) (*img.Image, error) { case "http://site.com/img.svg": if acceptEncoding, ok := img.HeaderFromContext(ctx); ok && acceptEncoding.Get("Accept-Encoding") == "gzip" { return &img.Image{ - Data: []byte(ImgSrc), - MimeType: "svg/gzip", - Id: url, + Data: []byte(ImgSrc), + MimeType: "svg/xml", + ContentEncoding: "gzip", + Id: url, }, nil } } @@ -606,7 +607,8 @@ func TestService_AsIs(t *testing.T) { test.Error(t, test.Equal("public, max-age=86400", w.Header().Get("Cache-Control"), "Cache-Control header"), test.Equal("3", w.Header().Get("Content-Length"), "Content-Length header"), - test.Equal("svg/gzip", w.Header().Get("Content-Type"), "Content-Type header"), + test.Equal("svg/xml", w.Header().Get("Content-Type"), "Content-Type header"), + test.Equal("gzip", w.Header().Get("Content-Encoding"), "Content-Encoding header"), test.Equal("", w.Header().Get("Vary"), "No Vary header"), ) }, @@ -695,6 +697,16 @@ func FuzzService_ResizeUrl(f *testing.F) { }) } +func TestHeaderFromContext(t *testing.T) { + header, ok := img.HeaderFromContext(context.Background()) + if header != nil { + t.Errorf("expected nil header") + } + if ok { + t.Errorf("expected ok to be false") + } +} + func createService(t *testing.T) *img.Service { img.CacheTTL = 86400 s, err := img.NewService(&loaderMock{}, &resizerMock{}, 1) diff --git a/img/types.go b/img/types.go index da376ff..8c7e240 100644 --- a/img/types.go +++ b/img/types.go @@ -6,6 +6,9 @@ type Image struct { Id string Data []byte MimeType string + // Content encoding is a literally Content-Encoding header from the response + // because of the #32 (https://github.com/Pixboost/transformimgs/issues/32) + ContentEncoding string } // Info holds basic information about an image. diff --git a/run.sh b/run.sh index 0763c2b..2053400 100644 --- a/run.sh +++ b/run.sh @@ -2,11 +2,4 @@ set -e -# Fetching and installing all dependencies -# and running server on port 8080. Using this -# script to run the application inside docker -# container. - -cd cmd/ -echo 'Running Application' -go run main.go -imConvert=/usr/local/bin/convert -imIdentify=/usr/local/bin/identify $@ \ No newline at end of file +go run cmd/main.go -imConvert=/usr/local/bin/convert -imIdentify=/usr/local/bin/identify $@ diff --git a/test.sh b/test.sh index bf88069..4e498be 100755 --- a/test.sh +++ b/test.sh @@ -10,6 +10,7 @@ go test $(go list -buildvcs=false ./... | grep -v '/vendor/') -v -bench . -bench go test -fuzz=FuzzCalculateTargetSizeForResize -fuzztime 30s ./img/processor/internal/ go test -fuzz=FuzzCalculateTargetSizeForFit -fuzztime 30s ./img/processor/internal/ go test -fuzz=FuzzHttp_LoadImg -fuzztime 30s ./img/loader/ +go test -fuzz=FuzzHttp_LoadCustomGlobalHeaders -fuzztime 30s ./img/loader/ go test -fuzz=FuzzService_ResizeUrl -fuzztime 30s ./img/ echo 'Running go vet' From 9e144e854af29352a529d78aee575f0fd7334417 Mon Sep 17 00:00:00 2001 From: Dmitry Pokidov <124110+dooman87@users.noreply.github.com> Date: Sun, 2 Feb 2025 21:02:15 +1100 Subject: [PATCH 04/12] Fixed test when context is nil --- img/service.go | 4 ++++ img/service_test.go | 12 +++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/img/service.go b/img/service.go index 0a86dab..2beda35 100644 --- a/img/service.go +++ b/img/service.go @@ -409,6 +409,10 @@ func NewContextWithHeaders(ctx context.Context, headers *http.Header) context.Co } func HeaderFromContext(ctx context.Context) (*http.Header, bool) { + if ctx == nil { + return nil, false + } + header, ok := ctx.Value(headersKey(0)).(*http.Header) return header, ok } diff --git a/img/service_test.go b/img/service_test.go index b7d6b73..74280d5 100644 --- a/img/service_test.go +++ b/img/service_test.go @@ -697,7 +697,7 @@ func FuzzService_ResizeUrl(f *testing.F) { }) } -func TestHeaderFromContext(t *testing.T) { +func TestHeaderFromContext_NoHeader(t *testing.T) { header, ok := img.HeaderFromContext(context.Background()) if header != nil { t.Errorf("expected nil header") @@ -707,6 +707,16 @@ func TestHeaderFromContext(t *testing.T) { } } +func TestHeaderFromContext_NoContext(t *testing.T) { + header, ok := img.HeaderFromContext(nil) + if header != nil { + t.Errorf("expected nil header") + } + if ok { + t.Errorf("expected ok to be false") + } +} + func createService(t *testing.T) *img.Service { img.CacheTTL = 86400 s, err := img.NewService(&loaderMock{}, &resizerMock{}, 1) From 549b2c0c2730cc4f0c591407aed66079aec75eac Mon Sep 17 00:00:00 2001 From: Dmitry Pokidov <124110+dooman87@users.noreply.github.com> Date: Mon, 3 Feb 2025 20:18:31 +1100 Subject: [PATCH 05/12] Fixing codecov --- .github/workflows/action.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/action.yml b/.github/workflows/action.yml index 43906a8..608b582 100644 --- a/.github/workflows/action.yml +++ b/.github/workflows/action.yml @@ -49,10 +49,10 @@ jobs: name: Run tests run: | docker run --entrypoint=/go/src/github.com/Pixboost/transformimgs/test.sh -v $(pwd):/go/src/github.com/Pixboost/transformimgs transformimgs-dev - - - name: Code coverage - run: | - bash <(curl -s https://codecov.io/bash) + - id: codecov + uses: codecov/codecov-action@v5 + with: + token: ${{ secrets.CODECOV_TOKEN }} - name: Build a prod image id: docker_build_prod From 199c7f07cbbb754542f043b8052b086833244224 Mon Sep 17 00:00:00 2001 From: Dmitry Pokidov <124110+dooman87@users.noreply.github.com> Date: Mon, 3 Feb 2025 20:40:21 +1100 Subject: [PATCH 06/12] Added test for Accept header --- img/service_test.go | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/img/service_test.go b/img/service_test.go index 74280d5..5e8c80a 100644 --- a/img/service_test.go +++ b/img/service_test.go @@ -141,13 +141,17 @@ func (l *loaderMock) Load(url string, ctx context.Context) (*img.Image, error) { return nil, img.NewHttpError(http.StatusTeapot, "Uh oh :(") case "http://site.com/img.svg": - if acceptEncoding, ok := img.HeaderFromContext(ctx); ok && acceptEncoding.Get("Accept-Encoding") == "gzip" { - return &img.Image{ - Data: []byte(ImgSrc), - MimeType: "svg/xml", - ContentEncoding: "gzip", - Id: url, - }, nil + if headers, ok := img.HeaderFromContext(ctx); ok { + accept := headers.Get("Accept") + acceptEncoding := headers.Get("Accept-Encoding") + if accept == "svg" && acceptEncoding == "gzip" { + return &img.Image{ + Data: []byte(ImgSrc), + MimeType: "svg/xml", + ContentEncoding: "gzip", + Id: url, + }, nil + } } } @@ -601,6 +605,7 @@ func TestService_AsIs(t *testing.T) { URL: parseUrl("http://localhost/img/http%3A%2F%2Fsite.com/img.svg/asis", t), Header: map[string][]string{ "Accept-Encoding": {"gzip"}, + "Accept": {"svg"}, }, }, Handler: func(w *httptest.ResponseRecorder, t *testing.T) { From 3c7ae8b41a64161d7d0d19d574e4d34099837535 Mon Sep 17 00:00:00 2001 From: Dmitry Pokidov <124110+dooman87@users.noreply.github.com> Date: Mon, 3 Feb 2025 21:19:19 +1100 Subject: [PATCH 07/12] Added gosec --- .github/workflows/action.yml | 6 ++++++ cmd/main.go | 9 ++++++++- img/processor/imagemagick.go | 4 ++-- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/.github/workflows/action.yml b/.github/workflows/action.yml index 608b582..2db3542 100644 --- a/.github/workflows/action.yml +++ b/.github/workflows/action.yml @@ -45,6 +45,12 @@ jobs: tags: transformimgs-dev cache-from: type=local,src=/tmp/.buildx-cache cache-to: type=local,dest=/tmp/.buildx-cache + - + name: Gosec + id: gosec + uses: securego/gosec@master + with: + args: ./... - name: Run tests run: | diff --git a/cmd/main.go b/cmd/main.go index aefa105..0bd3c79 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -9,6 +9,7 @@ import ( "net/http" "os" "runtime" + "time" ) func main() { @@ -46,7 +47,13 @@ func main() { router.HandleFunc("/health", health.Health) img.Log.Printf("Running the application on port 8080...\n") - err = http.ListenAndServe(":8080", router) + server := http.Server{ + Addr: ":8080", + Handler: router, + ReadTimeout: 5 * time.Second, + WriteTimeout: 10 * time.Second, + } + err = server.ListenAndServe() if err != nil { img.Log.Errorf("Error while stopping application: %+v", err) diff --git a/img/processor/imagemagick.go b/img/processor/imagemagick.go index ef6962d..9031a7b 100644 --- a/img/processor/imagemagick.go +++ b/img/processor/imagemagick.go @@ -252,7 +252,7 @@ func (p *ImageMagick) Optimise(config *img.TransformationConfig) (*img.Image, er func (p *ImageMagick) execImagemagick(in *bytes.Reader, args []string, imgId string) ([]byte, error) { var out, cmderr bytes.Buffer - cmd := exec.Command(p.convertCmd) + cmd := exec.Command(p.convertCmd) // #nosec G204 - sanitizing before assigning cmd.Args = append(cmd.Args, args...) @@ -295,7 +295,7 @@ func (p *ImageMagick) LoadImageInfo(src *img.Image) (*img.Info, error) { var out, cmderr bytes.Buffer imgId := src.Id in := bytes.NewReader(src.Data) - cmd := exec.Command(p.identifyCmd) + cmd := exec.Command(p.identifyCmd) // #nosec G204 - sanitizing before assigning cmd.Args = append(cmd.Args, "-format", "%m %Q %[opaque] %w %h", "-") cmd.Stdin = in From 2373020a96e687f704ddb91539c18da978a91727 Mon Sep 17 00:00:00 2001 From: Dmitry Pokidov <124110+dooman87@users.noreply.github.com> Date: Mon, 3 Feb 2025 21:40:28 +1100 Subject: [PATCH 08/12] Added gosec --- .github/workflows/action.yml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/.github/workflows/action.yml b/.github/workflows/action.yml index 2db3542..f648ccd 100644 --- a/.github/workflows/action.yml +++ b/.github/workflows/action.yml @@ -50,7 +50,17 @@ jobs: id: gosec uses: securego/gosec@master with: - args: ./... + args: + - -exclude-dir illustration + - ./... + - + name: Gosec illustration + id: gosecillustration + working-directory: ./illustration + uses: securego/gosec@master + with: + args: + - ./... - name: Run tests run: | From 2a2898b9c77aa82b7f08df706017513b31631c00 Mon Sep 17 00:00:00 2001 From: Dmitry Pokidov <124110+dooman87@users.noreply.github.com> Date: Mon, 3 Feb 2025 21:45:50 +1100 Subject: [PATCH 09/12] Added gosec --- .github/workflows/action.yml | 37 ++++++++++++------------------------ 1 file changed, 12 insertions(+), 25 deletions(-) diff --git a/.github/workflows/action.yml b/.github/workflows/action.yml index f648ccd..400f986 100644 --- a/.github/workflows/action.yml +++ b/.github/workflows/action.yml @@ -17,24 +17,21 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 - - - name: Set up Docker Buildx + - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Login to DockerHub uses: docker/login-action@v3 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - - - name: Cache Docker layers + - name: Cache Docker layers uses: actions/cache@v4 with: path: /tmp/.buildx-cache key: ${{ runner.os }}-buildx-${{ github.sha }} restore-keys: | ${{ runner.os }}-buildx- - - - name: Build a dev image + - name: Build a dev image id: docker_build_dev uses: docker/build-push-action@v5 with: @@ -45,32 +42,25 @@ jobs: tags: transformimgs-dev cache-from: type=local,src=/tmp/.buildx-cache cache-to: type=local,dest=/tmp/.buildx-cache - - - name: Gosec + - name: Gosec id: gosec uses: securego/gosec@master with: - args: - - -exclude-dir illustration - - ./... - - - name: Gosec illustration + args: -exclude-dir illustration ./... + - name: Gosec illustration id: gosecillustration working-directory: ./illustration uses: securego/gosec@master with: - args: - - ./... - - - name: Run tests + args: ./... + - name: Run tests run: | docker run --entrypoint=/go/src/github.com/Pixboost/transformimgs/test.sh -v $(pwd):/go/src/github.com/Pixboost/transformimgs transformimgs-dev - id: codecov uses: codecov/codecov-action@v5 with: token: ${{ secrets.CODECOV_TOKEN }} - - - name: Build a prod image + - name: Build a prod image id: docker_build_prod uses: docker/build-push-action@v5 with: @@ -83,17 +73,14 @@ jobs: "BRANCH=${{ github.ref_name }}" cache-from: type=local,src=/tmp/.buildx-cache cache-to: type=local,dest=/tmp/.buildx-cache - - - name: Run the service + - name: Run the service run: | docker run -p 8080:8080 -d transformimgs sleep 5 - - - name: Smoketest + - name: Smoketest run: | curl -o /dev/null -f http://localhost:8080/img/https://pixboost.com/img/homepage/hero.jpg/resize?size=x600 - - - name: Publish image + - name: Publish image if: ${{ github.event_name == 'release' }} uses: docker/build-push-action@v5 with: From 2ef3a56d8573428ad6698b0cf494ace0ab70bb13 Mon Sep 17 00:00:00 2001 From: Dmitry Pokidov <124110+dooman87@users.noreply.github.com> Date: Mon, 3 Feb 2025 21:55:58 +1100 Subject: [PATCH 10/12] Added gosec --- .github/workflows/action.yml | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/.github/workflows/action.yml b/.github/workflows/action.yml index 400f986..edf6ee2 100644 --- a/.github/workflows/action.yml +++ b/.github/workflows/action.yml @@ -44,15 +44,14 @@ jobs: cache-to: type=local,dest=/tmp/.buildx-cache - name: Gosec id: gosec - uses: securego/gosec@master - with: - args: -exclude-dir illustration ./... - - name: Gosec illustration - id: gosecillustration - working-directory: ./illustration - uses: securego/gosec@master - with: - args: ./... + run: | + CWD=$(pwd) + cd /tmp + curl -L https://github.com/securego/gosec/releases/download/v2.22.0/gosec_2.22.0_linux_amd64.tar.gz | tar zx + cd $CWD + /tmp/gosec -exclude-dir illustration ./... + cd illustration + /tmp/gosec ./... - name: Run tests run: | docker run --entrypoint=/go/src/github.com/Pixboost/transformimgs/test.sh -v $(pwd):/go/src/github.com/Pixboost/transformimgs transformimgs-dev From 764ee048cd84e5cc01ac661cb6b94aefe5a18b06 Mon Sep 17 00:00:00 2001 From: Dmitry Pokidov <124110+dooman87@users.noreply.github.com> Date: Mon, 3 Feb 2025 23:18:40 +1100 Subject: [PATCH 11/12] Added gosec --- illustration/main.go | 11 +++++++---- illustration/main_test.go | 16 ++++++++++++++++ 2 files changed, 23 insertions(+), 4 deletions(-) create mode 100644 illustration/main_test.go diff --git a/illustration/main.go b/illustration/main.go index 39697ff..3f77d4c 100644 --- a/illustration/main.go +++ b/illustration/main.go @@ -63,9 +63,9 @@ func main() { count uint currColor *imagick.PixelWand pixelsCount = uint(0) - totalPixelsCount = float32(mw.GetImageHeight() * mw.GetImageWidth()) - tenPercent = uint(totalPixelsCount * 0.1) - fiftyPercent = uint(totalPixelsCount * 0.5) + totalPixelsCount = mw.GetImageHeight() * mw.GetImageWidth() + tenPercent = totalPixelsCount / 10 + fiftyPercent = totalPixelsCount / 2 isBackground = false lastBackgroundColor *imagick.PixelWand colorsInBackground = uint(0) @@ -108,7 +108,7 @@ func main() { pixelsInBackground = 0 } else { pixelsCount += count - fiftyPercent = uint((totalPixelsCount - float32(pixelsInBackground)) * 0.5) + fiftyPercent = (totalPixelsCount - pixelsInBackground) / 2 } } default: @@ -116,6 +116,9 @@ func main() { } } + if colorIdx < 0 { + log.Fatal("colorIdx < 0") + } colorsCntIn50Pct := uint(colorIdx) - colorsInBackground fmt.Print(colorsCntIn50Pct < 10 || (float32(colorsCntIn50Pct)/float32(colorsCnt)) <= 0.02) diff --git a/illustration/main_test.go b/illustration/main_test.go new file mode 100644 index 0000000..ac613e3 --- /dev/null +++ b/illustration/main_test.go @@ -0,0 +1,16 @@ +package main + +import "testing" + +func TestPercentage(t *testing.T) { + + b := 1234 + a := uint(float32(b) * 0.1) + if uint(b/10) != a { + t.Errorf("%d != %d", 1234/10, uint(float32(b)*0.1)) + } + + if a != uint(123) { + t.Errorf("%d != %d", a, uint(123)) + } +} From 0d0c6d21671083a25e90dec67203bc9c459f04e8 Mon Sep 17 00:00:00 2001 From: Dmitry Pokidov <124110+dooman87@users.noreply.github.com> Date: Tue, 11 Feb 2025 21:44:29 +1100 Subject: [PATCH 12/12] Cleaned up tests --- illustration/main_test.go | 16 ---------------- img/service_test.go | 8 -------- 2 files changed, 24 deletions(-) delete mode 100644 illustration/main_test.go diff --git a/illustration/main_test.go b/illustration/main_test.go deleted file mode 100644 index ac613e3..0000000 --- a/illustration/main_test.go +++ /dev/null @@ -1,16 +0,0 @@ -package main - -import "testing" - -func TestPercentage(t *testing.T) { - - b := 1234 - a := uint(float32(b) * 0.1) - if uint(b/10) != a { - t.Errorf("%d != %d", 1234/10, uint(float32(b)*0.1)) - } - - if a != uint(123) { - t.Errorf("%d != %d", a, uint(123)) - } -} diff --git a/img/service_test.go b/img/service_test.go index 5e8c80a..2b8a058 100644 --- a/img/service_test.go +++ b/img/service_test.go @@ -155,14 +155,6 @@ func (l *loaderMock) Load(url string, ctx context.Context) (*img.Image, error) { } } - if url == "http://site.com/img.png" { - } - - if url == "" { - } - if url == "" { - - } return nil, errors.New("read_error") }