Skip to content

Commit

Permalink
Merge pull request #619 from christianhelle/fix-missing-content-type-…
Browse files Browse the repository at this point in the history
…headers

Fix missing Content-Type [Headers]
  • Loading branch information
christianhelle authored Feb 26, 2025
2 parents 4d37dbf + fd62613 commit c3bf4f1
Show file tree
Hide file tree
Showing 17 changed files with 246 additions and 44 deletions.
28 changes: 24 additions & 4 deletions src/Refitter.Core/RefitInterfaceGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ private string GenerateInterfaceBody(out string? dynamicQuerystringParameters)
this.docGenerator.AppendMethodDocumentation(operationModel, IsApiResponseType(returnType), hasDynamicQuerystringParameter, hasApizrRequestOptionsParameter, code);
GenerateObsoleteAttribute(operation, code);
GenerateForMultipartFormData(operationModel, code);
GenerateAcceptHeaders(operations, operation, code);
GenerateHeaders(operations, operation, code);

code.AppendLine($"{Separator}{Separator}[{verb}(\"{kv.Key}\")]")
.AppendLine($"{Separator}{Separator}{returnType} {operationName}({parametersString});")
Expand All @@ -85,7 +85,7 @@ private string GenerateInterfaceBody(out string? dynamicQuerystringParameters)
this.docGenerator.AppendMethodDocumentation(operationModel, IsApiResponseType(returnType), false, hasApizrRequestOptionsParameter, code);
GenerateObsoleteAttribute(operation, code);
GenerateForMultipartFormData(operationModel, code);
GenerateAcceptHeaders(operations, operation, code);
GenerateHeaders(operations, operation, code);

parametersString = string.Join(", ", parameters.Where(parameter => !parameter.Contains("?")));

Expand Down Expand Up @@ -166,11 +166,13 @@ protected static void GenerateForMultipartFormData(CSharpOperationModel operatio
}
}

