diff --git a/go.mod b/go.mod index 72cfefc7e6..b678a7e7ba 100644 --- a/go.mod +++ b/go.mod @@ -27,7 +27,7 @@ require ( github.com/gorilla/mux v1.8.1 github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 - github.com/hashicorp/consul/api v1.30.0 + github.com/hashicorp/consul/api v1.31.0 github.com/hashicorp/go-cleanhttp v0.5.2 github.com/hashicorp/go-sockaddr v1.0.7 github.com/hashicorp/memberlist v0.5.1 diff --git a/go.sum b/go.sum index 88485cf722..866d42b1ad 100644 --- a/go.sum +++ b/go.sum @@ -1262,8 +1262,8 @@ github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9K github.com/grpc-ecosystem/grpc-gateway/v2 v2.24.0 h1:TmHmbvxPmaegwhDubVz0lICL0J5Ka2vwTzhoePEXsGE= github.com/grpc-ecosystem/grpc-gateway/v2 v2.24.0/go.mod h1:qztMSjm835F2bXf+5HKAPIS5qsmQDqZna/PgVt4rWtI= github.com/hashicorp/consul/api v1.12.0/go.mod h1:6pVBMo0ebnYdt2S3H87XhekM/HHrUoTD2XXb/VrZVy0= -github.com/hashicorp/consul/api v1.30.0 h1:ArHVMMILb1nQv8vZSGIwwQd2gtc+oSQZ6CalyiyH2XQ= -github.com/hashicorp/consul/api v1.30.0/go.mod h1:B2uGchvaXVW2JhFoS8nqTxMD5PBykr4ebY4JWHTTeLM= +github.com/hashicorp/consul/api v1.31.0 h1:32BUNLembeSRek0G/ZAM6WNfdEwYdYo8oQ4+JoqGkNQ= +github.com/hashicorp/consul/api v1.31.0/go.mod h1:2ZGIiXM3A610NmDULmCHd/aqBJj8CkMfOhswhOafxRg= github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms= github.com/hashicorp/consul/sdk v0.16.1 h1:V8TxTnImoPD5cj0U9Spl0TUxcytjcbbJeADFF07KdHg= github.com/hashicorp/consul/sdk v0.16.1/go.mod h1:fSXvwxB2hmh1FMZCNl6PwX0Q/1wdWtHJcZ7Ea5tns0s= diff --git a/vendor/github.com/hashicorp/consul/api/api.go b/vendor/github.com/hashicorp/consul/api/api.go index d4d853d5d4..27af1ea569 100644 --- a/vendor/github.com/hashicorp/consul/api/api.go +++ b/vendor/github.com/hashicorp/consul/api/api.go @@ -1087,8 +1087,23 @@ func (c *Client) doRequest(r *request) (time.Duration, *http.Response, error) { if err != nil { return 0, nil, err } + + contentType := GetContentType(req) + + if req != nil { + req.Header.Set(contentTypeHeader, contentType) + } + start := time.Now() resp, err := c.config.HttpClient.Do(req) + + if resp != nil { + respContentType := resp.Header.Get(contentTypeHeader) + if respContentType == "" || respContentType != contentType { + resp.Header.Set(contentTypeHeader, contentType) + } + } + diff := time.Since(start) return diff, resp, err } diff --git a/vendor/github.com/hashicorp/consul/api/content_type.go b/vendor/github.com/hashicorp/consul/api/content_type.go new file mode 100644 index 0000000000..37c8cf60aa --- /dev/null +++ b/vendor/github.com/hashicorp/consul/api/content_type.go @@ -0,0 +1,81 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package api + +import ( + "net/http" + "strings" +) + +const ( + contentTypeHeader = "Content-Type" + plainContentType = "text/plain; charset=utf-8" + octetStream = "application/octet-stream" + jsonContentType = "application/json" // Default content type +) + +// ContentTypeRule defines a rule for determining the content type of an HTTP request. +// This rule is based on the combination of the HTTP path, method, and the desired content type. +type ContentTypeRule struct { + path string + httpMethod string + contentType string +} + +var ContentTypeRules = []ContentTypeRule{ + { + path: "/v1/snapshot", + httpMethod: http.MethodPut, + contentType: octetStream, + }, + { + path: "/v1/kv", + httpMethod: http.MethodPut, + contentType: octetStream, + }, + { + path: "/v1/event/fire", + httpMethod: http.MethodPut, + contentType: octetStream, + }, +} + +// GetContentType returns the content type for a request +// This function isused as routing logic or middleware to determine and enforce +// the appropriate content type for HTTP requests. +func GetContentType(req *http.Request) string { + reqContentType := req.Header.Get(contentTypeHeader) + + if isIndexPage(req) { + return plainContentType + } + + // For GET, DELETE, or internal API paths, ensure a valid Content-Type is returned. + if req.Method == http.MethodGet || req.Method == http.MethodDelete || strings.HasPrefix(req.URL.Path, "/v1/internal") { + if reqContentType == "" { + // Default to JSON Content-Type if no Content-Type is provided. + return jsonContentType + } + // Return the provided Content-Type if it exists. + return reqContentType + } + + for _, rule := range ContentTypeRules { + if matchesRule(req, rule) { + return rule.contentType + } + } + return jsonContentType +} + +// matchesRule checks if a request matches a content type rule +func matchesRule(req *http.Request, rule ContentTypeRule) bool { + return strings.HasPrefix(req.URL.Path, rule.path) && + (rule.httpMethod == "" || req.Method == rule.httpMethod) +} + +// isIndexPage checks if the request is for the index page +func isIndexPage(req *http.Request) bool { + return req.URL.Path == "/" || req.URL.Path == "/ui" +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 4035c28b7d..7d17aceab0 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -556,7 +556,7 @@ github.com/grpc-ecosystem/go-grpc-middleware/v2 github.com/grpc-ecosystem/grpc-gateway/v2/internal/httprule github.com/grpc-ecosystem/grpc-gateway/v2/runtime github.com/grpc-ecosystem/grpc-gateway/v2/utilities -# github.com/hashicorp/consul/api v1.30.0 +# github.com/hashicorp/consul/api v1.31.0 ## explicit; go 1.19 github.com/hashicorp/consul/api # github.com/hashicorp/errwrap v1.1.0