diff --git a/CHANGELOG.md b/CHANGELOG.md index 82f797bd6f..5b6ee54c0f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Deduplicates 4XX and 5XX error mappings when they map to the same type to reduce emitted code. [#4025](https://github.com/microsoft/kiota/issues/4025) - 📢📢📢 Java generation is now stable! 🚀🚀🚀 special thanks to @andreaTP (Red Hat) for all the help. - Fixed bug where stream responses would generate incorrect partial paging code. [#4207](https://github.com/microsoft/kiota/issues/4207) +- Sanitize Accept and Content-Type headers during generation. [#4211](https://github.com/microsoft/kiota/issues/4211) ## [1.11.1] - 2024-02-05 diff --git a/src/Kiota.Builder/Writers/CLI/CliCodeMethodWriter.cs b/src/Kiota.Builder/Writers/CLI/CliCodeMethodWriter.cs index 9d7c94edca..b651471c26 100644 --- a/src/Kiota.Builder/Writers/CLI/CliCodeMethodWriter.cs +++ b/src/Kiota.Builder/Writers/CLI/CliCodeMethodWriter.cs @@ -639,7 +639,7 @@ protected virtual void WriteCommandHandlerBody(CodeMethod codeElement, CodeClass if (requestBodyParamType?.TypeDefinition is CodeClass) { writer.WriteLine($"using var stream = new MemoryStream(Encoding.UTF8.GetBytes({requestBodyParam.Name}));"); - writer.WriteLine($"var parseNode = ParseNodeFactoryRegistry.DefaultInstance.GetRootParseNode(\"{generatorMethod.RequestBodyContentType}\", stream);"); + writer.WriteLine($"var parseNode = ParseNodeFactoryRegistry.DefaultInstance.GetRootParseNode(\"{generatorMethod.RequestBodyContentType.SanitizeDoubleQuote()}\", stream);"); var typeString = conventions.GetTypeString(requestBodyParamType, requestBodyParam, false); @@ -757,9 +757,10 @@ private static void WriteRequestInformation(LanguageWriter writer, CodeMethod ge // Set the content type header. Will not add the code if the method is a stream, has no RequestBodyContentType or if there's no body parameter. if (!isStream && generatorMethod.Parameters.Any(p => p.IsOfKind(CodeParameterKind.RequestBody))) { - if (!string.IsNullOrWhiteSpace(generatorMethod.RequestBodyContentType)) + var sanitizedRequestBodyContentType = generatorMethod.RequestBodyContentType.SanitizeDoubleQuote(); + if (!string.IsNullOrWhiteSpace(sanitizedRequestBodyContentType)) { - writer.WriteLine($"requestInfo.SetContentFromParsable({RequestAdapterParamName}, \"{generatorMethod.RequestBodyContentType}\", model);"); + writer.WriteLine($"requestInfo.SetContentFromParsable({RequestAdapterParamName}, \"{sanitizedRequestBodyContentType}\", model);"); } else { diff --git a/src/Kiota.Builder/Writers/CSharp/CodeMethodWriter.cs b/src/Kiota.Builder/Writers/CSharp/CodeMethodWriter.cs index bdab613416..08a2e53183 100644 --- a/src/Kiota.Builder/Writers/CSharp/CodeMethodWriter.cs +++ b/src/Kiota.Builder/Writers/CSharp/CodeMethodWriter.cs @@ -418,22 +418,23 @@ private void WriteRequestGeneratorBody(CodeMethod codeElement, RequestParams req writer.WriteLine($"{RequestInfoVarName}.Configure({requestParams.requestConfiguration.Name});"); if (codeElement.ShouldAddAcceptHeader) - writer.WriteLine($"{RequestInfoVarName}.Headers.TryAdd(\"Accept\", \"{codeElement.AcceptHeaderValue}\");"); + writer.WriteLine($"{RequestInfoVarName}.Headers.TryAdd(\"Accept\", \"{codeElement.AcceptHeaderValue.SanitizeDoubleQuote()}\");"); if (requestParams.requestBody != null) { var suffix = requestParams.requestBody.Type.IsCollection ? "Collection" : string.Empty; + var sanitizedRequestBodyContentType = codeElement.RequestBodyContentType.SanitizeDoubleQuote(); if (requestParams.requestBody.Type.Name.Equals(conventions.StreamTypeName, StringComparison.OrdinalIgnoreCase)) { if (requestParams.requestContentType is not null) writer.WriteLine($"{RequestInfoVarName}.SetStreamContent({requestParams.requestBody.Name}, {requestParams.requestContentType.Name});"); - else if (!string.IsNullOrEmpty(codeElement.RequestBodyContentType)) - writer.WriteLine($"{RequestInfoVarName}.SetStreamContent({requestParams.requestBody.Name}, \"{codeElement.RequestBodyContentType}\");"); + else if (!string.IsNullOrEmpty(sanitizedRequestBodyContentType)) + writer.WriteLine($"{RequestInfoVarName}.SetStreamContent({requestParams.requestBody.Name}, \"{sanitizedRequestBodyContentType}\");"); } else if (currentClass.GetPropertyOfKind(CodePropertyKind.RequestAdapter) is CodeProperty requestAdapterProperty) if (requestParams.requestBody.Type is CodeType bodyType && (bodyType.TypeDefinition is CodeClass || bodyType.Name.Equals("MultipartBody", StringComparison.OrdinalIgnoreCase))) - writer.WriteLine($"{RequestInfoVarName}.SetContentFromParsable({requestAdapterProperty.Name.ToFirstCharacterUpperCase()}, \"{codeElement.RequestBodyContentType}\", {requestParams.requestBody.Name});"); + writer.WriteLine($"{RequestInfoVarName}.SetContentFromParsable({requestAdapterProperty.Name.ToFirstCharacterUpperCase()}, \"{sanitizedRequestBodyContentType}\", {requestParams.requestBody.Name});"); else - writer.WriteLine($"{RequestInfoVarName}.SetContentFromScalar{suffix}({requestAdapterProperty.Name.ToFirstCharacterUpperCase()}, \"{codeElement.RequestBodyContentType}\", {requestParams.requestBody.Name});"); + writer.WriteLine($"{RequestInfoVarName}.SetContentFromScalar{suffix}({requestAdapterProperty.Name.ToFirstCharacterUpperCase()}, \"{sanitizedRequestBodyContentType}\", {requestParams.requestBody.Name});"); } writer.WriteLine($"return {RequestInfoVarName};"); diff --git a/src/Kiota.Builder/Writers/Go/CodeMethodWriter.cs b/src/Kiota.Builder/Writers/Go/CodeMethodWriter.cs index cb7889c03f..41b1456864 100644 --- a/src/Kiota.Builder/Writers/Go/CodeMethodWriter.cs +++ b/src/Kiota.Builder/Writers/Go/CodeMethodWriter.cs @@ -882,17 +882,18 @@ private void WriteRequestGeneratorBody(CodeMethod codeElement, RequestParams req WriteLegacyRequestConfiguration(requestParams, writer); if (codeElement.ShouldAddAcceptHeader) - writer.WriteLine($"{RequestInfoVarName}.Headers.TryAdd(\"Accept\", \"{codeElement.AcceptHeaderValue}\")"); + writer.WriteLine($"{RequestInfoVarName}.Headers.TryAdd(\"Accept\", \"{codeElement.AcceptHeaderValue.SanitizeDoubleQuote()}\")"); if (requestParams.requestBody != null) { var bodyParamReference = $"{requestParams.requestBody.Name.ToFirstCharacterLowerCase()}"; var collectionSuffix = requestParams.requestBody.Type.IsCollection ? "Collection" : string.Empty; + var sanitizedRequestBodyContentType = codeElement.RequestBodyContentType.SanitizeDoubleQuote(); if (requestParams.requestBody.Type.Name.Equals("binary", StringComparison.OrdinalIgnoreCase) || requestParams.requestBody.Type.Name.Equals(conventions.StreamTypeName, StringComparison.OrdinalIgnoreCase)) { if (requestParams.requestContentType is not null) writer.WriteLine($"{RequestInfoVarName}.SetStreamContentAndContentType({bodyParamReference}, *{requestParams.requestContentType.Name.ToFirstCharacterLowerCase()})"); - else if (!string.IsNullOrEmpty(codeElement.RequestBodyContentType)) - writer.WriteLine($"{RequestInfoVarName}.SetStreamContentAndContentType({bodyParamReference}, \"{codeElement.RequestBodyContentType}\")"); + else if (!string.IsNullOrEmpty(sanitizedRequestBodyContentType)) + writer.WriteLine($"{RequestInfoVarName}.SetStreamContentAndContentType({bodyParamReference}, \"{sanitizedRequestBodyContentType}\")"); } else if (requestParams.requestBody.Type is CodeType bodyType && (bodyType.TypeDefinition is CodeClass || bodyType.TypeDefinition is CodeInterface || bodyType.Name.Equals("MultipartBody", StringComparison.OrdinalIgnoreCase))) { @@ -902,11 +903,11 @@ private void WriteRequestGeneratorBody(CodeMethod codeElement, RequestParams req WriteCollectionCast(parsableSymbol, bodyParamReference, "cast", writer, string.Empty, false); bodyParamReference = "cast"; } - writer.WriteLine($"err := {RequestInfoVarName}.SetContentFromParsable{collectionSuffix}({contextParameterName}, m.{requestAdapterPropertyName}, \"{codeElement.RequestBodyContentType}\", {bodyParamReference})"); + writer.WriteLine($"err := {RequestInfoVarName}.SetContentFromParsable{collectionSuffix}({contextParameterName}, m.{requestAdapterPropertyName}, \"{sanitizedRequestBodyContentType}\", {bodyParamReference})"); writer.WriteBlock("if err != nil {", "}", "return nil, err"); } else - writer.WriteLine($"{RequestInfoVarName}.SetContentFromScalar{collectionSuffix}({contextParameterName}, m.{requestAdapterPropertyName}, \"{codeElement.RequestBodyContentType}\", {bodyParamReference})"); + writer.WriteLine($"{RequestInfoVarName}.SetContentFromScalar{collectionSuffix}({contextParameterName}, m.{requestAdapterPropertyName}, \"{sanitizedRequestBodyContentType}\", {bodyParamReference})"); } writer.WriteLine($"return {RequestInfoVarName}, nil"); diff --git a/src/Kiota.Builder/Writers/Java/CodeMethodWriter.cs b/src/Kiota.Builder/Writers/Java/CodeMethodWriter.cs index ab24292b6d..8bf41ca027 100644 --- a/src/Kiota.Builder/Writers/Java/CodeMethodWriter.cs +++ b/src/Kiota.Builder/Writers/Java/CodeMethodWriter.cs @@ -585,24 +585,25 @@ private void WriteRequestGeneratorBody(CodeMethod codeElement, RequestParams req } if (codeElement.ShouldAddAcceptHeader) - writer.WriteLine($"{RequestInfoVarName}.headers.tryAdd(\"Accept\", \"{codeElement.AcceptHeaderValue}\");"); + writer.WriteLine($"{RequestInfoVarName}.headers.tryAdd(\"Accept\", \"{codeElement.AcceptHeaderValue.SanitizeDoubleQuote()}\");"); if (requestParams.requestBody != null && currentClass.GetPropertyOfKind(CodePropertyKind.RequestAdapter) is CodeProperty requestAdapterProperty) { var toArrayPostfix = requestParams.requestBody.Type.IsCollection ? $".toArray(new {requestParams.requestBody.Type.Name}[0])" : string.Empty; var collectionPostfix = requestParams.requestBody.Type.IsCollection ? "Collection" : string.Empty; + var sanitizedRequestBodyContentType = codeElement.RequestBodyContentType.SanitizeDoubleQuote(); if (requestParams.requestBody.Type.Name.Equals(conventions.StreamTypeName, StringComparison.OrdinalIgnoreCase)) { if (requestParams.requestContentType is not null) writer.WriteLine($"{RequestInfoVarName}.setStreamContent({requestParams.requestBody.Name}, {requestParams.requestContentType.Name});"); else if (!string.IsNullOrEmpty(codeElement.RequestBodyContentType)) - writer.WriteLine($"{RequestInfoVarName}.setStreamContent({requestParams.requestBody.Name}, \"{codeElement.RequestBodyContentType}\");"); + writer.WriteLine($"{RequestInfoVarName}.setStreamContent({requestParams.requestBody.Name}, \"{sanitizedRequestBodyContentType}\");"); } else if (requestParams.requestBody.Type is CodeType bodyType && (bodyType.TypeDefinition is CodeClass || bodyType.Name.Equals("MultipartBody", StringComparison.OrdinalIgnoreCase))) - writer.WriteLine($"{RequestInfoVarName}.setContentFromParsable({requestAdapterProperty.Name}, \"{codeElement.RequestBodyContentType}\", {requestParams.requestBody.Name}{toArrayPostfix});"); + writer.WriteLine($"{RequestInfoVarName}.setContentFromParsable({requestAdapterProperty.Name}, \"{sanitizedRequestBodyContentType}\", {requestParams.requestBody.Name}{toArrayPostfix});"); else - writer.WriteLine($"{RequestInfoVarName}.setContentFromScalar{collectionPostfix}({requestAdapterProperty.Name}, \"{codeElement.RequestBodyContentType}\", {requestParams.requestBody.Name}{toArrayPostfix});"); + writer.WriteLine($"{RequestInfoVarName}.setContentFromScalar{collectionPostfix}({requestAdapterProperty.Name}, \"{sanitizedRequestBodyContentType}\", {requestParams.requestBody.Name}{toArrayPostfix});"); } writer.WriteLine($"return {RequestInfoVarName};"); diff --git a/src/Kiota.Builder/Writers/Php/CodeMethodWriter.cs b/src/Kiota.Builder/Writers/Php/CodeMethodWriter.cs index 3fc6397717..375f986024 100644 --- a/src/Kiota.Builder/Writers/Php/CodeMethodWriter.cs +++ b/src/Kiota.Builder/Writers/Php/CodeMethodWriter.cs @@ -568,18 +568,19 @@ private void WriteRequestGeneratorBody(CodeMethod codeElement, RequestParams req if (requestParams.requestBody != null) { var suffix = requestParams.requestBody.Type.IsCollection ? "Collection" : string.Empty; + var sanitizedRequestBodyContentType = codeElement.RequestBodyContentType.SanitizeDoubleQuote(); if (requestParams.requestBody.Type.Name.Equals(conventions.StreamTypeName, StringComparison.OrdinalIgnoreCase)) { if (requestParams.requestContentType is not null) writer.WriteLine($"{RequestInfoVarName}->setStreamContent({conventions.GetParameterName(requestParams.requestBody)}, {conventions.GetParameterName(requestParams.requestContentType)});"); else if (!string.IsNullOrEmpty(codeElement.RequestBodyContentType)) - writer.WriteLine($"{RequestInfoVarName}->setStreamContent({conventions.GetParameterName(requestParams.requestBody)}, \"{codeElement.RequestBodyContentType}\");"); + writer.WriteLine($"{RequestInfoVarName}->setStreamContent({conventions.GetParameterName(requestParams.requestBody)}, \"{sanitizedRequestBodyContentType}\");"); } else if (currentClass.GetPropertyOfKind(CodePropertyKind.RequestAdapter) is CodeProperty requestAdapterProperty) if (requestParams.requestBody.Type is CodeType bodyType && bodyType.TypeDefinition is CodeClass) - writer.WriteLine($"{RequestInfoVarName}->setContentFromParsable{suffix}($this->{requestAdapterProperty.Name.ToFirstCharacterLowerCase()}, \"{codeElement.RequestBodyContentType}\", {conventions.GetParameterName(requestParams.requestBody)});"); + writer.WriteLine($"{RequestInfoVarName}->setContentFromParsable{suffix}($this->{requestAdapterProperty.Name.ToFirstCharacterLowerCase()}, \"{sanitizedRequestBodyContentType}\", {conventions.GetParameterName(requestParams.requestBody)});"); else - writer.WriteLine($"{RequestInfoVarName}->setContentFromScalar{suffix}($this->{requestAdapterProperty.Name.ToFirstCharacterLowerCase()}, \"{codeElement.RequestBodyContentType}\", {conventions.GetParameterName(requestParams.requestBody)});"); + writer.WriteLine($"{RequestInfoVarName}->setContentFromScalar{suffix}($this->{requestAdapterProperty.Name.ToFirstCharacterLowerCase()}, \"{sanitizedRequestBodyContentType}\", {conventions.GetParameterName(requestParams.requestBody)});"); } writer.WriteLine($"return {RequestInfoVarName};"); @@ -612,7 +613,7 @@ private void WriteRequestConfiguration(RequestParams requestParams, LanguageWrit private void WriteAcceptHeaderDef(CodeMethod codeMethod, LanguageWriter writer) { if (codeMethod.ShouldAddAcceptHeader) - writer.WriteLine($"{RequestInfoVarName}->tryAddHeader('Accept', \"{codeMethod.AcceptHeaderValue}\");"); + writer.WriteLine($"{RequestInfoVarName}->tryAddHeader('Accept', \"{codeMethod.AcceptHeaderValue.SanitizeDoubleQuote()}\");"); } private void WriteDeserializerBody(CodeClass parentClass, LanguageWriter writer, CodeMethod method, bool extendsModelClass = false) { diff --git a/src/Kiota.Builder/Writers/Python/CodeMethodWriter.cs b/src/Kiota.Builder/Writers/Python/CodeMethodWriter.cs index 42a222e36b..f156bf9262 100644 --- a/src/Kiota.Builder/Writers/Python/CodeMethodWriter.cs +++ b/src/Kiota.Builder/Writers/Python/CodeMethodWriter.cs @@ -619,7 +619,7 @@ private void WriteRequestGeneratorBody(CodeMethod codeElement, RequestParams req if (requestParams.requestConfiguration != null) writer.WriteLine($"{RequestInfoVarName}.configure({requestParams.requestConfiguration.Name})"); if (codeElement.ShouldAddAcceptHeader) - writer.WriteLine($"{RequestInfoVarName}.headers.try_add(\"Accept\", \"{codeElement.AcceptHeaderValue}\")"); + writer.WriteLine($"{RequestInfoVarName}.headers.try_add(\"Accept\", \"{codeElement.AcceptHeaderValue.SanitizeDoubleQuote()}\")"); if (currentClass.GetPropertyOfKind(CodePropertyKind.RequestAdapter) is CodeProperty requestAdapterProperty) UpdateRequestInformationFromRequestBody(codeElement, requestParams, requestAdapterProperty, writer); writer.WriteLine($"return {RequestInfoVarName}"); @@ -823,17 +823,18 @@ private void UpdateRequestInformationFromRequestBody(CodeMethod codeElement, Req { if (requestParams.requestBody != null) { + var sanitizedRequestBodyContentType = codeElement.RequestBodyContentType.SanitizeDoubleQuote(); if (requestParams.requestBody.Type.Name.Equals(conventions.StreamTypeName, StringComparison.OrdinalIgnoreCase)) { if (requestParams.requestContentType is not null) writer.WriteLine($"{RequestInfoVarName}.set_stream_content({requestParams.requestBody.Name}, {requestParams.requestContentType.Name})"); - else if (!string.IsNullOrEmpty(codeElement.RequestBodyContentType)) - writer.WriteLine($"{RequestInfoVarName}.set_stream_content({requestParams.requestBody.Name}, \"{codeElement.RequestBodyContentType}\")"); + else if (!string.IsNullOrEmpty(sanitizedRequestBodyContentType)) + writer.WriteLine($"{RequestInfoVarName}.set_stream_content({requestParams.requestBody.Name}, \"{sanitizedRequestBodyContentType}\")"); } else { var setMethodName = requestParams.requestBody.Type is CodeType bodyType && bodyType.TypeDefinition is CodeClass ? "set_content_from_parsable" : "set_content_from_scalar"; - writer.WriteLine($"{RequestInfoVarName}.{setMethodName}(self.{requestAdapterProperty.Name}, \"{codeElement.RequestBodyContentType}\", {requestParams.requestBody.Name})"); + writer.WriteLine($"{RequestInfoVarName}.{setMethodName}(self.{requestAdapterProperty.Name}, \"{sanitizedRequestBodyContentType}\", {requestParams.requestBody.Name})"); } } } diff --git a/src/Kiota.Builder/Writers/Ruby/CodeMethodWriter.cs b/src/Kiota.Builder/Writers/Ruby/CodeMethodWriter.cs index a20eeb3823..8b51bc0e29 100644 --- a/src/Kiota.Builder/Writers/Ruby/CodeMethodWriter.cs +++ b/src/Kiota.Builder/Writers/Ruby/CodeMethodWriter.cs @@ -301,15 +301,16 @@ private void WriteRequestGeneratorBody(CodeMethod codeElement, RequestParams req } if (requestParams.requestBody != null) { + var sanitizedRequestBodyContentType = codeElement.RequestBodyContentType.SanitizeSingleQuote(); if (requestParams.requestBody.Type.Name.Equals(conventions.StreamTypeName, StringComparison.OrdinalIgnoreCase)) { if (requestParams.requestContentType is not null) writer.WriteLine($"request_info.set_stream_content({requestParams.requestBody.Name}, {requestParams.requestContentType.Name})"); - else if (!string.IsNullOrEmpty(codeElement.RequestBodyContentType)) - writer.WriteLine($"request_info.set_stream_content({requestParams.requestBody.Name}, \"{codeElement.RequestBodyContentType}\")"); + else if (!string.IsNullOrEmpty(sanitizedRequestBodyContentType)) + writer.WriteLine($"request_info.set_stream_content({requestParams.requestBody.Name}, '{sanitizedRequestBodyContentType}')"); } else if (parentClass.GetPropertyOfKind(CodePropertyKind.RequestAdapter) is CodeProperty requestAdapterProperty) - writer.WriteLine($"request_info.set_content_from_parsable(@{requestAdapterProperty.Name.ToSnakeCase()}, \"{codeElement.RequestBodyContentType}\", {requestParams.requestBody.Name})"); + writer.WriteLine($"request_info.set_content_from_parsable(@{requestAdapterProperty.Name.ToSnakeCase()}, '{sanitizedRequestBodyContentType}', {requestParams.requestBody.Name})"); } } if (parentClass.GetPropertyOfKind(CodePropertyKind.PathParameters) is CodeProperty urlTemplateParamsProperty && @@ -321,7 +322,7 @@ private void WriteRequestGeneratorBody(CodeMethod codeElement, RequestParams req } writer.WriteLine($"request_info.http_method = :{codeElement.HttpMethod.Value.ToString().ToUpperInvariant()}"); if (codeElement.ShouldAddAcceptHeader) - writer.WriteLine($"request_info.headers.try_add('Accept', '{codeElement.AcceptHeaderValue}')"); + writer.WriteLine($"request_info.headers.try_add('Accept', '{codeElement.AcceptHeaderValue.SanitizeSingleQuote()}')"); writer.WriteLine("return request_info"); } private static string GetPropertyCall(CodeProperty property, string defaultValue) => property == null ? defaultValue : $"@{property.NamePrefix}{property.Name.ToSnakeCase()}"; diff --git a/src/Kiota.Builder/Writers/StringExtensions.cs b/src/Kiota.Builder/Writers/StringExtensions.cs index c3e9c21043..46f9461283 100644 --- a/src/Kiota.Builder/Writers/StringExtensions.cs +++ b/src/Kiota.Builder/Writers/StringExtensions.cs @@ -1,5 +1,29 @@ -namespace Kiota.Builder.Writers; +using System; + +namespace Kiota.Builder.Writers; + public static class StringExtensions { - public static string StripArraySuffix(this string original) => string.IsNullOrEmpty(original) ? original : original.TrimEnd(']').TrimEnd('['); + public static string StripArraySuffix(this string original) => + string.IsNullOrEmpty(original) ? original : original.TrimEnd(']').TrimEnd('['); + + /// + /// Sanitize a string for direct writing. + /// + /// The string to sanitize. + /// The sanitized string. + public static string SanitizeDoubleQuote(this string original) + => string.IsNullOrEmpty(original) + ? original + : original.Replace("\"", "\\\"", StringComparison.Ordinal); + + /// + /// Sanitize a string for direct writing. + /// + /// The string to sanitize. + /// The sanitized string. + public static string SanitizeSingleQuote(this string original) + => string.IsNullOrEmpty(original) + ? original + : original.Replace("'", "\\'", StringComparison.Ordinal); } diff --git a/src/Kiota.Builder/Writers/TypeScript/CodeConstantWriter.cs b/src/Kiota.Builder/Writers/TypeScript/CodeConstantWriter.cs index c1d37e9233..a3e0f9401b 100644 --- a/src/Kiota.Builder/Writers/TypeScript/CodeConstantWriter.cs +++ b/src/Kiota.Builder/Writers/TypeScript/CodeConstantWriter.cs @@ -105,7 +105,7 @@ private void WriteRequestsMetadataConstant(CodeConstant codeElement, LanguageWri writer.WriteLine($"uriTemplate: {urlTemplateValue},"); if (codeClass.Methods.FirstOrDefault(x => x.Kind is CodeMethodKind.RequestGenerator && x.HttpMethod == executorMethod.HttpMethod) is { } generatorMethod && generatorMethod.AcceptHeaderValue is string acceptHeader && !string.IsNullOrEmpty(acceptHeader)) - writer.WriteLine($"responseBodyContentType: \"{acceptHeader}\","); + writer.WriteLine($"responseBodyContentType: \"{acceptHeader.SanitizeDoubleQuote()}\","); if (executorMethod.ErrorMappings.Any()) { writer.StartBlock("errorMappings: {"); @@ -118,8 +118,9 @@ private void WriteRequestsMetadataConstant(CodeConstant codeElement, LanguageWri writer.WriteLine($"adapterMethodName: \"{GetSendRequestMethodName(isVoid, isStream, executorMethod.ReturnType.IsCollection, returnTypeWithoutCollectionSymbol)}\","); if (!isVoid) writer.WriteLine($"responseBodyFactory: {GetTypeFactory(isVoid, isStream, executorMethod, writer)},"); - if (!string.IsNullOrEmpty(executorMethod.RequestBodyContentType)) - writer.WriteLine($"requestBodyContentType: \"{executorMethod.RequestBodyContentType}\","); + var sanitizedRequestBodyContentType = executorMethod.RequestBodyContentType.SanitizeDoubleQuote(); + if (!string.IsNullOrEmpty(sanitizedRequestBodyContentType)) + writer.WriteLine($"requestBodyContentType: \"{sanitizedRequestBodyContentType}\","); if (executorMethod.Parameters.FirstOrDefault(static x => x.Kind is CodeParameterKind.RequestBody) is CodeParameter requestBody) { if (GetBodySerializer(requestBody) is string bodySerializer) diff --git a/tests/Kiota.Builder.Tests/Writers/CSharp/CodeMethodWriterTests.cs b/tests/Kiota.Builder.Tests/Writers/CSharp/CodeMethodWriterTests.cs index 2dc8a949f3..820e7d2a5d 100644 --- a/tests/Kiota.Builder.Tests/Writers/CSharp/CodeMethodWriterTests.cs +++ b/tests/Kiota.Builder.Tests/Writers/CSharp/CodeMethodWriterTests.cs @@ -1850,4 +1850,31 @@ public void WritesDeprecationInformationFromBuilder() var result = tw.ToString(); Assert.Contains("This method is obsolete. Use NewAwesomeMethod instead.", result); } + + [Fact] + public void WritesRequestGeneratorAcceptHeaderQuotes() + { + setup(); + method.Kind = CodeMethodKind.RequestGenerator; + method.HttpMethod = HttpMethod.Get; + AddRequestProperties(); + method.AcceptedResponseTypes.Add("application/json; profile=\"CamelCase\""); + writer.Write(method); + var result = tw.ToString(); + Assert.Contains("requestInfo.Headers.TryAdd(\"Accept\", \"application/json; profile=\\\"CamelCase\\\"\")", result); + } + + [Fact] + public void WritesRequestGeneratorContentTypeQuotes() + { + setup(); + method.Kind = CodeMethodKind.RequestGenerator; + method.HttpMethod = HttpMethod.Post; + AddRequestProperties(); + AddRequestBodyParameters(); + method.RequestBodyContentType = "application/json; profile=\"CamelCase\""; + writer.Write(method); + var result = tw.ToString(); + Assert.Contains("\"application/json; profile=\\\"CamelCase\\\"\"", result); + } } diff --git a/tests/Kiota.Builder.Tests/Writers/Go/CodeMethodWriterTests.cs b/tests/Kiota.Builder.Tests/Writers/Go/CodeMethodWriterTests.cs index da4ee17d6b..54ded91a6e 100644 --- a/tests/Kiota.Builder.Tests/Writers/Go/CodeMethodWriterTests.cs +++ b/tests/Kiota.Builder.Tests/Writers/Go/CodeMethodWriterTests.cs @@ -2266,4 +2266,31 @@ public void WritesMessageOverrideOnPrimary() Assert.Contains("Error()(string) {", result); Assert.Contains("return *(m.GetProp1()", result); } + + [Fact] + public void WritesRequestGeneratorAcceptHeaderQuotes() + { + setup(); + method.Kind = CodeMethodKind.RequestGenerator; + method.HttpMethod = HttpMethod.Get; + AddRequestProperties(); + method.AcceptedResponseTypes.Add("application/json; profile=\"CamelCase\""); + writer.Write(method); + var result = tw.ToString(); + Assert.Contains("requestInfo.Headers.TryAdd(\"Accept\", \"application/json; profile=\\\"CamelCase\\\"\")", result); + } + + [Fact] + public void WritesRequestGeneratorContentTypeQuotes() + { + setup(); + method.Kind = CodeMethodKind.RequestGenerator; + method.HttpMethod = HttpMethod.Post; + AddRequestProperties(); + AddRequestBodyParameters(); + method.RequestBodyContentType = "application/json; profile=\"CamelCase\""; + writer.Write(method); + var result = tw.ToString(); + Assert.Contains("\"application/json; profile=\\\"CamelCase\\\"\"", result); + } } diff --git a/tests/Kiota.Builder.Tests/Writers/Java/CodeMethodWriterTests.cs b/tests/Kiota.Builder.Tests/Writers/Java/CodeMethodWriterTests.cs index 1fa32f6de4..dca1b6850f 100644 --- a/tests/Kiota.Builder.Tests/Writers/Java/CodeMethodWriterTests.cs +++ b/tests/Kiota.Builder.Tests/Writers/Java/CodeMethodWriterTests.cs @@ -2132,4 +2132,31 @@ public void WritesMessageOverrideOnPrimary() Assert.Contains("String getErrorMessage() ", result); Assert.Contains("return this.getProp1()", result); } + + [Fact] + public void WritesRequestGeneratorAcceptHeaderQuotes() + { + setup(); + method.Kind = CodeMethodKind.RequestGenerator; + method.HttpMethod = HttpMethod.Get; + AddRequestProperties(); + method.AcceptedResponseTypes.Add("application/json; profile=\"CamelCase\""); + writer.Write(method); + var result = tw.ToString(); + Assert.Contains("requestInfo.headers.tryAdd(\"Accept\", \"application/json; profile=\\\"CamelCase\\\"\");", result); + } + + [Fact] + public void WritesRequestGeneratorContentTypeQuotes() + { + setup(); + method.Kind = CodeMethodKind.RequestGenerator; + method.HttpMethod = HttpMethod.Post; + AddRequestProperties(); + AddRequestBodyParameters(); + method.RequestBodyContentType = "application/json; profile=\"CamelCase\""; + writer.Write(method); + var result = tw.ToString(); + Assert.Contains("\"application/json; profile=\\\"CamelCase\\\"\"", result); + } } diff --git a/tests/Kiota.Builder.Tests/Writers/Php/CodeMethodWriterTests.cs b/tests/Kiota.Builder.Tests/Writers/Php/CodeMethodWriterTests.cs index d7fecc9ab7..f5dd725799 100644 --- a/tests/Kiota.Builder.Tests/Writers/Php/CodeMethodWriterTests.cs +++ b/tests/Kiota.Builder.Tests/Writers/Php/CodeMethodWriterTests.cs @@ -2482,4 +2482,30 @@ public async Task WritesFullyQualifiedNameWhenSimilarTypeAlreadyExists() Assert.Contains("return $this->requestAdapter->sendCollectionAsync($requestInfo, [Component::class, 'createFromDiscriminatorValue'], null);", result); } + [Fact] + public void WritesRequestGeneratorAcceptHeaderQuotes() + { + setup(); + method.Kind = CodeMethodKind.RequestGenerator; + method.HttpMethod = HttpMethod.Get; + AddRequestProperties(); + method.AcceptedResponseTypes.Add("application/json; profile=\"CamelCase\""); + languageWriter.Write(method); + var result = stringWriter.ToString(); + Assert.Contains("$requestInfo->tryAddHeader('Accept', \"application/json; profile=\\\"CamelCase\\\"\");", result); + } + + [Fact] + public void WritesRequestGeneratorContentTypeQuotes() + { + setup(); + method.Kind = CodeMethodKind.RequestGenerator; + method.HttpMethod = HttpMethod.Post; + AddRequestProperties(); + AddRequestBodyParameters(); + method.RequestBodyContentType = "application/json; profile=\"CamelCase\""; + languageWriter.Write(method); + var result = stringWriter.ToString(); + Assert.Contains("\"application/json; profile=\\\"CamelCase\\\"\"", result); + } } diff --git a/tests/Kiota.Builder.Tests/Writers/Python/CodeMethodWriterTests.cs b/tests/Kiota.Builder.Tests/Writers/Python/CodeMethodWriterTests.cs index 6693c4ba59..b4d73a1481 100644 --- a/tests/Kiota.Builder.Tests/Writers/Python/CodeMethodWriterTests.cs +++ b/tests/Kiota.Builder.Tests/Writers/Python/CodeMethodWriterTests.cs @@ -2202,4 +2202,31 @@ public void WritesDeprecationInformationFromBuilder() var result = tw.ToString(); Assert.Contains("This method is obsolete. Use NewAwesomeMethod instead.", result); } + + [Fact] + public void WritesRequestGeneratorAcceptHeaderQuotes() + { + setup(); + method.Kind = CodeMethodKind.RequestGenerator; + method.HttpMethod = HttpMethod.Get; + AddRequestProperties(); + method.AcceptedResponseTypes.Add("application/json; profile=\"CamelCase\""); + writer.Write(method); + var result = tw.ToString(); + Assert.Contains("request_info.headers.try_add(\"Accept\", \"application/json; profile=\\\"CamelCase\\\"\")", result); + } + + [Fact] + public void WritesRequestGeneratorContentTypeQuotes() + { + setup(); + method.Kind = CodeMethodKind.RequestGenerator; + method.HttpMethod = HttpMethod.Post; + AddRequestProperties(); + AddRequestBodyParameters(); + method.RequestBodyContentType = "application/json; profile=\"CamelCase\""; + writer.Write(method); + var result = tw.ToString(); + Assert.Contains("\"application/json; profile=\\\"CamelCase\\\"\"", result); + } } diff --git a/tests/Kiota.Builder.Tests/Writers/Ruby/CodeMethodWriterTests.cs b/tests/Kiota.Builder.Tests/Writers/Ruby/CodeMethodWriterTests.cs index 44cb9bdd9c..1f2a128c5c 100644 --- a/tests/Kiota.Builder.Tests/Writers/Ruby/CodeMethodWriterTests.cs +++ b/tests/Kiota.Builder.Tests/Writers/Ruby/CodeMethodWriterTests.cs @@ -1074,4 +1074,31 @@ public void DoesntWriteReadOnlyPropertiesInSerializerBody() Assert.DoesNotContain("ReadOnlyProperty", result); AssertExtensions.CurlyBracesAreClosed(result); } + + [Fact] + public void WritesRequestGeneratorAcceptHeaderQuotes() + { + setup(); + method.Kind = CodeMethodKind.RequestGenerator; + method.HttpMethod = HttpMethod.Get; + AddRequestProperties(); + method.AcceptedResponseTypes.Add("application/json; profile='CamelCase'"); + writer.Write(method); + var result = tw.ToString(); + Assert.Contains("request_info.headers.try_add('Accept', 'application/json; profile=\\'CamelCase\\'')", result); + } + + [Fact] + public void WritesRequestGeneratorContentTypeQuotes() + { + setup(); + method.Kind = CodeMethodKind.RequestGenerator; + method.HttpMethod = HttpMethod.Post; + AddRequestProperties(); + AddRequestBodyParameters(); + method.RequestBodyContentType = "application/json; profile='CamelCase'"; + writer.Write(method); + var result = tw.ToString(); + Assert.Contains("'application/json; profile=\\'CamelCase\\''", result); + } }