protected void GenerateAcceptHeaders(
protected void GenerateHeaders(
KeyValuePair<string, OpenApiOperation> operations,
OpenApiOperation operation,
StringBuilder code)
{
var headers = new List<string>();

if (settings.AddAcceptHeaders && document.SchemaType is >= NJsonSchema.SchemaType.OpenApi3)
{
//Generate header "Accept"
Expand All @@ -185,9 +187,27 @@ protected void GenerateAcceptHeaders(

if (uniqueContentTypes.Any())
{
code.AppendLine($"{Separator}{Separator}[Headers(\"Accept: {string.Join(", ", uniqueContentTypes)}\")]");
headers.Add($"\"Accept: {string.Join(", ", uniqueContentTypes)}\"");
}
}

if (settings.AddContentTypeHeaders && document.SchemaType is >= NJsonSchema.SchemaType.OpenApi3)
{
var uniqueContentTypes = operations.Value.RequestBody?.Content.Keys ?? Array.Empty<string>();
var contentType =
uniqueContentTypes.FirstOrDefault(c => c.Equals("application/json", StringComparison.OrdinalIgnoreCase)) ??
uniqueContentTypes.FirstOrDefault();

if (!string.IsNullOrWhiteSpace(contentType))
{
headers.Add($"\"Content-Type: {contentType}\"");
}
}

if (headers.Any())
{
code.AppendLine($"{Separator}{Separator}[Headers({string.Join(", ", headers)})]");
}
}

protected string GetReturnType(string? returnTypeParameter)
Expand Down
4 changes: 2 additions & 2 deletions src/Refitter.Core/RefitMultipleInterfaceByTagGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ public override IEnumerable<GeneratedCode> GenerateCode()
this.docGenerator.AppendMethodDocumentation(operationModel, IsApiResponseType(returnType), hasDynamicQuerystringParameter, hasApizrRequestOptionsParameter, sb);
GenerateObsoleteAttribute(operation, sb);
GenerateForMultipartFormData(operationModel, sb);
GenerateAcceptHeaders(operations, operation, sb);
GenerateHeaders(operations, operation, sb);

sb.AppendLine($"{Separator}{Separator}[{verb}(\"{op.PathItem.Key}\")]")
.AppendLine($"{Separator}{Separator}{returnType} {operationName}({parametersString});")
Expand All @@ -95,7 +95,7 @@ public override IEnumerable<GeneratedCode> GenerateCode()
this.docGenerator.AppendMethodDocumentation(operationModel, IsApiResponseType(returnType), false, hasApizrRequestOptionsParameter, sb);
GenerateObsoleteAttribute(operation, sb);
GenerateForMultipartFormData(operationModel, sb);
GenerateAcceptHeaders(operations, operation, sb);
GenerateHeaders(operations, operation, sb);

parametersString = string.Join(", ", parameters.Where(parameter => !parameter.Contains("?")));

Expand Down
4 changes: 2 additions & 2 deletions src/Refitter.Core/RefitMultipleInterfaceGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public override IEnumerable<GeneratedCode> GenerateCode()
this.docGenerator.AppendMethodDocumentation(operationModel, IsApiResponseType(returnType), hasDynamicQuerystringParameter, hasApizrRequestOptionsParameter, code);
GenerateObsoleteAttribute(operation, code);
GenerateForMultipartFormData(operationModel, code);
GenerateAcceptHeaders(operations, operation, code);
GenerateHeaders(operations, operation, code);

code.AppendLine($"{Separator}{Separator}[{verb}(\"{kv.Key}\")]")
.AppendLine($"{Separator}{Separator}{returnType} {methodName}({parametersString});")
Expand All @@ -69,7 +69,7 @@ public override IEnumerable<GeneratedCode> GenerateCode()
this.docGenerator.AppendMethodDocumentation(operationModel, IsApiResponseType(returnType), false, hasApizrRequestOptionsParameter, code);
GenerateObsoleteAttribute(operation, code);
GenerateForMultipartFormData(operationModel, code);
GenerateAcceptHeaders(operations, operation, code);
GenerateHeaders(operations, operation, code);

parametersString = string.Join(", ", parameters.Where(parameter => !parameter.Contains("?")));

Expand Down
5 changes: 5 additions & 0 deletions src/Refitter.Core/Settings/RefitGeneratorSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,11 @@ public class RefitGeneratorSettings
/// </summary>
public bool AddAcceptHeaders { get; set; } = true;

/// <summary>
/// Gets or sets a value indicating whether to add content-type headers [Headers("Content-Type: application/json")].
/// </summary>
public bool AddContentTypeHeaders { get; set; } = true;

/// <summary>
/// Gets or sets a value indicating whether to return <c>IApiResponse</c> objects.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public partial interface ISwaggerPetstore
/// </item>
/// </list>
/// </exception>
[Headers("Accept: application/xml, application/json")]
[Headers("Accept: application/xml, application/json", "Content-Type: application/json")]
[Put("/pet")]
Task<Pet> UpdatePet([Body] Pet body);

Expand All @@ -61,7 +61,7 @@ public partial interface ISwaggerPetstore
/// </item>
/// </list>
/// </exception>
[Headers("Accept: application/xml, application/json")]
[Headers("Accept: application/xml, application/json", "Content-Type: application/json")]
[Post("/pet")]
Task<Pet> AddPet([Body] Pet body);

Expand Down Expand Up @@ -188,7 +188,7 @@ public partial interface ISwaggerPetstore
/// </item>
/// </list>
/// </returns>
[Headers("Accept: application/json")]
[Headers("Accept: application/json", "Content-Type: application/octet-stream")]
[Post("/pet/{petId}/uploadImage")]
Task<ApiResponse> UploadFile(long petId, [Query] string additionalMetadata, StreamPart body);

Expand Down Expand Up @@ -216,7 +216,7 @@ public partial interface ISwaggerPetstore
/// </item>
/// </list>
/// </exception>
[Headers("Accept: application/json")]
[Headers("Accept: application/json", "Content-Type: application/json")]
[Post("/store/order")]
Task<Order> PlaceOrder([Body] Order body);

Expand Down Expand Up @@ -274,15 +274,15 @@ public partial interface ISwaggerPetstore
/// <param name="body">Created user object</param>
/// <returns>successful operation</returns>
/// <exception cref="ApiException">Thrown when the request returns a non-success status code.</exception>
[Headers("Accept: application/json, application/xml")]
[Headers("Accept: application/json, application/xml", "Content-Type: application/json")]
[Post("/user")]
Task CreateUser([Body] User body);

/// <summary>Creates list of users with given input array</summary>
/// <remarks>Creates list of users with given input array</remarks>
/// <returns>Successful operation</returns>
/// <exception cref="ApiException">Thrown when the request returns a non-success status code.</exception>
[Headers("Accept: application/xml, application/json")]
[Headers("Accept: application/xml, application/json", "Content-Type: application/json")]
[Post("/user/createWithList")]
Task<User> CreateUsersWithListInput([Body] IEnumerable<User> body);

Expand Down Expand Up @@ -343,6 +343,7 @@ public partial interface ISwaggerPetstore
/// <param name="body">Update an existent user in the store</param>
/// <returns>A <see cref="Task"/> that completes when the request is finished.</returns>
/// <exception cref="ApiException">Thrown when the request returns a non-success status code.</exception>
[Headers("Content-Type: application/json")]
[Put("/user/{username}")]
Task UpdateUser(string username, [Body] User body);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ public partial interface IUpdatePetEndpoint
/// </item>
/// </list>
/// </exception>
[Headers("Content-Type: application/json")]
[Put("/pet")]
Task<Pet> Execute([Body] Pet body);
}
Expand All @@ -68,6 +69,7 @@ public partial interface IAddPetEndpoint
/// </item>
/// </list>
/// </exception>
[Headers("Content-Type: application/json")]
[Post("/pet")]
Task<Pet> Execute([Body] Pet body);
}
Expand Down Expand Up @@ -221,6 +223,7 @@ public partial interface IUploadFileEndpoint
/// </item>
/// </list>
/// </returns>
[Headers("Content-Type: application/octet-stream")]
[Post("/pet/{petId}/uploadImage")]
Task<ApiResponse> Execute(long petId, [Query] string additionalMetadata, StreamPart body);
}
Expand Down Expand Up @@ -257,6 +260,7 @@ public partial interface IPlaceOrderEndpoint
/// </item>
/// </list>
/// </exception>
[Headers("Content-Type: application/json")]
[Post("/store/order")]
Task<Order> Execute([Body] Order body);
}
Expand Down Expand Up @@ -328,6 +332,7 @@ public partial interface ICreateUserEndpoint
/// <param name="body">Created user object</param>
/// <returns>successful operation</returns>
/// <exception cref="ApiException">Thrown when the request returns a non-success status code.</exception>
[Headers("Content-Type: application/json")]
[Post("/user")]
Task Execute([Body] User body);
}
Expand All @@ -340,6 +345,7 @@ public partial interface ICreateUsersWithListInputEndpoint
/// <remarks>Creates list of users with given input array</remarks>
/// <returns>Successful operation</returns>
/// <exception cref="ApiException">Thrown when the request returns a non-success status code.</exception>
[Headers("Content-Type: application/json")]
[Post("/user/createWithList")]
Task<User> Execute([Body] IEnumerable<User> body);
}
Expand Down Expand Up @@ -418,6 +424,7 @@ public partial interface IUpdateUserEndpoint
/// <param name="body">Update an existent user in the store</param>
/// <returns>A <see cref="Task"/> that completes when the request is finished.</returns>
/// <exception cref="ApiException">Thrown when the request returns a non-success status code.</exception>
[Headers("Content-Type: application/json")]
[Put("/user/{username}")]
Task Execute(string username, [Body] User body);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ public partial interface IPetApi
/// </item>
/// </list>
/// </exception>
[Headers("Content-Type: application/json")]
[Put("/pet")]
Task<Pet> UpdatePet([Body] Pet body);

