From d371b31aa4d68bef59688704c0d99421404d9105 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Jun 2026 21:32:39 +0000 Subject: [PATCH] chore(deps): bump github.com/reubenmiller/go-c8y from 0.37.9 to 0.37.11 Bumps [github.com/reubenmiller/go-c8y](https://github.com/reubenmiller/go-c8y) from 0.37.9 to 0.37.11. - [Release notes](https://github.com/reubenmiller/go-c8y/releases) - [Changelog](https://github.com/reubenmiller/go-c8y/blob/main/CHANGELOG.md) - [Commits](https://github.com/reubenmiller/go-c8y/compare/v0.37.9...v0.37.11) --- updated-dependencies: - dependency-name: github.com/reubenmiller/go-c8y dependency-version: 0.37.11 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 +- .../reubenmiller/go-c8y/pkg/c8y/client.go | 34 +++++++---- .../go-c8y/pkg/c8y/commonOptions.go | 4 ++ .../reubenmiller/go-c8y/pkg/c8y/utils.go | 56 ++++++++++++++++++- vendor/modules.txt | 2 +- 6 files changed, 83 insertions(+), 19 deletions(-) diff --git a/go.mod b/go.mod index 45d702c..08bf1bb 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/hashicorp/go-retryablehttp v0.7.8 github.com/hashicorp/go-version v1.9.0 github.com/pkg/errors v0.9.1 - github.com/reubenmiller/go-c8y v0.37.9 + github.com/reubenmiller/go-c8y v0.37.11 github.com/spf13/cobra v1.10.2 github.com/spf13/viper v1.21.0 github.com/stretchr/testify v1.11.1 diff --git a/go.sum b/go.sum index 86c2505..3e4e91d 100644 --- a/go.sum +++ b/go.sum @@ -125,8 +125,8 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/reubenmiller/go-c8y v0.37.9 h1:55XOj9G5fok84gOexyuLny+o9bF5chCBvzOyHVBFOqU= -github.com/reubenmiller/go-c8y v0.37.9/go.mod h1:omJlFF3uDmYwbhiBC5ll5mq44+Yk9jax+tDzkjNje/A= +github.com/reubenmiller/go-c8y v0.37.11 h1:NHQbcfE4+qT9gx/KAApaHHjWJl41dvk6CTajtIS1UYs= +github.com/reubenmiller/go-c8y v0.37.11/go.mod h1:omJlFF3uDmYwbhiBC5ll5mq44+Yk9jax+tDzkjNje/A= github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= diff --git a/vendor/github.com/reubenmiller/go-c8y/pkg/c8y/client.go b/vendor/github.com/reubenmiller/go-c8y/pkg/c8y/client.go index 5ef2c8d..6ea10c4 100644 --- a/vendor/github.com/reubenmiller/go-c8y/pkg/c8y/client.go +++ b/vendor/github.com/reubenmiller/go-c8y/pkg/c8y/client.go @@ -583,7 +583,7 @@ func (c *Client) SetBaseURL(v string) error { // must be a struct whose fields may contain "url" tags. func addOptions(s string, opt interface{}) (string, error) { v := reflect.ValueOf(opt) - if v.Kind() == reflect.Ptr && v.IsNil() { + if v.Kind() == reflect.Pointer && v.IsNil() { return s, nil } @@ -1579,9 +1579,17 @@ func (c *Client) Do(ctx context.Context, req *http.Request, v interface{}, middl return nil, err } + var ctxCommonOptions CommonOptions + + if ctxOptions := ctx.Value(GetContextCommonOptionsKey()); ctxOptions != nil { + if ctxOptions, ok := ctxOptions.(CommonOptions); ok { + ctxCommonOptions = ctxOptions + } + } + response := newResponse(resp, duration) - err = CheckResponse(resp) + err = CheckResponse(response, ctxCommonOptions) if err != nil { // even though there was an error, we still return the response // in case the caller wants to inspect it further @@ -1589,12 +1597,8 @@ func (c *Client) Do(ctx context.Context, req *http.Request, v interface{}, middl return response, err } - if ctxOptions := ctx.Value(GetContextCommonOptionsKey()); ctxOptions != nil { - if ctxOptions, ok := ctxOptions.(CommonOptions); ok { - if ctxOptions.OnResponse != nil { - ctxOptions.OnResponse(response.Response) - } - } + if ctxCommonOptions.OnResponse != nil { + ctxCommonOptions.OnResponse(response.Response) } if v != nil { @@ -1698,13 +1702,16 @@ func (r *ErrorResponse) Error() string { // API error responses are expected to have either no response // body, or a JSON response body that maps to ErrorResponse. Any other // response body will be silently ignored. -func CheckResponse(r *http.Response) error { - if c := r.StatusCode; 200 <= c && c <= 299 { +func CheckResponse(r *Response, opt CommonOptions) error { + if r == nil { + return fmt.Errorf("response is nil") + } + if c := r.StatusCode(); 200 <= c && c <= 299 { return nil } - errorResponse := &ErrorResponse{Response: newResponse(r, 0)} - data, err := io.ReadAll(r.Body) + errorResponse := &ErrorResponse{Response: r} + data, err := io.ReadAll(r.RawBody()) // Store copy of response as error messages are short anyway errorResponse.Response.SetBody(data) @@ -1712,6 +1719,9 @@ func CheckResponse(r *http.Response) error { if err == nil && data != nil { DecodeJSONBytes(data, errorResponse) } + if opt.WithError { + r.SetBody(data) + } return errorResponse } diff --git a/vendor/github.com/reubenmiller/go-c8y/pkg/c8y/commonOptions.go b/vendor/github.com/reubenmiller/go-c8y/pkg/c8y/commonOptions.go index c25e4f1..94e4e2c 100644 --- a/vendor/github.com/reubenmiller/go-c8y/pkg/c8y/commonOptions.go +++ b/vendor/github.com/reubenmiller/go-c8y/pkg/c8y/commonOptions.go @@ -10,6 +10,10 @@ type CommonOptions struct { // DryRun command will not be sent DryRun bool + // Include the body in the response on HTTP errors (>=400) + // otherwise the body will only be included in the returned err + WithError bool + // OnResponse called on the response before the body is processed OnResponse func(response *http.Response) io.Reader } diff --git a/vendor/github.com/reubenmiller/go-c8y/pkg/c8y/utils.go b/vendor/github.com/reubenmiller/go-c8y/pkg/c8y/utils.go index ed617f8..61f31e4 100644 --- a/vendor/github.com/reubenmiller/go-c8y/pkg/c8y/utils.go +++ b/vendor/github.com/reubenmiller/go-c8y/pkg/c8y/utils.go @@ -4,14 +4,45 @@ import ( "bytes" "fmt" "io" + "mime" "mime/multipart" "net/http" + "net/textproto" "os" "path/filepath" "sort" "strings" ) +var multipartQuoteEscaper = strings.NewReplacer("\\", "\\\\", `"`, "\\\"") + +// createFormFile is like multipart.Writer.CreateFormFile but allows the part's +// Content-Type to be set instead of always using application/octet-stream +func createFormFile(w *multipart.Writer, fieldname string, filename string, contentType string) (io.Writer, error) { + if contentType == "" { + contentType = "application/octet-stream" + } + h := make(textproto.MIMEHeader) + h.Set("Content-Disposition", + fmt.Sprintf(`form-data; name="%s"; filename="%s"`, + multipartQuoteEscaper.Replace(fieldname), multipartQuoteEscaper.Replace(filename))) + h.Set("Content-Type", contentType) + return w.CreatePart(h) +} + +// detectContentType returns the content type of a file by first checking the file +// extension, and then by sniffing the first 512 bytes of the content. +// The returned reader yields the full contents including any bytes consumed whilst sniffing +func detectContentType(filename string, r io.Reader) (string, io.Reader) { + if contentType := mime.TypeByExtension(filepath.Ext(filename)); contentType != "" { + return strings.Split(contentType, ";")[0], r + } + buf := make([]byte, 512) + n, _ := io.ReadFull(r, buf) + contentType := http.DetectContentType(buf[:n]) + return strings.Split(contentType, ";")[0], io.MultiReader(bytes.NewReader(buf[:n]), r) +} + // Prepare multipart form-data request which uses io.Pipe to buffer reading the message to ensure files won't be read entirely into memory func prepareMultipartRequest(method string, url string, values map[string]io.Reader) (*http.Request, error) { pr, pw := io.Pipe() @@ -30,8 +61,9 @@ func prepareMultipartRequest(method string, url string, values map[string]io.Rea var err error for _, key := range keys { r := values[key] - if key == "filename" { - // Ignore filename as it is used to name the uploaded file + if key == "filename" || key == "contentType" { + // Ignore filename and contentType as they are used as metadata + // for the uploaded file rather than as standalone form fields continue } @@ -52,7 +84,25 @@ func prepareMultipartRequest(method string, url string, values map[string]io.Rea return } } - if fw, err = w.CreateFormFile(key, filename); err != nil { + // Check if a manual content type was provided, otherwise detect it + // from the filename, falling back to sniffing the content, so files + // such as log files are viewable in the Cumulocity UI (which + // requires a text/* content type) + contentType := "" + if manualContentType, ok := values["contentType"]; ok { + if b, rErr := io.ReadAll(manualContentType); rErr == nil { + contentType = string(b) + } else { + pw.CloseWithError(rErr) + return + } + } + if contentType == "" { + var contents io.Reader + contentType, contents = detectContentType(filename, r) + r = contents + } + if fw, err = createFormFile(w, key, filename, contentType); err != nil { pw.CloseWithError(err) return } diff --git a/vendor/modules.txt b/vendor/modules.txt index c7203c9..9a83813 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -185,7 +185,7 @@ github.com/pkg/errors # github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 ## explicit github.com/pmezard/go-difflib/difflib -# github.com/reubenmiller/go-c8y v0.37.9 +# github.com/reubenmiller/go-c8y v0.37.11 ## explicit; go 1.25.0 github.com/reubenmiller/go-c8y/pkg/c8y github.com/reubenmiller/go-c8y/pkg/c8y/binary