Skip to content

Commit 4953761

Browse files
benluddyk8s-publishing-bot
authored andcommitted
Fix content type fallback when a client defaults to CBOR.
With the ClientsAllowCBOR client-go feature gate enabled, a 415 response to a CBOR-encoded REST causes all subsequent requests from the client to fall back to a JSON request encoding. This mechanism had only worked as intended when CBOR was explicitly configured in the ClientContentConfig. When both ClientsAllowCBOR and ClientsPreferCBOR are enabled, an unconfigured (empty) content type defaults to CBOR instead of JSON. Both ways of configuring a client to use the CBOR request encoding are now subject to the same fallback mechanism. Kubernetes-commit: a77f4c7ba2e761461daaf115a38903fc91916dd6
1 parent c57dbd8 commit 4953761

File tree

2 files changed

+27
-20
lines changed

2 files changed

+27
-20
lines changed

rest/client.go

+22-11
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,8 @@ func (c *RESTClient) Delete() *Request {
238238

239239
// APIVersion returns the APIVersion this RESTClient is expected to use.
240240
func (c *RESTClient) APIVersion() schema.GroupVersion {
241-
return c.content.GetClientContentConfig().GroupVersion
241+
config, _ := c.content.GetClientContentConfig()
242+
return config.GroupVersion
242243
}
243244

244245
// requestClientContentConfigProvider observes HTTP 415 (Unsupported Media Type) responses to detect
@@ -257,25 +258,35 @@ type requestClientContentConfigProvider struct {
257258
}
258259

259260
// GetClientContentConfig returns the ClientContentConfig that should be used for new requests by
260-
// this client.
261-
func (p *requestClientContentConfigProvider) GetClientContentConfig() ClientContentConfig {
261+
// this client and true if the request ContentType was selected by default.
262+
func (p *requestClientContentConfigProvider) GetClientContentConfig() (ClientContentConfig, bool) {
263+
config := p.base
264+
265+
defaulted := config.ContentType == ""
266+
if defaulted {
267+
config.ContentType = "application/json"
268+
}
269+
262270
if !clientfeatures.FeatureGates().Enabled(clientfeatures.ClientsAllowCBOR) {
263-
return p.base
271+
return config, defaulted
272+
}
273+
274+
if defaulted && clientfeatures.FeatureGates().Enabled(clientfeatures.ClientsPreferCBOR) {
275+
config.ContentType = "application/cbor"
264276
}
265277

266278
if sawUnsupportedMediaTypeForCBOR := p.sawUnsupportedMediaTypeForCBOR.Load(); !sawUnsupportedMediaTypeForCBOR {
267-
return p.base
279+
return config, defaulted
268280
}
269281

270-
if mediaType, _, _ := mime.ParseMediaType(p.base.ContentType); mediaType != runtime.ContentTypeCBOR {
271-
return p.base
282+
if mediaType, _, _ := mime.ParseMediaType(config.ContentType); mediaType != runtime.ContentTypeCBOR {
283+
return config, defaulted
272284
}
273285

274-
config := p.base
275-
// The default ClientContentConfig sets ContentType to CBOR and the client has previously
276-
// received an HTTP 415 in response to a CBOR request. Override ContentType to JSON.
286+
// The effective ContentType is CBOR and the client has previously received an HTTP 415 in
287+
// response to a CBOR request. Override ContentType to JSON.
277288
config.ContentType = runtime.ContentTypeJSON
278-
return config
289+
return config, defaulted
279290
}
280291

281292
// UnsupportedMediaType reports that the server has responded to a request with HTTP 415 Unsupported

rest/request.go

+5-9
Original file line numberDiff line numberDiff line change
@@ -156,14 +156,10 @@ func NewRequest(c *RESTClient) *Request {
156156
timeout = c.Client.Timeout
157157
}
158158

159-
contentConfig := c.content.GetClientContentConfig()
160-
contentTypeNotSet := len(contentConfig.ContentType) == 0
161-
if contentTypeNotSet {
162-
contentConfig.ContentType = "application/json"
163-
if clientfeatures.FeatureGates().Enabled(clientfeatures.ClientsAllowCBOR) && clientfeatures.FeatureGates().Enabled(clientfeatures.ClientsPreferCBOR) {
164-
contentConfig.ContentType = "application/cbor"
165-
}
166-
}
159+
// A request needs to know whether the content type was explicitly configured or selected by
160+
// default in order to support the per-request Protobuf override used by clients generated
161+
// with --prefers-protobuf.
162+
contentConfig, contentTypeDefaulted := c.content.GetClientContentConfig()
167163

168164
r := &Request{
169165
c: c,
@@ -176,7 +172,7 @@ func NewRequest(c *RESTClient) *Request {
176172
warningHandler: c.warningHandler,
177173

178174
contentConfig: contentConfig,
179-
contentTypeNotSet: contentTypeNotSet,
175+
contentTypeNotSet: contentTypeDefaulted,
180176
}
181177

182178
r.setAcceptHeader()

0 commit comments

Comments
 (0)