Closed
Description
openedon Feb 18, 2024
Our server returns HTTP 304 (Not Modified) without a response body when the incoming fingerprint in the If-None-Match
header matches the stored version. This enables clients to poll for changes without receiving a response body, unless it has changed since it was last fetched.
Status 304 is described in the OAS document, but Kiota throws an ApiException
saying the error isn't mapped:
Microsoft.Kiota.Abstractions.ApiException: The server returned an unexpected status code and no error factory is registered for this code: 304
OAS fragment:
{
"paths": {
"/api/people": {
"get": {
"tags": [
"people"
],
"summary": "Retrieves a collection of people.",
"operationId": "getPersonCollection",
"responses": {
"200": {
"description": "Successfully returns the found people, or an empty array if none were found.",
"headers": {
"ETag": {
"description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.",
"required": true,
"schema": {
"type": "string"
}
}
},
"content": {
"application/vnd.api+json": {
"schema": {
"$ref": "#/components/schemas/personCollectionResponseDocument"
}
}
}
},
"400": {
"description": "The query string is invalid.",
"content": {
"application/vnd.api+json": {
"schema": {
"$ref": "#/components/schemas/errorResponseDocument"
}
}
}
},
"304": {
"description": "The fingerprint of the HTTP response matches one of the ETags from the incoming If_None_Match header.",
"headers": {
"ETag": {
"description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.",
"required": true,
"schema": {
"type": "string"
}
}
}
}
}
}
}
}
}
Generated C# code:
namespace GeneratedClient.Api.People {
public class PeopleRequestBuilder : BaseRequestBuilder {
/// <summary>
/// Retrieves a collection of people.
/// </summary>
/// <param name="cancellationToken">Cancellation token to use when cancelling requests</param>
/// <param name="requestConfiguration">Configuration for the request such as headers, query parameters, and middleware options.</param>
#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_1_OR_GREATER
#nullable enable
public async Task<PersonCollectionResponseDocument?> GetAsync(Action<RequestConfiguration<PeopleRequestBuilderGetQueryParameters>>? requestConfiguration = default, CancellationToken cancellationToken = default) {
#nullable restore
#else
public async Task<PersonCollectionResponseDocument> GetAsync(Action<RequestConfiguration<PeopleRequestBuilderGetQueryParameters>> requestConfiguration = default, CancellationToken cancellationToken = default) {
#endif
var requestInfo = ToGetRequestInformation(requestConfiguration);
var errorMapping = new Dictionary<string, ParsableFactory<IParsable>> {
{"400", ErrorResponseDocument.CreateFromDiscriminatorValue},
};
return await RequestAdapter.SendAsync<PersonCollectionResponseDocument>(requestInfo, PersonCollectionResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false);
}
}
}
To work around this, we need to catch an exception to detect HTTP 304 is being returned:
var headerInspector = new HeadersInspectionHandlerOption
{
InspectResponseHeaders = true
};
PersonCollectionResponseDocument? getResponse1 = await client.Api.People.GetAsync(
configuration => configuration.Options.Add(headerInspector));
string eTag = headerInspector.ResponseHeaders["ETag"].Single();
try
{
PersonCollectionResponseDocument? getResponse2 = await client.Api.People.GetAsync(
configuration => configuration.Headers.Add("If-None-Match", eTag));
}
catch (ApiException exception) when (exception.ResponseStatusCode == (int)HttpStatusCode.NotModified)
{
Console.WriteLine("The HTTP response hasn't changed, so no response body was returned.");
}
This looks like a bug to me. In KiotaBuilder.cs
, I found the following line:
private static readonly HashSet<string> noContentStatusCodes = new(StringComparer.OrdinalIgnoreCase) { "201", "202", "204", "205" };
Should that just be changed to include 304?
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Metadata
Assignees
Type
Projects
Status
Done ✔️