Skip to content
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

[dotnet] Handle unsuccessful http requests properly #10807

Merged
merged 6 commits into from
Jul 13, 2022
Merged

[dotnet] Handle unsuccessful http requests properly #10807

merged 6 commits into from
Jul 13, 2022

Conversation

nvborisenko
Copy link
Member

@nvborisenko nvborisenko commented Jun 24, 2022

  • Check http status code
  • Removed code which is never executed

I didn't verify whether the solution is still compiling without errors, I wrote this code in notepad.

Fixes #10805

@titusfortner
Copy link
Member

Thanks for the PR.

I'm still learning the .NET classes. Why can't that code you deleted be executed? Thanks.

@nvborisenko
Copy link
Member Author

In version 4 selenium was migrated from WebRequest to new HttpClient, what is good. But HttpClient works slightly differently.

For instance timeout exception now looks like this:
in .net 6

Unhandled exception. System.Threading.Tasks.TaskCanceledException: The request was canceled due to the configured HttpClient.Timeout of 0.001 seconds elapsing.
 ---> System.TimeoutException: A task was canceled.
 ---> System.Threading.Tasks.TaskCanceledException: A task was canceled.
   at System.Threading.Tasks.TaskCompletionSourceWithCancellation`1.WaitWithCancellation(CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.GetHttp11ConnectionAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.SendWithVersionDetectionAndRetryAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken)
   at System.Net.Http.HttpMessageHandlerStage.Send(HttpRequestMessage request, CancellationToken cancellationToken)
   at System.Net.Http.DiagnosticsHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)

in .net framework 4.8

Unhandled Exception: System.Threading.Tasks.TaskCanceledException: A task was canceled.
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)

Or if cannot connect to the server:
in .net 6

Unhandled exception. System.Net.Http.HttpRequestException: No such host is known. (werkjhwberkjbwkerwe876.com:443)
 ---> System.Net.Sockets.SocketException (11001): No such host is known.
   at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ThrowException(SocketError error, CancellationToken cancellationToken)

in .net framework 4.8

Unhandled Exception: System.Net.Http.HttpRequestException: An error occurred while sending the request. ---> System.Net.WebException: The remote name could not be resolved: 'werkjhwberkjbwkerwe876.com'


   at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
   at System.Net.Http.HttpClientHandler.GetResponseCallback(IAsyncResult ar)

Copy link
Member

@titusfortner titusfortner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your fix won't work because there are lots of unsuccessful status codes that are valid: https://w3c.github.io/webdriver/#errors

@titusfortner
Copy link
Member

Ah, I see what is going on. Sauce Labs returns a different signature than Browser Stack, which is why it isn't having the same issue for a 401 error.

The issue is when this condition isn't met in CreateResponse():

      if (responseInfo.ContentType != null && responseInfo.ContentType.StartsWith("application/json", StringComparison.OrdinalIgnoreCase))

Since all valid webdriver responses have to be those things, this is going to apply when either the http response isn't coming from a driver/server (i.e. bad request in StartSession()), or is an invalid webdriver response.

I think what we want to do is throw a WebDriverException from an else if after the previous one like

new HttpResponseMessage(responseInfo.StatusCode).IsSuccessStatusCode

@nvborisenko
Copy link
Member Author

nvborisenko commented Jul 8, 2022

It was hard to understand, and finally it works for me.

I didn't touch or changed logic in making http requests, generally, don't throw any exceptions.

Current Logic:
When we get http response, we construct Response based on body. Status of response is also set based on json body. But body might be formatted unexpectedly.

What I did:
After constructing Response object based on json body, we also set Status based on http status in case if we couldn't parse status from body (Success by default). So setting proper Status here allows it to be handled later and throw corresponding exception like NoSuchElementException.

@titusfortner thanks for your suggestion and please review.

@titusfortner titusfortner merged commit c0fa00f into SeleniumHQ:trunk Jul 13, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[🐛 Bug]: RemoteWebDriver doesn't properly handle response from the external resource
2 participants