Skip to content

Commit a23df91

Browse files
authored
[dotnet] Use new implementation of HttpClient in DriverService for communication (#11143)
* Use new implementation of HttpClient * Update SafariDriverService.cs
1 parent 38d9776 commit a23df91

File tree

2 files changed

+74
-68
lines changed

2 files changed

+74
-68
lines changed

dotnet/src/webdriver/DriverService.cs

Lines changed: 39 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@
2121
using System.Globalization;
2222
using System.IO;
2323
using System.Net;
24-
using System.Security.Permissions;
24+
using System.Net.Http;
25+
using System.Threading.Tasks;
2526
using OpenQA.Selenium.Internal;
2627
using OpenQA.Selenium.Remote;
2728

@@ -235,20 +236,23 @@ protected virtual bool IsInitialized
235236
bool isInitialized = false;
236237
try
237238
{
238-
Uri serviceHealthUri = new Uri(this.ServiceUrl, new Uri(DriverCommand.Status, UriKind.Relative));
239-
HttpWebRequest request = HttpWebRequest.Create(serviceHealthUri) as HttpWebRequest;
240-
request.KeepAlive = false;
241-
request.Timeout = 5000;
242-
HttpWebResponse response = request.GetResponse() as HttpWebResponse;
243-
244-
// Checking the response from the 'status' end point. Note that we are simply checking
245-
// that the HTTP status returned is a 200 status, and that the resposne has the correct
246-
// Content-Type header. A more sophisticated check would parse the JSON response and
247-
// validate its values. At the moment we do not do this more sophisticated check.
248-
isInitialized = response.StatusCode == HttpStatusCode.OK && response.ContentType.StartsWith("application/json", StringComparison.OrdinalIgnoreCase);
249-
response.Close();
239+
using (var httpClient = new HttpClient())
240+
{
241+
httpClient.DefaultRequestHeaders.ConnectionClose = true;
242+
httpClient.Timeout = TimeSpan.FromSeconds(5);
243+
244+
Uri serviceHealthUri = new Uri(this.ServiceUrl, new Uri(DriverCommand.Status, UriKind.Relative));
245+
using (var response = Task.Run(async () => await httpClient.GetAsync(serviceHealthUri)).GetAwaiter().GetResult())
246+
{
247+
// Checking the response from the 'status' end point. Note that we are simply checking
248+
// that the HTTP status returned is a 200 status, and that the resposne has the correct
249+
// Content-Type header. A more sophisticated check would parse the JSON response and
250+
// validate its values. At the moment we do not do this more sophisticated check.
251+
isInitialized = response.StatusCode == HttpStatusCode.OK && response.Content.Headers.ContentType.MediaType.StartsWith("application/json", StringComparison.OrdinalIgnoreCase);
252+
}
253+
}
250254
}
251-
catch (WebException ex)
255+
catch (Exception ex) when (ex is HttpRequestException || ex is TaskCanceledException)
252256
{
253257
Console.WriteLine(ex.Message);
254258
}
@@ -394,23 +398,29 @@ private void Stop()
394398
{
395399
Uri shutdownUrl = new Uri(this.ServiceUrl, "/shutdown");
396400
DateTime timeout = DateTime.Now.Add(this.TerminationTimeout);
397-
while (this.IsRunning && DateTime.Now < timeout)
401+
using (var httpClient = new HttpClient())
398402
{
399-
try
400-
{
401-
// Issue the shutdown HTTP request, then wait a short while for
402-
// the process to have exited. If the process hasn't yet exited,
403-
// we'll retry. We wait for exit here, since catching the exception
404-
// for a failed HTTP request due to a closed socket is particularly
405-
// expensive.
406-
HttpWebRequest request = HttpWebRequest.Create(shutdownUrl) as HttpWebRequest;
407-
request.KeepAlive = false;
408-
HttpWebResponse response = request.GetResponse() as HttpWebResponse;
409-
response.Close();
410-
this.driverServiceProcess.WaitForExit(3000);
411-
}
412-
catch (WebException)
403+
httpClient.DefaultRequestHeaders.ConnectionClose = true;
404+
405+
while (this.IsRunning && DateTime.Now < timeout)
413406
{
407+
try
408+
{
409+
// Issue the shutdown HTTP request, then wait a short while for
410+
// the process to have exited. If the process hasn't yet exited,
411+
// we'll retry. We wait for exit here, since catching the exception
412+
// for a failed HTTP request due to a closed socket is particularly
413+
// expensive.
414+
using (var response = Task.Run(async () => await httpClient.GetAsync(shutdownUrl)).GetAwaiter().GetResult())
415+
{
416+
417+
}
418+
419+
this.driverServiceProcess.WaitForExit(3000);
420+
}
421+
catch (Exception ex) when (ex is HttpRequestException || ex is TimeoutException)
422+
{
423+
}
414424
}
415425
}
416426
}

dotnet/src/webdriver/Safari/SafariDriverService.cs

Lines changed: 35 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@
1818

1919
using System;
2020
using System.Net;
21+
using System.Net.Http;
2122
using System.Text;
23+
using System.Threading.Tasks;
2224
using OpenQA.Selenium.Internal;
2325

2426
namespace OpenQA.Selenium.Safari
@@ -110,47 +112,41 @@ protected override bool IsInitialized
110112
get
111113
{
112114
bool isInitialized = false;
113-
try
114-
{
115-
// Since Firefox driver won't implement the /session end point (because
116-
// the W3C spec working group stupidly decided that it isn't necessary),
117-
// we'll attempt to poll for a different URL which has no side effects.
118-
// We've chosen to poll on the "quit" URL, passing in a nonexistent
119-
// session id.
120-
Uri serviceHealthUri = new Uri(this.ServiceUrl, new Uri("/session/FakeSessionIdForPollingPurposes", UriKind.Relative));
121-
HttpWebRequest request = HttpWebRequest.Create(serviceHealthUri) as HttpWebRequest;
122-
request.KeepAlive = false;
123-
request.Timeout = 5000;
124-
request.Method = "DELETE";
125-
HttpWebResponse response = request.GetResponse() as HttpWebResponse;
126-
127-
// Checking the response from deleting a nonexistent session. Note that we are simply
128-
// checking that the HTTP status returned is a 200 status, and that the resposne has
129-
// the correct Content-Type header. A more sophisticated check would parse the JSON
130-
// response and validate its values. At the moment we do not do this more sophisticated
131-
// check.
132-
isInitialized = response.StatusCode == HttpStatusCode.OK && response.ContentType.StartsWith("application/json", StringComparison.OrdinalIgnoreCase);
133-
response.Close();
134-
}
135-
catch (WebException ex)
115+
116+
Uri serviceHealthUri = new Uri(this.ServiceUrl, new Uri("/session/FakeSessionIdForPollingPurposes", UriKind.Relative));
117+
118+
// Since Firefox driver won't implement the /session end point (because
119+
// the W3C spec working group stupidly decided that it isn't necessary),
120+
// we'll attempt to poll for a different URL which has no side effects.
121+
// We've chosen to poll on the "quit" URL, passing in a nonexistent
122+
// session id.
123+
using (var httpClient = new HttpClient())
136124
{
137-
// Because the Firefox driver (incorrectly) does not allow quit on a
138-
// nonexistent session to succeed, this will throw a WebException,
139-
// which means we're reduced to using exception handling for flow control.
140-
// This situation is highly undesirable, and in fact is a horrible code
141-
// smell, but the implementation leaves us no choice. So we will check for
142-
// the known response code and content type header, just like we would for
143-
// the success case. Either way, a valid HTTP response instead of a socket
144-
// error would tell us that the HTTP server is responding to requests, which
145-
// is really what we want anyway.
146-
HttpWebResponse errorResponse = ex.Response as HttpWebResponse;
147-
if (errorResponse != null)
148-
{
149-
isInitialized = (errorResponse.StatusCode == HttpStatusCode.InternalServerError && errorResponse.ContentType.StartsWith("application/json", StringComparison.OrdinalIgnoreCase)) || (errorResponse.StatusCode == HttpStatusCode.NotFound);
150-
}
151-
else
125+
httpClient.DefaultRequestHeaders.ConnectionClose = true;
126+
httpClient.Timeout = TimeSpan.FromSeconds(5);
127+
128+
using (var httpRequest = new HttpRequestMessage(HttpMethod.Delete, serviceHealthUri))
152129
{
153-
Console.WriteLine(ex.Message);
130+
try
131+
{
132+
using (var httpResponse = Task.Run(async () => await httpClient.SendAsync(httpRequest)).GetAwaiter().GetResult())
133+
{
134+
isInitialized = (httpResponse.StatusCode == HttpStatusCode.OK
135+
|| httpResponse.StatusCode == HttpStatusCode.InternalServerError
136+
|| httpResponse.StatusCode == HttpStatusCode.NotFound)
137+
&& httpResponse.Content.Headers.ContentType.MediaType.StartsWith("application/json", StringComparison.OrdinalIgnoreCase);
138+
}
139+
}
140+
141+
// Checking the response from deleting a nonexistent session. Note that we are simply
142+
// checking that the HTTP status returned is a 200 status, and that the resposne has
143+
// the correct Content-Type header. A more sophisticated check would parse the JSON
144+
// response and validate its values. At the moment we do not do this more sophisticated
145+
// check.
146+
catch (Exception ex) when (ex is HttpRequestException || ex is TaskCanceledException)
147+
{
148+
Console.WriteLine(ex);
149+
}
154150
}
155151
}
156152

0 commit comments

Comments
 (0)