Skip to content

Commit cef8da1

Browse files
committed
[dotnet] Fully annotate nullability on HttpCommandExecutor
1 parent 48ba3a1 commit cef8da1

File tree

1 file changed

+52
-42
lines changed

1 file changed

+52
-42
lines changed

dotnet/src/webdriver/Remote/HttpCommandExecutor.cs

Lines changed: 52 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
using System.Threading;
3131
using System.Threading.Tasks;
3232

33+
#nullable enable
34+
3335
namespace OpenQA.Selenium.Remote
3436
{
3537
/// <summary>
@@ -47,7 +49,8 @@ public class HttpCommandExecutor : ICommandExecutor
4749
private readonly TimeSpan serverResponseTimeout;
4850
private bool isDisposed;
4951
private CommandInfoRepository commandInfoRepository = new W3CWireProtocolCommandInfoRepository();
50-
private HttpClient client;
52+
private HttpClient? client;
53+
private readonly object _createClientLock = new();
5154

5255
private static readonly ILogger _logger = Log.GetLogger<HttpCommandExecutor>();
5356

@@ -56,6 +59,7 @@ public class HttpCommandExecutor : ICommandExecutor
5659
/// </summary>
5760
/// <param name="addressOfRemoteServer">Address of the WebDriver Server</param>
5861
/// <param name="timeout">The timeout within which the server must respond.</param>
62+
/// <exception cref="ArgumentNullException">If <paramref name="addressOfRemoteServer"/> is <see langword="null"/>.</exception>
5963
public HttpCommandExecutor(Uri addressOfRemoteServer, TimeSpan timeout)
6064
: this(addressOfRemoteServer, timeout, true)
6165
{
@@ -91,14 +95,14 @@ public HttpCommandExecutor(Uri addressOfRemoteServer, TimeSpan timeout, bool ena
9195
/// Occurs when the <see cref="HttpCommandExecutor"/> is sending an HTTP
9296
/// request to the remote end WebDriver implementation.
9397
/// </summary>
94-
public event EventHandler<SendingRemoteHttpRequestEventArgs> SendingRemoteHttpRequest;
98+
public event EventHandler<SendingRemoteHttpRequestEventArgs>? SendingRemoteHttpRequest;
9599

96100
/// <summary>
97101
/// Gets or sets an <see cref="IWebProxy"/> object to be used to proxy requests
98102
/// between this <see cref="HttpCommandExecutor"/> and the remote end WebDriver
99103
/// implementation.
100104
/// </summary>
101-
public IWebProxy Proxy { get; set; }
105+
public IWebProxy? Proxy { get; set; }
102106

103107
/// <summary>
104108
/// Gets or sets a value indicating whether keep-alive is enabled for HTTP
@@ -167,17 +171,12 @@ public virtual async Task<Response> ExecuteAsync(Command commandToExecute)
167171
_logger.Debug($"Executing command: {commandToExecute}");
168172
}
169173

170-
HttpCommandInfo info = this.commandInfoRepository.GetCommandInfo<HttpCommandInfo>(commandToExecute.Name);
174+
HttpCommandInfo? info = this.commandInfoRepository.GetCommandInfo<HttpCommandInfo>(commandToExecute.Name);
171175
if (info == null)
172176
{
173177
throw new NotImplementedException(string.Format("The command you are attempting to execute, {0}, does not exist in the protocol dialect used by the remote end.", commandToExecute.Name));
174178
}
175179

176-
if (this.client == null)
177-
{
178-
this.CreateHttpClient();
179-
}
180-
181180
HttpRequestInfo requestInfo = new HttpRequestInfo(this.remoteServerUri, commandToExecute, info);
182181
HttpResponseInfo responseInfo;
183182
try
@@ -216,42 +215,55 @@ protected virtual void OnSendingRemoteHttpRequest(SendingRemoteHttpRequestEventA
216215
throw new ArgumentNullException(nameof(eventArgs), "eventArgs must not be null");
217216
}
218217

219-
if (this.SendingRemoteHttpRequest != null)
220-
{
221-
this.SendingRemoteHttpRequest(this, eventArgs);
222-
}
218+
this.SendingRemoteHttpRequest?.Invoke(this, eventArgs);
223219
}
224220

225-
private void CreateHttpClient()
221+
private HttpClient Client
226222
{
227-
HttpClientHandler httpClientHandler = new HttpClientHandler();
228-
string userInfo = this.remoteServerUri.UserInfo;
229-
if (!string.IsNullOrEmpty(userInfo) && userInfo.Contains(":"))
230-
{
231-
string[] userInfoComponents = this.remoteServerUri.UserInfo.Split(new char[] { ':' }, 2);
232-
httpClientHandler.Credentials = new NetworkCredential(userInfoComponents[0], userInfoComponents[1]);
233-
httpClientHandler.PreAuthenticate = true;
234-
}
235-
236-
httpClientHandler.Proxy = this.Proxy;
237-
238-
HttpMessageHandler handler = httpClientHandler;
239-
240-
if (_logger.IsEnabled(LogEventLevel.Trace))
223+
get
241224
{
242-
handler = new DiagnosticsHttpHandler(httpClientHandler, _logger);
243-
}
225+
if (this.client is null)
226+
{
227+
lock (_createClientLock)
228+
{
229+
if (this.client is null)
230+
{
231+
HttpClientHandler httpClientHandler = new HttpClientHandler();
232+
string userInfo = this.remoteServerUri.UserInfo;
233+
if (!string.IsNullOrEmpty(userInfo) && userInfo.Contains(":"))
234+
{
235+
string[] userInfoComponents = this.remoteServerUri.UserInfo.Split(new char[] { ':' }, 2);
236+
httpClientHandler.Credentials = new NetworkCredential(userInfoComponents[0], userInfoComponents[1]);
237+
httpClientHandler.PreAuthenticate = true;
238+
}
239+
240+
httpClientHandler.Proxy = this.Proxy;
241+
242+
HttpMessageHandler handler = httpClientHandler;
243+
244+
if (_logger.IsEnabled(LogEventLevel.Trace))
245+
{
246+
handler = new DiagnosticsHttpHandler(httpClientHandler, _logger);
247+
}
248+
249+
var client = new HttpClient(handler);
250+
client.DefaultRequestHeaders.UserAgent.ParseAdd(this.UserAgent);
251+
client.DefaultRequestHeaders.Accept.ParseAdd(RequestAcceptHeader);
252+
client.DefaultRequestHeaders.ExpectContinue = false;
253+
if (!this.IsKeepAliveEnabled)
254+
{
255+
client.DefaultRequestHeaders.Connection.ParseAdd("close");
256+
}
257+
258+
client.Timeout = this.serverResponseTimeout;
259+
260+
this.client = client;
261+
}
262+
}
263+
}
244264

245-
this.client = new HttpClient(handler);
246-
this.client.DefaultRequestHeaders.UserAgent.ParseAdd(this.UserAgent);
247-
this.client.DefaultRequestHeaders.Accept.ParseAdd(RequestAcceptHeader);
248-
this.client.DefaultRequestHeaders.ExpectContinue = false;
249-
if (!this.IsKeepAliveEnabled)
250-
{
251-
this.client.DefaultRequestHeaders.Connection.ParseAdd("close");
265+
return this.client;
252266
}
253-
254-
this.client.Timeout = this.serverResponseTimeout;
255267
}
256268

257269
private async Task<HttpResponseInfo> MakeHttpRequest(HttpRequestInfo requestInfo)
@@ -288,7 +300,7 @@ private async Task<HttpResponseInfo> MakeHttpRequest(HttpRequestInfo requestInfo
288300
requestMessage.Content.Headers.ContentType = contentTypeHeader;
289301
}
290302

291-
using (HttpResponseMessage responseMessage = await this.client.SendAsync(requestMessage).ConfigureAwait(false))
303+
using (HttpResponseMessage responseMessage = await this.Client.SendAsync(requestMessage).ConfigureAwait(false))
292304
{
293305
var responseBody = await responseMessage.Content.ReadAsStringAsync().ConfigureAwait(false);
294306
var responseContentType = responseMessage.Content.Headers.ContentType?.ToString();
@@ -331,8 +343,6 @@ private Response CreateResponse(HttpResponseInfo responseInfo)
331343
return response;
332344
}
333345

334-
#nullable enable
335-
336346
/// <summary>
337347
/// Releases all resources used by the <see cref="HttpCommandExecutor"/>.
338348
/// </summary>

0 commit comments

Comments
 (0)