Refit 6.0.x: Content-Length not set for PATCH requests
See original GitHub issueHi
It seems like the following issue is related to a slightly old issue i.e. #885 and probably #372
Description
I am consuming a third-party REST API using .NET 5/C# 9.0 and Refit version 6.0.24. The third-party system doesn’t support chunked encoding. When making a PATCH call the Transfer-Encoding: chunked
header is getting added, and the API returns with 400 status code.
The interface method looks like below:
[Patch("/states/{Id}"), Headers("Content-Type: application/json")]
Task<ApiResponse<State>> ChangeState([Body] StateControl stateControl, string id);
I have tried changing the [Body]
attribute to all possible documented values without any success
- [Body]
- [Body(true)]
- [Body(BodySerializationMethod.Default, true)]
- [Body(BodySerializationMethod.Serialized)]
- [Body(BodySerializationMethod.Serialized, true)]
Following is the request and response captured by Fiddler
Request
PATCH http://thidparty.api.com:5000/states/0 HTTP/1.1
Host: thidparty.api.com:5000
X-Correlation-ID: 3edcc52b-aec1-4a8c-b725-c646fc269e95
traceparent: 00-4f869cf85a015f4fae43466700c2a395-5effe2f12308e444-00
Transfer-Encoding: chunked
Content-Type: application/json
1C
{"state":"new","force":true}
0
Response
HTTP/1.1 400 BAD REQUEST
server: gunicorn/19.4.5
date: Mon, 01 Mar 2021 23:29:51 GMT
content-type: application/json
content-length: 92
x-sentry-id: 3b2b0bad862a4eed9d62e8e76c96a7f0
{"message": "The browser (or proxy) sent a request that this server could not understand."}
Expected behavior The expected behavior should be how it was in the version prior to 6.0.x. i.e. Content-Length header should be set. It works fine in version 5.2.4, without changing the [Body] attribute. Following is the request and response captured by Fiddler when using Refit version 5.2.4
Request
PATCH http://thidparty.api.com:5000/states/0 HTTP/1.1
Host: thidparty.api.com:5000
X-Correlation-ID: 3edcc52b-aec1-4a8c-b725-c646fc269e95
traceparent: 00-1b3b2ddae1c35c4f9ae2b6c6e7c72093-ce1d3605b1a6b241-00
Content-Length: 28
Content-Type: application/json
{"state":"new","force":true}
Response
Please note that 408 is the expected status code for this request 😃
HTTP/1.1 408 REQUEST TIMEOUT
server: gunicorn/19.4.5
date: Mon, 01 Mar 2021 18:01:03 GMT
content-type: application/json
content-length: 35
x-sentry-id: 1b4b324faff9412e831aeff453efbeb2
{"message": "State didn't change"}
Environment
- OS: Windows 10 Professional
- Version: Refit 6.0.x
- Working Version: Refit 5.2.4
Additional context I am using a workaround mentioned at #372 in a delegating handler before the request is sent like below and it works fine. However, it would be great if this issue can be fixed. I am happy to contribute if I can get some direction. It would probably be my first contribution ever 😃
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
if (request.Method == HttpMethod.Patch && request.Content != null)
{
var content = await request.Content.ReadAsStringAsync(cancellationToken);
request.Content = new StringContent(content, Encoding.UTF8, "application/json");
}
return await base.SendAsync(request, cancellationToken);
}
Issue Analytics
- State:
- Created 3 years ago
- Reactions:1
- Comments:18 (6 by maintainers)
This was helpful.
Just been struggling with Azure API Management cutting out the JSON content of my post body. Turns out that it was ignoring the content because the content-length header wasn’t being sent. Set buffered to true in the body attribute and it started working. [Body(BodySerializationMethod.Serialized, true)]
@lotz Thanks for the fix. I presume that it would work with the methods that return Task<<T>> as I mentioned in this bug. I’ll give it a go and will let you know.