Expand All @@ -63,6 +64,7 @@ public partial interface IPetApi
/// </item>
/// </list>
/// </exception>
[Headers("Content-Type: application/json")]
[Post("/pet")]
Task<Pet> AddPet([Body] Pet body);

Expand Down Expand Up @@ -186,6 +188,7 @@ public partial interface IPetApi
/// </item>
/// </list>
/// </returns>
[Headers("Content-Type: application/octet-stream")]
[Post("/pet/{petId}/uploadImage")]
Task<ApiResponse> UploadFile(long petId, [Query] string additionalMetadata, StreamPart body);
}
Expand Down Expand Up @@ -217,6 +220,7 @@ public partial interface IStoreApi
/// </item>
/// </list>
/// </exception>
[Headers("Content-Type: application/json")]
[Post("/store/order")]
Task<Order> PlaceOrder([Body] Order body);

Expand Down Expand Up @@ -278,13 +282,15 @@ public partial interface IUserApi
/// <param name="body">Created user object</param>
/// <returns>successful operation</returns>
/// <exception cref="ApiException">Thrown when the request returns a non-success status code.</exception>
[Headers("Content-Type: application/json")]
[Post("/user")]
Task CreateUser([Body] User body);

/// <summary>Creates list of users with given input array</summary>
/// <remarks>Creates list of users with given input array</remarks>
/// <returns>Successful operation</returns>
/// <exception cref="ApiException">Thrown when the request returns a non-success status code.</exception>
[Headers("Content-Type: application/json")]
[Post("/user/createWithList")]
Task<User> CreateUsersWithListInput([Body] IEnumerable<User> body);

