@@ -43,19 +43,19 @@ protected virtual void SetClientCertificates(HttpWebRequest request, RequestData
43
43
protected virtual void SetServerCertificateValidationCallBackIfNeeded ( HttpWebRequest request , RequestData requestData )
44
44
{
45
45
var callback = requestData ? . ConnectionSettings ? . ServerCertificateValidationCallback ;
46
- #if ! __MonoCS__
46
+ #if ! __MonoCS__
47
47
//Only assign if one is defined on connection settings and a subclass has not already set one
48
48
if ( callback != null && request . ServerCertificateValidationCallback == null )
49
49
request . ServerCertificateValidationCallback = new RemoteCertificateValidationCallback ( callback ) ;
50
- #else
50
+ #else
51
51
if ( callback != null )
52
52
throw new Exception ( "Mono misses ServerCertificateValidationCallback on HttpWebRequest" ) ;
53
53
#endif
54
54
}
55
55
56
56
protected virtual HttpWebRequest CreateWebRequest ( RequestData requestData )
57
57
{
58
- var request = ( HttpWebRequest ) WebRequest . Create ( requestData . Uri ) ;
58
+ var request = ( HttpWebRequest ) WebRequest . Create ( requestData . Uri ) ;
59
59
60
60
request . Accept = requestData . Accept ;
61
61
request . ContentType = requestData . ContentType ;
@@ -76,7 +76,7 @@ protected virtual HttpWebRequest CreateWebRequest(RequestData requestData)
76
76
if ( requestData . Headers != null && requestData . Headers . HasKeys ( ) )
77
77
request . Headers . Add ( requestData . Headers ) ;
78
78
79
- var timeout = ( int ) requestData . RequestTimeout . TotalMilliseconds ;
79
+ var timeout = ( int ) requestData . RequestTimeout . TotalMilliseconds ;
80
80
request . Timeout = timeout ;
81
81
request . ReadWriteTimeout = timeout ;
82
82
@@ -101,7 +101,6 @@ protected virtual void AlterServicePoint(ServicePoint requestServicePoint, Reque
101
101
//this method only sets internal values and wont actually cause timers and such to be reset
102
102
//So it should be idempotent if called with the same parameters
103
103
requestServicePoint . SetTcpKeepAlive ( true , requestData . KeepAliveTime , requestData . KeepAliveInterval ) ;
104
-
105
104
}
106
105
107
106
protected virtual void SetProxyIfNeeded ( HttpWebRequest request , RequestData requestData )
@@ -161,8 +160,8 @@ public virtual ElasticsearchResponse<TReturn> Request<TReturn>(RequestData reque
161
160
//Either the stream or the response object needs to be closed but not both although it won't
162
161
//throw any errors if both are closed atleast one of them has to be Closed.
163
162
//Since we expose the stream we let closing the stream determining when to close the connection
164
- var response = ( HttpWebResponse ) request . GetResponse ( ) ;
165
- builder . StatusCode = ( int ) response . StatusCode ;
163
+ var response = ( HttpWebResponse ) request . GetResponse ( ) ;
164
+ builder . StatusCode = ( int ) response . StatusCode ;
166
165
builder . Stream = response . GetResponseStream ( ) ;
167
166
168
167
if ( response . SupportsHeaders && response . Headers . HasKeys ( ) && response . Headers . AllKeys . Contains ( "Warning" ) )
@@ -180,8 +179,17 @@ public virtual ElasticsearchResponse<TReturn> Request<TReturn>(RequestData reque
180
179
}
181
180
182
181
183
- private static RegisteredWaitHandle RegisterApmTaskTimeout ( IAsyncResult result , WebRequest request , RequestData requestData ) =>
184
- ThreadPool . RegisterWaitForSingleObject ( result . AsyncWaitHandle , TimeoutCallback , request , requestData . RequestTimeout , true ) ;
182
+ /// <summary>
183
+ /// Registers an APM async task cancellation on the threadpool
184
+ /// </summary>
185
+ /// <returns>An unregister action that can be used to remove the waithandle prematurely</returns>
186
+ private static Action RegisterApmTaskTimeout ( IAsyncResult result , WebRequest request , RequestData requestData )
187
+ {
188
+ var waitHandle = result . AsyncWaitHandle ;
189
+ var registeredWaitHandle =
190
+ ThreadPool . RegisterWaitForSingleObject ( waitHandle , TimeoutCallback , request , requestData . RequestTimeout , true ) ;
191
+ return ( ) => registeredWaitHandle ? . Unregister ( waitHandle ) ;
192
+ }
185
193
186
194
private static void TimeoutCallback ( object state , bool timedOut )
187
195
{
@@ -193,74 +201,65 @@ public virtual async Task<ElasticsearchResponse<TReturn>> RequestAsync<TReturn>(
193
201
CancellationToken cancellationToken ) where TReturn : class
194
202
{
195
203
var builder = new ResponseBuilder < TReturn > ( requestData , cancellationToken ) ;
196
- WaitHandle apmWaitHandle = null ;
197
- RegisteredWaitHandle apmTaskTimeout = null ;
204
+ Action unregisterWaitHandle = null ;
198
205
try
199
206
{
200
207
var data = requestData . PostData ;
201
208
var request = this . CreateHttpWebRequest ( requestData ) ;
202
209
using ( cancellationToken . Register ( ( ) => request . Abort ( ) ) )
203
210
{
204
211
if ( data != null )
205
- await PostRequestAsync ( requestData , cancellationToken , request , data ) ;
212
+ {
213
+ var apmGetRequestStreamTask = Task . Factory . FromAsync ( request . BeginGetRequestStream , request . EndGetRequestStream , null ) ;
214
+ unregisterWaitHandle = RegisterApmTaskTimeout ( apmGetRequestStreamTask , request , requestData ) ;
215
+
216
+ using ( var stream = await apmGetRequestStreamTask . ConfigureAwait ( false ) )
217
+ {
218
+ if ( requestData . HttpCompression )
219
+ using ( var zipStream = new GZipStream ( stream , CompressionMode . Compress ) )
220
+ await data . WriteAsync ( zipStream , requestData . ConnectionSettings , cancellationToken ) . ConfigureAwait ( false ) ;
221
+ else
222
+ await data . WriteAsync ( stream , requestData . ConnectionSettings , cancellationToken ) . ConfigureAwait ( false ) ;
223
+ }
224
+ unregisterWaitHandle ? . Invoke ( ) ;
225
+ }
206
226
requestData . MadeItToResponse = true ;
207
- //http://msdn.microsoft.com/en-us/library/system.net.httpwebresponse.getresponsestream.aspx
208
- //Either the stream or the response object needs to be closed but not both although it won't
209
- //throw any errors if both are closed atleast one of them has to be Closed.
210
- //Since we expose the stream we let closing the stream determining when to close the connection
211
-
212
- var apmGetResponseTask = Task . Factory . FromAsync ( request . BeginGetResponse , request . EndGetResponse , null ) ;
213
- apmWaitHandle = ( ( IAsyncResult ) apmGetResponseTask ) . AsyncWaitHandle ;
214
- apmTaskTimeout = RegisterApmTaskTimeout ( apmGetResponseTask , request , requestData ) ;
215
-
216
- var response = ( HttpWebResponse ) ( await apmGetResponseTask . ConfigureAwait ( false ) ) ;
217
- builder . StatusCode = ( int ) response . StatusCode ;
218
- builder . Stream = response . GetResponseStream ( ) ;
219
- if ( response . SupportsHeaders && response . Headers . HasKeys ( ) && response . Headers . AllKeys . Contains ( "Warning" ) )
220
- builder . DeprecationWarnings = response . Headers . GetValues ( "Warning" ) ;
221
- // https://github.com/elastic/elasticsearch-net/issues/2311
222
- // if stream is null call dispose on response instead.
223
- if ( builder . Stream == null || builder . Stream == Stream . Null ) response . Dispose ( ) ;
224
- if ( apmWaitHandle != null ) apmTaskTimeout ? . Unregister ( apmWaitHandle ) ;
227
+ //http://msdn.microsoft.com/en-us/library/system.net.httpwebresponse.getresponsestream.aspx
228
+ //Either the stream or the response object needs to be closed but not both although it won't
229
+ //throw any errors if both are closed atleast one of them has to be Closed.
230
+ //Since we expose the stream we let closing the stream determining when to close the connection
231
+
232
+ var apmGetResponseTask = Task . Factory . FromAsync ( request . BeginGetResponse , request . EndGetResponse , null ) ;
233
+ unregisterWaitHandle = RegisterApmTaskTimeout ( apmGetResponseTask , request , requestData ) ;
234
+
235
+ var response = ( HttpWebResponse ) ( await apmGetResponseTask . ConfigureAwait ( false ) ) ;
236
+ builder . StatusCode = ( int ) response . StatusCode ;
237
+ builder . Stream = response . GetResponseStream ( ) ;
238
+ if ( response . SupportsHeaders && response . Headers . HasKeys ( ) && response . Headers . AllKeys . Contains ( "Warning" ) )
239
+ builder . DeprecationWarnings = response . Headers . GetValues ( "Warning" ) ;
240
+ // https://github.com/elastic/elasticsearch-net/issues/2311
241
+ // if stream is null call dispose on response instead.
242
+ if ( builder . Stream == null || builder . Stream == Stream . Null ) response . Dispose ( ) ;
225
243
}
226
244
}
227
245
catch ( WebException e )
228
246
{
229
- if ( apmWaitHandle != null ) apmTaskTimeout ? . Unregister ( apmWaitHandle ) ;
230
247
HandleException ( builder , e ) ;
231
248
}
232
- catch
249
+ finally
233
250
{
234
- if ( apmWaitHandle != null ) apmTaskTimeout ? . Unregister ( apmWaitHandle ) ;
235
- throw ;
251
+ unregisterWaitHandle ? . Invoke ( ) ;
236
252
}
237
253
return await builder . ToResponseAsync ( ) . ConfigureAwait ( false ) ;
238
254
}
239
255
240
- private static async Task PostRequestAsync ( RequestData requestData , CancellationToken cancellationToken , HttpWebRequest request ,
241
- PostData < object > data )
242
- {
243
- var apmGetRequestStreamTask = Task . Factory . FromAsync ( request . BeginGetRequestStream , request . EndGetRequestStream , null ) ;
244
- var getRequestStreamCancellationHandle = RegisterApmTaskTimeout ( apmGetRequestStreamTask , request , requestData ) ;
245
-
246
- using ( var stream = await apmGetRequestStreamTask . ConfigureAwait ( false ) )
247
- {
248
- if ( requestData . HttpCompression )
249
- using ( var zipStream = new GZipStream ( stream , CompressionMode . Compress ) )
250
- await data . WriteAsync ( zipStream , requestData . ConnectionSettings , cancellationToken ) . ConfigureAwait ( false ) ;
251
- else
252
- await data . WriteAsync ( stream , requestData . ConnectionSettings , cancellationToken ) . ConfigureAwait ( false ) ;
253
- }
254
- getRequestStreamCancellationHandle . Unregister ( ( ( IAsyncResult ) apmGetRequestStreamTask ) . AsyncWaitHandle ) ;
255
- }
256
-
257
- private void HandleException < TReturn > ( ResponseBuilder < TReturn > builder , WebException exception )
256
+ private static void HandleException < TReturn > ( ResponseBuilder < TReturn > builder , WebException exception )
258
257
where TReturn : class
259
258
{
260
259
builder . Exception = exception ;
261
260
var response = exception . Response as HttpWebResponse ;
262
261
if ( response == null ) return ;
263
- builder . StatusCode = ( int ) response . StatusCode ;
262
+ builder . StatusCode = ( int ) response . StatusCode ;
264
263
builder . Stream = response . GetResponseStream ( ) ;
265
264
// https://github.com/elastic/elasticsearch-net/issues/2311
266
265
// if stream is null call dispose on response instead.
@@ -269,7 +268,9 @@ private void HandleException<TReturn>(ResponseBuilder<TReturn> builder, WebExcep
269
268
270
269
void IDisposable . Dispose ( ) => this . DisposeManagedResources ( ) ;
271
270
272
- protected virtual void DisposeManagedResources ( ) { }
271
+ protected virtual void DisposeManagedResources ( )
272
+ {
273
+ }
273
274
}
274
275
}
275
276
#endif
0 commit comments