-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Fix sending GET and HEAD messages #3101
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
…of a HEAD or GET request. HttpClient does not accept a content at all when the request is a HEAD or a GET. Even an empty ByteArray is not allowed. A ProtocolViolationException will be thrown. The 'Ping' functionality can not be activated without this fix because that is based on a HEAD message.
|
Could you provide some more details for this change @BastiaanLouis ?
Have you experienced exceptions thrown? I ask because we run integration tests on both Windows and Linux (see the Windows CI and Linux CI build links) and have not seen |
|
What versions of |
|
Some additional info. I'm running on a windows 2012 server, on .NET framework 4.7 The following package version are used:
Below a simple representation of the code that is executed by Elasticsearch.NET. |
…tails use it in a safe wat
…is/elasticsearch-net into fix/contentbody-verb
|
@russcam @Mpdreamz When you execute the following code (the value of the uri doesn't matter) within a NET 4.7 console application, without the proposed commits, the resulting responsePing contained an error that does not contain the original exception (for which this PR is opened in the first place). Fixing the handling of a bad response in the RequestPipeline, makes sure the internal exception (ProtocolViolationException) will be visible in the responsePing object. The fix in HttpConnection that I've already made, will make sure the ProtocalViolationException won't occur anymore. Of course when executing including the fixes, the uri does matter. |
|
I saw this issue with integration tests against 6.1.2 |
|
I think we may have never seen this before because |
|
How do you suggest to fix this issue @russcam ? Because we are building to .net framework 4.6.x/4.7 the net46 assembly from the package will be picked. Is the solution in the pull request the correct way of fixing it? |
|
Apologies for not getting back to you sooner @BastiaanLouis, I've currently been travelling. I think in the case of any request where there is not request data written to the request stream, we can forgo setting content and the Content-Type header i.e. inside var data = requestData.PostData;
if (data != null)
{
var stream = requestData.MemoryStreamFactory.Create();
requestMessage.Content = new StreamContent(stream);
requestMessage.Content.Headers.ContentType = new MediaTypeHeaderValue(requestData.RequestMimeType);
if (requestData.HttpCompression)
{
requestMessage.Content.Headers.Add("Content-Encoding", "gzip");
requestMessage.Headers.AcceptEncoding.Add(new StringWithQualityHeaderValue("gzip"));
requestMessage.Headers.AcceptEncoding.Add(new StringWithQualityHeaderValue("deflate"));
using (var zipStream = new GZipStream(stream, CompressionMode.Compress, true))
data.Write(zipStream, requestData.ConnectionSettings);
}
else
data.Write(stream, requestData.ConnectionSettings);
stream.Position = 0;
}
return requestMessage; |
|
Nice @russcam mentioned cleaning up method |
|
Thanks @BastiaanLouis , will take a look now. The empty body was required in order to set a Content-Type header. In a much earlier version of Elasticsearch, the Content-Type header was incorrectly used for both the inward content type and the outward content type; the latter was corrected to use the Accept header. |
|
Great! |
|
This looks good to me, thanks for your efforts on this one @BastiaanLouis 👍 |
* The Http specs says that the body can be ignored by the host in case of a HEAD or GET request. HttpClient does not accept a content at all when the request is a HEAD or a GET. Even an empty ByteArray is not allowed. A ProtocolViolationException will be thrown. The 'Ping' functionality can not be activated without this fix because that is based on a HEAD message. * callDetails can be null so just like the rest of the usages of callDetails use it in a safe wat * Simplify handling empty data
* The Http specs says that the body can be ignored by the host in case of a HEAD or GET request. HttpClient does not accept a content at all when the request is a HEAD or a GET. Even an empty ByteArray is not allowed. A ProtocolViolationException will be thrown. The 'Ping' functionality can not be activated without this fix because that is based on a HEAD message. * callDetails can be null so just like the rest of the usages of callDetails use it in a safe wat * Simplify handling empty data Conflicts: src/Elasticsearch.Net/Connection/HttpConnection-CoreFx.cs src/Elasticsearch.Net/Transport/Pipeline/RequestPipeline.cs
|
ported to |
|
Great, thx! Looking forward to use the new package. |
|
Thanks @Mpdreamz for picking up my slack on this. And apologies @BastiaanLouis for the delay here; this PR got caught up in my moving house and annual leave 😞 |
|
@BastiaanLouis We were hoping to get a new release out today, but backporting changes from |
When sending a HEAD or GET message, the message does not contain any content. The used HttpClient class accepts no content at all using these type of verbs. The current implementation that creates an empty BytesArrayContent actually creates a message that will not be send by the HttpClient. A ProtocolViolationException will be thrown (see https://github.com/Microsoft/referencesource/blob/master/System/net/System/Net/HttpWebRequest.cs, private void CheckProtocol(bool onRequestStream)).
This small fixes leaves the Content of the requestMessage null, only for HEAD and GET messages for which no postdata is offered.
Unfortunately there are no tests available that I can update to validate the change. To verify the bug and it's fix, I've been using the StaticConnectionPool (actually through Serilog).