Expand Down Expand Up @@ -343,6 +349,7 @@ public partial interface IUserApi
/// <param name="body">Update an existent user in the store</param>
/// <returns>A <see cref="Task"/> that completes when the request is finished.</returns>
/// <exception cref="ApiException">Thrown when the request returns a non-success status code.</exception>
[Headers("Content-Type: application/json")]
[Put("/user/{username}")]
Task UpdateUser(string username, [Body] User body);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public partial interface ISwaggerPetstoreWithOptionalParameters
/// </item>
/// </list>
/// </exception>
[Headers("Accept: application/xml, application/json")]
[Headers("Accept: application/xml, application/json", "Content-Type: application/json")]
[Put("/pet")]
Task<Pet> UpdatePet([Body] Pet body);

Expand All @@ -61,7 +61,7 @@ public partial interface ISwaggerPetstoreWithOptionalParameters
/// </item>
/// </list>
/// </exception>
[Headers("Accept: application/xml, application/json")]
[Headers("Accept: application/xml, application/json", "Content-Type: application/json")]
[Post("/pet")]
Task<Pet> AddPet([Body] Pet body);

Expand Down Expand Up @@ -188,7 +188,7 @@ public partial interface ISwaggerPetstoreWithOptionalParameters
/// </item>
/// </list>
/// </returns>
[Headers("Accept: application/json")]
[Headers("Accept: application/json", "Content-Type: application/octet-stream")]
[Post("/pet/{petId}/uploadImage")]
Task<ApiResponse> UploadFile(long petId, StreamPart body, [Query] string? additionalMetadata = default);

Expand Down Expand Up @@ -216,7 +216,7 @@ public partial interface ISwaggerPetstoreWithOptionalParameters
/// </item>
/// </list>
/// </exception>
[Headers("Accept: application/json")]
[Headers("Accept: application/json", "Content-Type: application/json")]
[Post("/store/order")]
Task<Order> PlaceOrder([Body] Order? body = default);

Expand Down Expand Up @@ -274,15 +274,15 @@ public partial interface ISwaggerPetstoreWithOptionalParameters
/// <param name="body">Created user object</param>
/// <returns>successful operation</returns>
/// <exception cref="ApiException">Thrown when the request returns a non-success status code.</exception>
[Headers("Accept: application/json, application/xml")]
[Headers("Accept: application/json, application/xml", "Content-Type: application/json")]
[Post("/user")]
Task CreateUser([Body] User? body = default);

/// <summary>Creates list of users with given input array</summary>
/// <remarks>Creates list of users with given input array</remarks>
/// <returns>Successful operation</returns>
/// <exception cref="ApiException">Thrown when the request returns a non-success status code.</exception>
[Headers("Accept: application/xml, application/json")]
[Headers("Accept: application/xml, application/json", "Content-Type: application/json")]
[Post("/user/createWithList")]
Task<User> CreateUsersWithListInput([Body] IEnumerable<User>? body = default);

Expand Down Expand Up @@ -343,6 +343,7 @@ public partial interface ISwaggerPetstoreWithOptionalParameters
/// <param name="body">Update an existent user in the store</param>
/// <returns>A <see cref="Task"/> that completes when the request is finished.</returns>
/// <exception cref="ApiException">Thrown when the request returns a non-success status code.</exception>
[Headers("Content-Type: application/json")]
[Put("/user/{username}")]
Task UpdateUser(string username, [Body] User? body = default);

Expand Down
Loading

0 comments on commit c3bf4f1

Please sign in to comment.