Skip to content

Commit abf05f2

Browse files
committed
Fixed some issues with the Accept headers sent over the wire.
Changed the HttpClient to be single instance, instead of transient with every request.
1 parent b4bb009 commit abf05f2

File tree

1 file changed

+72
-28
lines changed

1 file changed

+72
-28
lines changed

src/Connections/Elasticsearch.Net.Connection.HttpClient/ElasticsearchHttpClient.cs

Lines changed: 72 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,9 @@ namespace Elasticsearch.Net.Connection.HttpClient
1010
/// <summary>
1111
/// IConnection implemented using <see cref="System.Net.Http.HttpClient"/>
1212
/// </summary>
13-
public class ElasticsearchHttpClient : IConnection
13+
public class ElasticsearchHttpClient : IConnection, IDisposable
1414
{
1515
private readonly IConnectionConfigurationValues _settings;
16-
private readonly HttpClientHandler _innerHandler;
1716

1817
static ElasticsearchHttpClient()
1918
{
@@ -33,20 +32,24 @@ static ElasticsearchHttpClient()
3332
public ElasticsearchHttpClient(IConnectionConfigurationValues settings, HttpClientHandler handler = null)
3433
{
3534
_settings = settings;
36-
37-
_innerHandler = handler ?? new WebRequestHandler();
38-
3935
DefaultContentType = "application/json";
4036

41-
if (_innerHandler.SupportsProxy && !string.IsNullOrWhiteSpace(_settings.ProxyAddress))
37+
var innerHandler = handler ?? new WebRequestHandler();
38+
39+
if (innerHandler.SupportsProxy && !string.IsNullOrWhiteSpace(_settings.ProxyAddress))
4240
{
43-
_innerHandler.Proxy = new WebProxy(_settings.ProxyAddress)
41+
innerHandler.Proxy = new WebProxy(_settings.ProxyAddress)
4442
{
4543
Credentials = new NetworkCredential(_settings.ProxyUsername, _settings.ProxyPassword),
4644
};
4745

48-
_innerHandler.UseProxy = true;
46+
innerHandler.UseProxy = true;
4947
}
48+
49+
Client = new System.Net.Http.HttpClient(new ElasticsearchHttpMessageHandler(innerHandler), false)
50+
{
51+
Timeout = TimeSpan.FromMilliseconds(_settings.Timeout)
52+
};
5053
}
5154

5255
/// <summary>
@@ -55,6 +58,18 @@ public ElasticsearchHttpClient(IConnectionConfigurationValues settings, HttpClie
5558
/// <value>The default type of the content.</value>
5659
public string DefaultContentType { get; set; }
5760

61+
/// <summary>
62+
/// Gets a value indicating whether this instance is disposed.
63+
/// </summary>
64+
/// <value><c>true</c> if this instance is disposed; otherwise, <c>false</c>.</value>
65+
public bool IsDisposed { get; private set; }
66+
67+
/// <summary>
68+
/// Gets the client.
69+
/// </summary>
70+
/// <value>The client.</value>
71+
public System.Net.Http.HttpClient Client { get; private set; }
72+
5873
/// <summary>
5974
/// Wraps the DoRequest to run synchronously
6075
/// </summary>
@@ -65,6 +80,8 @@ public ElasticsearchHttpClient(IConnectionConfigurationValues settings, HttpClie
6580
/// <returns>ElasticsearchResponse&lt;Stream&gt;.</returns>
6681
public ElasticsearchResponse<Stream> DoRequestSync(HttpMethod method, Uri uri, byte[] data = null, IRequestConnectionConfiguration requestSpecificConfig = null)
6782
{
83+
ThrowIfDisposed();
84+
6885
var requestTask = DoRequest(method, uri, data, requestSpecificConfig);
6986

7087
try
@@ -92,6 +109,8 @@ public ElasticsearchResponse<Stream> DoRequestSync(HttpMethod method, Uri uri, b
92109
/// <returns>Task&lt;ElasticsearchResponse&lt;Stream&gt;&gt;.</returns>
93110
public async Task<ElasticsearchResponse<Stream>> DoRequest(HttpMethod method, Uri uri, byte[] data = null, IRequestConnectionConfiguration requestSpecificConfig = null)
94111
{
112+
ThrowIfDisposed();
113+
95114
try
96115
{
97116
var request = new HttpRequestMessage(method, uri);
@@ -102,11 +121,11 @@ public async Task<ElasticsearchResponse<Stream>> DoRequest(HttpMethod method, Ur
102121

103122
if (requestSpecificConfig != null && !string.IsNullOrWhiteSpace(requestSpecificConfig.AcceptsContentType))
104123
{
105-
request.Content.Headers.Allow.Add(requestSpecificConfig.AcceptsContentType);
124+
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(requestSpecificConfig.AcceptsContentType));
106125
}
107126
else if (!string.IsNullOrWhiteSpace(DefaultContentType))
108127
{
109-
request.Content.Headers.Allow.Add(DefaultContentType);
128+
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(DefaultContentType));
110129
}
111130

112131
if (!string.IsNullOrWhiteSpace(DefaultContentType))
@@ -115,27 +134,16 @@ public async Task<ElasticsearchResponse<Stream>> DoRequest(HttpMethod method, Ur
115134
}
116135
}
117136

118-
using (var client = new System.Net.Http.HttpClient(new ElasticsearchHttpMessageHandler(_innerHandler), false))
119-
{
120-
if (requestSpecificConfig != null && requestSpecificConfig.TimeoutRequest.HasValue)
121-
{
122-
client.Timeout = TimeSpan.FromMilliseconds(requestSpecificConfig.TimeoutRequest.Value);
123-
}
124-
else
125-
{
126-
client.Timeout = TimeSpan.FromMilliseconds(_settings.Timeout);
127-
}
137+
var response = await Client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
128138

129-
var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
139+
if (method == HttpMethod.Head || response.Content == null || !response.Content.Headers.ContentLength.HasValue || response.Content.Headers.ContentLength.Value <= 0)
140+
{
141+
return ElasticsearchResponse<Stream>.Create(_settings, (int)response.StatusCode, method.ToString().ToLowerInvariant(), uri.ToString(), data);
142+
}
130143

131-
if (method == HttpMethod.Head || response.Content == null || !response.Content.Headers.ContentLength.HasValue || response.Content.Headers.ContentLength.Value <= 0)
132-
{
133-
return ElasticsearchResponse<Stream>.Create(_settings, (int) response.StatusCode, method.ToString().ToLowerInvariant(), uri.ToString(), data);
134-
}
144+
var responseStream = await response.Content.ReadAsStreamAsync();
145+
return ElasticsearchResponse<Stream>.Create(_settings, (int)response.StatusCode, method.ToString().ToLowerInvariant(), uri.ToString(), data, responseStream);
135146

136-
var responseStream = await response.Content.ReadAsStreamAsync();
137-
return ElasticsearchResponse<Stream>.Create(_settings, (int) response.StatusCode, method.ToString().ToLowerInvariant(), uri.ToString(), data, responseStream);
138-
}
139147
}
140148
catch (Exception ex)
141149
{
@@ -202,5 +210,41 @@ ElasticsearchResponse<Stream> IConnection.DeleteSync(Uri uri, byte[] data, IRequ
202210
{
203211
return DoRequestSync(HttpMethod.Delete, uri, data, requestSpecificConfig);
204212
}
213+
214+
private void ThrowIfDisposed()
215+
{
216+
if (IsDisposed)
217+
{
218+
throw new ObjectDisposedException(GetType().Name);
219+
}
220+
}
221+
222+
public void Dispose()
223+
{
224+
Dispose(true);
225+
GC.SuppressFinalize(this);
226+
}
227+
228+
~ElasticsearchHttpClient()
229+
{
230+
Dispose(false);
231+
}
232+
233+
protected virtual void Dispose(bool disposing)
234+
{
235+
if (IsDisposed)
236+
return;
237+
238+
if (disposing)
239+
{
240+
if (Client != null)
241+
{
242+
Client.Dispose();
243+
Client = null;
244+
}
245+
}
246+
247+
IsDisposed = true;
248+
}
205249
}
206250
}

0 commit comments

Comments
 (0)