From 541a318d10109791c0bcf6446b68cc0b130fe9bd Mon Sep 17 00:00:00 2001 From: Joel Hendrix Date: Thu, 24 Oct 2024 13:27:57 -0700 Subject: [PATCH 1/2] Conditionally set Content-Type header When the body param is optional, the Content-Type header should be set IFF the body param is not nil. Don't expose optional Content-Type literal params as flags. --- packages/codegen.go/src/operations.ts | 33 ++++++++++++++----- packages/typespec-go/CHANGELOG.md | 1 + .../typespec-go/src/tcgcadapter/clients.ts | 10 +++++- .../fake/zz_azurelargeinstance_server.go | 4 +-- .../test/armlargeinstance/fake/zz_internal.go | 16 --------- .../zz_azurelargeinstance_client.go | 4 +-- .../test/armlargeinstance/zz_options.go | 3 -- .../zz_basicimplicitbody_client.go | 2 +- ..._bodyoptionalityoptionalexplicit_server.go | 12 +++---- .../bodyoptionalgroup/fake/zz_internal.go | 16 --------- .../zz_bodyoptionality_client.go | 2 +- ..._bodyoptionalityoptionalexplicit_client.go | 8 ++--- .../bodyoptionalgroup/zz_options.go | 6 ---- .../spreadgroup/zz_spreadalias_client.go | 10 +++--- .../spreadgroup/zz_spreadmodel_client.go | 6 ++-- .../zz_jsonmergepatch_client.go | 2 +- .../zz_mediatypestringbody_client.go | 2 +- .../zz_dictionarydatetimevalue_client.go | 2 +- 18 files changed, 55 insertions(+), 84 deletions(-) diff --git a/packages/codegen.go/src/operations.ts b/packages/codegen.go/src/operations.ts index 1c0abd244..a8bb93f98 100644 --- a/packages/codegen.go/src/operations.ts +++ b/packages/codegen.go/src/operations.ts @@ -736,12 +736,21 @@ function createProtocolRequest(azureARM: boolean, client: go.Client, method: go. headerParams.push(param); } } + + let contentType: string | undefined; for (const param of headerParams.sort((a: go.HeaderParameter, b: go.HeaderParameter) => { return helpers.sortAscending(a.headerName, b.headerName);})) { if (param.headerName.match(/^content-type$/)) { // canonicalize content-type as req.SetBody checks for it via its canonicalized name :( param.headerName = 'Content-Type'; } - if (go.isRequiredParameter(param) || go.isLiteralParameter(param) || go.isClientSideDefault(param.kind)) { + + if (param.headerName === 'Content-Type' && param.kind === 'literal') { + // the content-type header will be set as part of emitSetBodyWithErrCheck + // to handle cases where the body param is optional. we don't want to set + // the content-type if the body is nil. + // we do it like this as tsp specifies content-type while swagger does not. + contentType = helpers.formatParamValue(param, imports); + } else if (go.isRequiredParameter(param) || go.isLiteralParameter(param) || go.isClientSideDefault(param.kind)) { text += emitHeaderSet(param, '\t'); } else if (param.location === 'client' && !param.group) { // global optional param @@ -757,8 +766,12 @@ function createProtocolRequest(azureARM: boolean, client: go.Client, method: go. const partialBodyParams = values(method.parameters).where((param: go.Parameter) => { return go.isPartialBodyParameter(param); }).toArray(); const bodyParam = values(method.parameters).where((each: go.Parameter) => { return go.isBodyParameter(each) || go.isFormBodyParameter(each) || go.isMultipartFormBodyParameter(each); }).first(); - const emitSetBodyWithErrCheck = function(setBodyParam: string): string { - return `if err := ${setBodyParam}; err != nil {\n\treturn nil, err\n}\n`; + const emitSetBodyWithErrCheck = function(setBodyParam: string, contentType?: string): string { + let content = `if err := ${setBodyParam}; err != nil {\n\treturn nil, err\n}\n;`; + if (contentType) { + content = `req.Raw().Header["Content-Type"] = []string{${contentType}}\n` + content; + } + return content; }; if (partialBodyParams.length > 0) { @@ -783,6 +796,8 @@ function createProtocolRequest(azureARM: boolean, client: go.Client, method: go. text += `\t\tbody.${capitalize(partialBodyParam.serializedName)} = options.${capitalize(partialBodyParam.name)}\n\t}\n`; } } + // TODO: spread params are JSON only https://github.com/Azure/autorest.go/issues/1455 + text += '\treq.Raw().Header["Content-Type"] = []string{"application/json"}\n'; text += '\tif err := runtime.MarshalAsJSON(req, body); err != nil {\n\t\treturn nil, err\n\t}\n'; text += '\treturn req, nil\n'; } else if (!bodyParam) { @@ -844,22 +859,22 @@ function createProtocolRequest(azureARM: boolean, client: go.Client, method: go. setBody = `req.SetBody(streaming.NopCloser(bytes.NewReader(${body})), "application/${bodyParam.bodyFormat.toLowerCase()}")`; } if (go.isRequiredParameter(bodyParam) || go.isLiteralParameter(bodyParam)) { - text += `\t${emitSetBodyWithErrCheck(setBody)}`; + text += `\t${emitSetBodyWithErrCheck(setBody, contentType)}`; text += '\treturn req, nil\n'; } else { text += emitParamGroupCheck(bodyParam); - text += `\t${emitSetBodyWithErrCheck(setBody)}`; + text += `\t${emitSetBodyWithErrCheck(setBody, contentType)}`; text += '\t\treturn req, nil\n'; text += '\t}\n'; text += '\treturn req, nil\n'; } } else if (bodyParam.bodyFormat === 'binary') { if (go.isRequiredParameter(bodyParam)) { - text += `\t${emitSetBodyWithErrCheck(`req.SetBody(${bodyParam.name}, ${bodyParam.contentType})`)}`; + text += `\t${emitSetBodyWithErrCheck(`req.SetBody(${bodyParam.name}, ${bodyParam.contentType})`, contentType)}`; text += '\treturn req, nil\n'; } else { text += emitParamGroupCheck(bodyParam); - text += `\t${emitSetBodyWithErrCheck(`req.SetBody(${helpers.getParamName(bodyParam)}, ${bodyParam.contentType})`)}`; + text += `\t${emitSetBodyWithErrCheck(`req.SetBody(${helpers.getParamName(bodyParam)}, ${bodyParam.contentType})`, contentType)}`; text += '\treturn req, nil\n'; text += '\t}\n'; text += '\treturn req, nil\n'; @@ -870,12 +885,12 @@ function createProtocolRequest(azureARM: boolean, client: go.Client, method: go. const bodyParam = values(method.parameters).where((each: go.Parameter) => { return go.isBodyParameter(each); }).first(); if (go.isRequiredParameter(bodyParam)) { text += `\tbody := streaming.NopCloser(strings.NewReader(${bodyParam.name}))\n`; - text += `\t${emitSetBodyWithErrCheck(`req.SetBody(body, ${bodyParam.contentType})`)}`; + text += `\t${emitSetBodyWithErrCheck(`req.SetBody(body, ${bodyParam.contentType})`, contentType)}`; text += '\treturn req, nil\n'; } else { text += emitParamGroupCheck(bodyParam); text += `\tbody := streaming.NopCloser(strings.NewReader(${helpers.getParamName(bodyParam)}))\n`; - text += `\t${emitSetBodyWithErrCheck(`req.SetBody(body, ${bodyParam.contentType})`)}`; + text += `\t${emitSetBodyWithErrCheck(`req.SetBody(body, ${bodyParam.contentType})`, contentType)}`; text += '\treturn req, nil\n'; text += '\t}\n'; text += '\treturn req, nil\n'; diff --git a/packages/typespec-go/CHANGELOG.md b/packages/typespec-go/CHANGELOG.md index 6bc7efa0f..f409ae5e2 100644 --- a/packages/typespec-go/CHANGELOG.md +++ b/packages/typespec-go/CHANGELOG.md @@ -10,6 +10,7 @@ * Fake servers will honor the caller's context in the `*http.Request`. * Add missing error check when parsing multipart/form content in fakes. +* Optional body params will only set the `Content-Type` header when a body is specified. ### Other Fixes diff --git a/packages/typespec-go/src/tcgcadapter/clients.ts b/packages/typespec-go/src/tcgcadapter/clients.ts index d9ed573f2..d7b4ee47a 100644 --- a/packages/typespec-go/src/tcgcadapter/clients.ts +++ b/packages/typespec-go/src/tcgcadapter/clients.ts @@ -324,6 +324,15 @@ export class clientAdapter { throw new Error(`didn't find operation parameter for method ${sdkMethod.name} parameter ${param.name}`); } + if (opParam.kind === 'header' && opParam.serializedName.match(/^content-type$/i) && param.type.kind === 'constant') { + // if the body param is optional, then the content-type param is also optional. + // for optional constants, this has the side effect of the param being treated like + // a flag which isn't what we want. so, we mark it as required. we ONLY do this + // if the content-type is a constant (i.e. literal value). + // the content-type will be conditionally set based on the requiredness of the body. + opParam.optional = false; + } + let adaptedParam: go.Parameter; if (opParam.kind === 'body' && opParam.type.kind === 'model' && opParam.type.kind !== param.type.kind) { const paramKind = this.adaptParameterKind(param); @@ -687,7 +696,6 @@ export class clientAdapter { private adaptParameterKind(param: tcgc.SdkBodyParameter | tcgc.SdkEndpointParameter | tcgc.SdkHeaderParameter | tcgc.SdkMethodParameter | tcgc.SdkPathParameter | tcgc.SdkQueryParameter): go.ParameterKind { // NOTE: must check for constant type first as it will also set clientDefaultValue if (param.type.kind === 'constant') { - // TODO: https://github.com/Azure/autorest.go/issues/1444 if (param.optional) { return 'flag'; } diff --git a/packages/typespec-go/test/armlargeinstance/fake/zz_azurelargeinstance_server.go b/packages/typespec-go/test/armlargeinstance/fake/zz_azurelargeinstance_server.go index aa937a2b2..b633c7343 100644 --- a/packages/typespec-go/test/armlargeinstance/fake/zz_azurelargeinstance_server.go +++ b/packages/typespec-go/test/armlargeinstance/fake/zz_azurelargeinstance_server.go @@ -334,12 +334,10 @@ func (a *AzureLargeInstanceServerTransport) dispatchBeginRestart(req *http.Reque if err != nil { return nil, err } - contentTypeParam := getOptional(getHeaderValue(req.Header, "Content-Type")) var options *armlargeinstance.AzureLargeInstanceClientBeginRestartOptions - if !reflect.ValueOf(body).IsZero() || contentTypeParam != nil { + if !reflect.ValueOf(body).IsZero() { options = &armlargeinstance.AzureLargeInstanceClientBeginRestartOptions{ ForceParameter: &body, - ContentType: contentTypeParam, } } respr, errRespr := a.srv.BeginRestart(req.Context(), resourceGroupNameParam, azureLargeInstanceNameParam, options) diff --git a/packages/typespec-go/test/armlargeinstance/fake/zz_internal.go b/packages/typespec-go/test/armlargeinstance/fake/zz_internal.go index 9989d5e3c..7425b6a66 100644 --- a/packages/typespec-go/test/armlargeinstance/fake/zz_internal.go +++ b/packages/typespec-go/test/armlargeinstance/fake/zz_internal.go @@ -7,7 +7,6 @@ package fake import ( "github.com/Azure/azure-sdk-for-go/sdk/azcore/fake/server" "net/http" - "reflect" "sync" ) @@ -33,21 +32,6 @@ func contains[T comparable](s []T, v T) bool { return false } -func getHeaderValue(h http.Header, k string) string { - v := h[k] - if len(v) == 0 { - return "" - } - return v[0] -} - -func getOptional[T any](v T) *T { - if reflect.ValueOf(v).IsZero() { - return nil - } - return &v -} - func newTracker[T any]() *tracker[T] { return &tracker[T]{ items: map[string]*T{}, diff --git a/packages/typespec-go/test/armlargeinstance/zz_azurelargeinstance_client.go b/packages/typespec-go/test/armlargeinstance/zz_azurelargeinstance_client.go index d7a55b514..dd4e5055e 100644 --- a/packages/typespec-go/test/armlargeinstance/zz_azurelargeinstance_client.go +++ b/packages/typespec-go/test/armlargeinstance/zz_azurelargeinstance_client.go @@ -421,10 +421,8 @@ func (client *AzureLargeInstanceClient) restartCreateRequest(ctx context.Context reqQP.Set("api-version", "2024-08-01-preview") req.Raw().URL.RawQuery = reqQP.Encode() req.Raw().Header["Accept"] = []string{"application/json"} - if options != nil && options.ContentType != nil { - req.Raw().Header["Content-Type"] = []string{"application/json"} - } if options != nil && options.ForceParameter != nil { + req.Raw().Header["Content-Type"] = []string{"application/json"} if err := runtime.MarshalAsJSON(req, *options.ForceParameter); err != nil { return nil, err } diff --git a/packages/typespec-go/test/armlargeinstance/zz_options.go b/packages/typespec-go/test/armlargeinstance/zz_options.go index 4b7f75777..d46dea146 100644 --- a/packages/typespec-go/test/armlargeinstance/zz_options.go +++ b/packages/typespec-go/test/armlargeinstance/zz_options.go @@ -10,9 +10,6 @@ type AzureLargeInstanceClientBeginRestartOptions struct { // Resumes the long-running operation from the provided token. ResumeToken string - // Body parameter's content type. Known values are application/json - ContentType *string - // When set to 'active', this parameter empowers the server with the ability to forcefully terminate and halt any existing // processes that may be running on the server ForceParameter *ForceState diff --git a/packages/typespec-go/test/cadlranch/parameters/basicparamsgroup/zz_basicimplicitbody_client.go b/packages/typespec-go/test/cadlranch/parameters/basicparamsgroup/zz_basicimplicitbody_client.go index ca0e15328..0da1b929f 100644 --- a/packages/typespec-go/test/cadlranch/parameters/basicparamsgroup/zz_basicimplicitbody_client.go +++ b/packages/typespec-go/test/cadlranch/parameters/basicparamsgroup/zz_basicimplicitbody_client.go @@ -50,12 +50,12 @@ func (client *BasicImplicitBodyClient) simpleCreateRequest(ctx context.Context, if err != nil { return nil, err } - req.Raw().Header["Content-Type"] = []string{"application/json"} body := struct { Name string `json:"name"` }{ Name: name, } + req.Raw().Header["Content-Type"] = []string{"application/json"} if err := runtime.MarshalAsJSON(req, body); err != nil { return nil, err } diff --git a/packages/typespec-go/test/cadlranch/parameters/bodyoptionalgroup/fake/zz_bodyoptionalityoptionalexplicit_server.go b/packages/typespec-go/test/cadlranch/parameters/bodyoptionalgroup/fake/zz_bodyoptionalityoptionalexplicit_server.go index 0387c600a..24e89b3e8 100644 --- a/packages/typespec-go/test/cadlranch/parameters/bodyoptionalgroup/fake/zz_bodyoptionalityoptionalexplicit_server.go +++ b/packages/typespec-go/test/cadlranch/parameters/bodyoptionalgroup/fake/zz_bodyoptionalityoptionalexplicit_server.go @@ -88,12 +88,10 @@ func (b *BodyOptionalityOptionalExplicitServerTransport) dispatchOmit(req *http. if err != nil { return nil, err } - contentTypeParam := getOptional(getHeaderValue(req.Header, "Content-Type")) var options *bodyoptionalgroup.BodyOptionalityOptionalExplicitClientOmitOptions - if !reflect.ValueOf(body).IsZero() || contentTypeParam != nil { + if !reflect.ValueOf(body).IsZero() { options = &bodyoptionalgroup.BodyOptionalityOptionalExplicitClientOmitOptions{ - Body: &body, - ContentType: contentTypeParam, + Body: &body, } } respr, errRespr := b.srv.Omit(req.Context(), options) @@ -119,12 +117,10 @@ func (b *BodyOptionalityOptionalExplicitServerTransport) dispatchSet(req *http.R if err != nil { return nil, err } - contentTypeParam := getOptional(getHeaderValue(req.Header, "Content-Type")) var options *bodyoptionalgroup.BodyOptionalityOptionalExplicitClientSetOptions - if !reflect.ValueOf(body).IsZero() || contentTypeParam != nil { + if !reflect.ValueOf(body).IsZero() { options = &bodyoptionalgroup.BodyOptionalityOptionalExplicitClientSetOptions{ - Body: &body, - ContentType: contentTypeParam, + Body: &body, } } respr, errRespr := b.srv.Set(req.Context(), options) diff --git a/packages/typespec-go/test/cadlranch/parameters/bodyoptionalgroup/fake/zz_internal.go b/packages/typespec-go/test/cadlranch/parameters/bodyoptionalgroup/fake/zz_internal.go index b90cb5adf..edd9ca564 100644 --- a/packages/typespec-go/test/cadlranch/parameters/bodyoptionalgroup/fake/zz_internal.go +++ b/packages/typespec-go/test/cadlranch/parameters/bodyoptionalgroup/fake/zz_internal.go @@ -6,7 +6,6 @@ package fake import ( "net/http" - "reflect" "sync" ) @@ -32,21 +31,6 @@ func contains[T comparable](s []T, v T) bool { return false } -func getHeaderValue(h http.Header, k string) string { - v := h[k] - if len(v) == 0 { - return "" - } - return v[0] -} - -func getOptional[T any](v T) *T { - if reflect.ValueOf(v).IsZero() { - return nil - } - return &v -} - func initServer[T any](mu *sync.Mutex, dst **T, src func() *T) { mu.Lock() if *dst == nil { diff --git a/packages/typespec-go/test/cadlranch/parameters/bodyoptionalgroup/zz_bodyoptionality_client.go b/packages/typespec-go/test/cadlranch/parameters/bodyoptionalgroup/zz_bodyoptionality_client.go index a5765ded0..5d5b63bc2 100644 --- a/packages/typespec-go/test/cadlranch/parameters/bodyoptionalgroup/zz_bodyoptionality_client.go +++ b/packages/typespec-go/test/cadlranch/parameters/bodyoptionalgroup/zz_bodyoptionality_client.go @@ -96,12 +96,12 @@ func (client *BodyOptionalityClient) requiredImplicitCreateRequest(ctx context.C if err != nil { return nil, err } - req.Raw().Header["Content-Type"] = []string{"application/json"} body := struct { Name string `json:"name"` }{ Name: name, } + req.Raw().Header["Content-Type"] = []string{"application/json"} if err := runtime.MarshalAsJSON(req, body); err != nil { return nil, err } diff --git a/packages/typespec-go/test/cadlranch/parameters/bodyoptionalgroup/zz_bodyoptionalityoptionalexplicit_client.go b/packages/typespec-go/test/cadlranch/parameters/bodyoptionalgroup/zz_bodyoptionalityoptionalexplicit_client.go index 80fa774e5..4b4b31951 100644 --- a/packages/typespec-go/test/cadlranch/parameters/bodyoptionalgroup/zz_bodyoptionalityoptionalexplicit_client.go +++ b/packages/typespec-go/test/cadlranch/parameters/bodyoptionalgroup/zz_bodyoptionalityoptionalexplicit_client.go @@ -50,10 +50,8 @@ func (client *BodyOptionalityOptionalExplicitClient) omitCreateRequest(ctx conte if err != nil { return nil, err } - if options != nil && options.ContentType != nil { - req.Raw().Header["Content-Type"] = []string{"application/json"} - } if options != nil && options.Body != nil { + req.Raw().Header["Content-Type"] = []string{"application/json"} if err := runtime.MarshalAsJSON(req, *options.Body); err != nil { return nil, err } @@ -94,10 +92,8 @@ func (client *BodyOptionalityOptionalExplicitClient) setCreateRequest(ctx contex if err != nil { return nil, err } - if options != nil && options.ContentType != nil { - req.Raw().Header["Content-Type"] = []string{"application/json"} - } if options != nil && options.Body != nil { + req.Raw().Header["Content-Type"] = []string{"application/json"} if err := runtime.MarshalAsJSON(req, *options.Body); err != nil { return nil, err } diff --git a/packages/typespec-go/test/cadlranch/parameters/bodyoptionalgroup/zz_options.go b/packages/typespec-go/test/cadlranch/parameters/bodyoptionalgroup/zz_options.go index eb634abed..19e1fef07 100644 --- a/packages/typespec-go/test/cadlranch/parameters/bodyoptionalgroup/zz_options.go +++ b/packages/typespec-go/test/cadlranch/parameters/bodyoptionalgroup/zz_options.go @@ -20,16 +20,10 @@ type BodyOptionalityClientRequiredImplicitOptions struct { // method. type BodyOptionalityOptionalExplicitClientOmitOptions struct { Body *BodyModel - - // Body parameter's content type. Known values are application/json - ContentType *string } // BodyOptionalityOptionalExplicitClientSetOptions contains the optional parameters for the BodyOptionalityOptionalExplicitClient.Set // method. type BodyOptionalityOptionalExplicitClientSetOptions struct { Body *BodyModel - - // Body parameter's content type. Known values are application/json - ContentType *string } diff --git a/packages/typespec-go/test/cadlranch/parameters/spreadgroup/zz_spreadalias_client.go b/packages/typespec-go/test/cadlranch/parameters/spreadgroup/zz_spreadalias_client.go index 720056831..1c53ced84 100644 --- a/packages/typespec-go/test/cadlranch/parameters/spreadgroup/zz_spreadalias_client.go +++ b/packages/typespec-go/test/cadlranch/parameters/spreadgroup/zz_spreadalias_client.go @@ -53,12 +53,12 @@ func (client *SpreadAliasClient) spreadAsRequestBodyCreateRequest(ctx context.Co if err != nil { return nil, err } - req.Raw().Header["Content-Type"] = []string{"application/json"} body := struct { Name string `json:"name"` }{ Name: name, } + req.Raw().Header["Content-Type"] = []string{"application/json"} if err := runtime.MarshalAsJSON(req, body); err != nil { return nil, err } @@ -101,13 +101,13 @@ func (client *SpreadAliasClient) spreadAsRequestParameterCreateRequest(ctx conte if err != nil { return nil, err } - req.Raw().Header["Content-Type"] = []string{"application/json"} req.Raw().Header["x-ms-test-header"] = []string{xMSTestHeader} body := struct { Name string `json:"name"` }{ Name: name, } + req.Raw().Header["Content-Type"] = []string{"application/json"} if err := runtime.MarshalAsJSON(req, body); err != nil { return nil, err } @@ -152,7 +152,6 @@ func (client *SpreadAliasClient) spreadParameterWithInnerAliasCreateRequest(ctx if err != nil { return nil, err } - req.Raw().Header["Content-Type"] = []string{"application/json"} req.Raw().Header["x-ms-test-header"] = []string{xMSTestHeader} body := struct { Name string `json:"name"` @@ -161,6 +160,7 @@ func (client *SpreadAliasClient) spreadParameterWithInnerAliasCreateRequest(ctx Name: name, Age: age, } + req.Raw().Header["Content-Type"] = []string{"application/json"} if err := runtime.MarshalAsJSON(req, body); err != nil { return nil, err } @@ -203,13 +203,13 @@ func (client *SpreadAliasClient) spreadParameterWithInnerModelCreateRequest(ctx if err != nil { return nil, err } - req.Raw().Header["Content-Type"] = []string{"application/json"} req.Raw().Header["x-ms-test-header"] = []string{xMSTestHeader} body := struct { Name string `json:"name"` }{ Name: name, } + req.Raw().Header["Content-Type"] = []string{"application/json"} if err := runtime.MarshalAsJSON(req, body); err != nil { return nil, err } @@ -254,7 +254,6 @@ func (client *SpreadAliasClient) spreadWithMultipleParametersCreateRequest(ctx c if err != nil { return nil, err } - req.Raw().Header["Content-Type"] = []string{"application/json"} req.Raw().Header["x-ms-test-header"] = []string{xMSTestHeader} body := struct { RequiredString string `json:"requiredString"` @@ -271,6 +270,7 @@ func (client *SpreadAliasClient) spreadWithMultipleParametersCreateRequest(ctx c if options != nil && options.OptionalStringList != nil { body.OptionalStringList = options.OptionalStringList } + req.Raw().Header["Content-Type"] = []string{"application/json"} if err := runtime.MarshalAsJSON(req, body); err != nil { return nil, err } diff --git a/packages/typespec-go/test/cadlranch/parameters/spreadgroup/zz_spreadmodel_client.go b/packages/typespec-go/test/cadlranch/parameters/spreadgroup/zz_spreadmodel_client.go index 5b584c3f9..1c9fea657 100644 --- a/packages/typespec-go/test/cadlranch/parameters/spreadgroup/zz_spreadmodel_client.go +++ b/packages/typespec-go/test/cadlranch/parameters/spreadgroup/zz_spreadmodel_client.go @@ -53,12 +53,12 @@ func (client *SpreadModelClient) spreadAsRequestBodyCreateRequest(ctx context.Co if err != nil { return nil, err } - req.Raw().Header["Content-Type"] = []string{"application/json"} body := struct { Name string `json:"name"` }{ Name: name, } + req.Raw().Header["Content-Type"] = []string{"application/json"} if err := runtime.MarshalAsJSON(req, body); err != nil { return nil, err } @@ -101,8 +101,8 @@ func (client *SpreadModelClient) spreadCompositeRequestCreateRequest(ctx context if err != nil { return nil, err } - req.Raw().Header["Content-Type"] = []string{"application/json"} req.Raw().Header["test-header"] = []string{testHeader} + req.Raw().Header["Content-Type"] = []string{"application/json"} if err := runtime.MarshalAsJSON(req, body); err != nil { return nil, err } @@ -145,13 +145,13 @@ func (client *SpreadModelClient) spreadCompositeRequestMixCreateRequest(ctx cont if err != nil { return nil, err } - req.Raw().Header["Content-Type"] = []string{"application/json"} req.Raw().Header["test-header"] = []string{testHeader} body := struct { Prop string `json:"prop"` }{ Prop: prop, } + req.Raw().Header["Content-Type"] = []string{"application/json"} if err := runtime.MarshalAsJSON(req, body); err != nil { return nil, err } diff --git a/packages/typespec-go/test/cadlranch/payload/jmergepatchgroup/zz_jsonmergepatch_client.go b/packages/typespec-go/test/cadlranch/payload/jmergepatchgroup/zz_jsonmergepatch_client.go index 61c53d788..1106a7a36 100644 --- a/packages/typespec-go/test/cadlranch/payload/jmergepatchgroup/zz_jsonmergepatch_client.go +++ b/packages/typespec-go/test/cadlranch/payload/jmergepatchgroup/zz_jsonmergepatch_client.go @@ -102,8 +102,8 @@ func (client *JSONMergePatchClient) updateOptionalResourceCreateRequest(ctx cont return nil, err } req.Raw().Header["Accept"] = []string{"application/json"} - req.Raw().Header["Content-Type"] = []string{"application/merge-patch+json"} if options != nil && options.Body != nil { + req.Raw().Header["Content-Type"] = []string{"application/merge-patch+json"} if err := runtime.MarshalAsJSON(req, *options.Body); err != nil { return nil, err } diff --git a/packages/typespec-go/test/cadlranch/payload/mediatypegroup/zz_mediatypestringbody_client.go b/packages/typespec-go/test/cadlranch/payload/mediatypegroup/zz_mediatypestringbody_client.go index 8c27e97d5..dc053eaa7 100644 --- a/packages/typespec-go/test/cadlranch/payload/mediatypegroup/zz_mediatypestringbody_client.go +++ b/packages/typespec-go/test/cadlranch/payload/mediatypegroup/zz_mediatypestringbody_client.go @@ -192,8 +192,8 @@ func (client *MediaTypeStringBodyClient) sendAsTextCreateRequest(ctx context.Con if err != nil { return nil, err } - req.Raw().Header["Content-Type"] = []string{"text/plain"} body := streaming.NopCloser(strings.NewReader(textParam)) + req.Raw().Header["Content-Type"] = []string{"text/plain"} if err := req.SetBody(body, "text/plain"); err != nil { return nil, err } diff --git a/packages/typespec-go/test/cadlranch/type/dictionarygroup/zz_dictionarydatetimevalue_client.go b/packages/typespec-go/test/cadlranch/type/dictionarygroup/zz_dictionarydatetimevalue_client.go index 016c9af3a..e9b762d82 100644 --- a/packages/typespec-go/test/cadlranch/type/dictionarygroup/zz_dictionarydatetimevalue_client.go +++ b/packages/typespec-go/test/cadlranch/type/dictionarygroup/zz_dictionarydatetimevalue_client.go @@ -103,11 +103,11 @@ func (client *DictionaryDatetimeValueClient) putCreateRequest(ctx context.Contex if err != nil { return nil, err } - req.Raw().Header["Content-Type"] = []string{"application/json"} aux := map[string]*dateTimeRFC3339{} for k, v := range body { aux[k] = (*dateTimeRFC3339)(v) } + req.Raw().Header["Content-Type"] = []string{"application/json"} if err := runtime.MarshalAsJSON(req, aux); err != nil { return nil, err } From eba1e857a156f8d329ea5737fc31ece40af3a624 Mon Sep 17 00:00:00 2001 From: Joel Hendrix Date: Tue, 29 Oct 2024 10:10:37 -0700 Subject: [PATCH 2/2] refine changelog --- packages/typespec-go/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/typespec-go/CHANGELOG.md b/packages/typespec-go/CHANGELOG.md index f409ae5e2..b0624d3c7 100644 --- a/packages/typespec-go/CHANGELOG.md +++ b/packages/typespec-go/CHANGELOG.md @@ -10,7 +10,7 @@ * Fake servers will honor the caller's context in the `*http.Request`. * Add missing error check when parsing multipart/form content in fakes. -* Optional body params will only set the `Content-Type` header when a body is specified. +* Optional request bodies will only set the `Content-Type` header when a body is specified. ### Other Fixes