odata.net icon indicating copy to clipboard operation
odata.net copied to clipboard

Header Accept cannot ends with semicolon

Open ycymio opened this issue 1 year ago • 2 comments

When the Header uses semicolon as the end character, it throws the exception:

Microsoft.OData.ODataException: An error occurred when parsing the HTTP header 'Prefer'. The header value 'odata.track-changes;odata.maxpagesize=2;' is incorrect at position '40' because the header value should not end with the separator ';'. at Microsoft.OData.HttpHeaderValueLexer.HttpHeaderSeparator.ReadNext() at Microsoft.OData.HttpHeaderValueLexer.ReadHttpHeaderValueElement(HttpHeaderValueLexer& lexer) at Microsoft.OData.HttpHeaderValueLexer.ToHttpHeaderValue() at Microsoft.OData.ODataPreferenceHeader.ParsePreferences() at Microsoft.OData.ODataPreferenceHeader.get_Preferences() at Microsoft.OData.ODataPreferenceHeader.Get(String preferenceName) at Microsoft.OData.ODataPreferenceHeader.get_AnnotationFilter() at Microsoft.AspNetCore.OData.Formatter.ODataOutputFormatterHelper.WriteToStreamAsync(Type type, Object value, IEdmModel model, ODataVersion version, Uri baseAddress, MediaTypeHeaderValue contentType, HttpRequest request, IHeaderDictionary requestHeaders, IODataSerializerProvider serializerProvider) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeResultAsync>g__Logged|22_0(ResourceInvoker invoker, IActionResult result) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResultFilterAsync>g__Awaited|30_0[TFilter,TFilterAsync](ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed context) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext[TFilter,TFilterAsync](State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters()\r\n--- End of stack trace from previous location --- at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|20_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker) at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)

Any reason why it is restricted like this? Is there any document saying OData header has this limitation?

ycymio avatar Jan 03 '24 08:01 ycymio

It seems by design, we cannot have a separator at the last token in a header. Separations include = , and ; Code throwing the exception https://github.com/OData/odata.net/blob/67365d65e0a98199820c076076e2e5978089d3f8/src/Microsoft.OData.Core/HttpHeaderValueLexer.cs#L556C90-L556C90

Tests https://github.com/OData/odata.net/blob/67365d65e0a98199820c076076e2e5978089d3f8/test/FunctionalTests/Microsoft.OData.Core.Tests/HttpHeaderValueLexerTests.cs#L162 https://github.com/OData/odata.net/blob/67365d65e0a98199820c076076e2e5978089d3f8/test/FunctionalTests/Microsoft.OData.Core.Tests/HttpHeaderValueLexerTests.cs#L171 https://github.com/OData/odata.net/blob/67365d65e0a98199820c076076e2e5978089d3f8/test/FunctionalTests/Microsoft.OData.Core.Tests/HttpHeaderValueLexerTests.cs#L180

KenitoInc avatar Jan 09 '24 14:01 KenitoInc

Potential fix; Ignore comma and semi colon at the end.

KenitoInc avatar Jan 09 '24 17:01 KenitoInc