Skip to content

Commit c608820

Browse files
qmfrederikbrendandburns
authored andcommitted
Handle WebSocket exceptions (#155)
1 parent a5a15d7 commit c608820

File tree

1 file changed

+43
-0
lines changed

1 file changed

+43
-0
lines changed

src/KubernetesClient/Kubernetes.WebSocket.cs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1+
using k8s.Models;
12
using Microsoft.AspNetCore.WebUtilities;
23
using Microsoft.Rest;
4+
using Microsoft.Rest.Serialization;
35
using System;
46
using System.Collections.Generic;
57
using System.Linq;
8+
using System.Net;
69
using System.Net.Http;
710
using System.Net.WebSockets;
811
using System.Security.Cryptography.X509Certificates;
@@ -270,6 +273,46 @@ public partial class Kubernetes
270273
{
271274
webSocket = await webSocketBuilder.BuildAndConnectAsync(uri, CancellationToken.None).ConfigureAwait(false);
272275
}
276+
catch (WebSocketException wse) when (wse.WebSocketErrorCode == WebSocketError.HeaderError || (wse.InnerException is WebSocketException && ((WebSocketException)wse.InnerException).WebSocketErrorCode == WebSocketError.HeaderError))
277+
{
278+
// This usually indicates the server sent an error message, like 400 Bad Request. Unfortunately, the WebSocket client
279+
// class doesn't give us a lot of information about what went wrong. So, retry the connection.
280+
var uriBuilder = new UriBuilder(uri);
281+
uriBuilder.Scheme = uri.Scheme == "wss" ? "https" : "http";
282+
283+
var response = await this.HttpClient.GetAsync(uriBuilder.Uri, cancellationToken).ConfigureAwait(false);
284+
285+
if (response.StatusCode == HttpStatusCode.SwitchingProtocols)
286+
{
287+
// This should never happen - the server just allowed us to switch to WebSockets but the previous call didn't work.
288+
// Rethrow the original exception
289+
response.Dispose();
290+
throw;
291+
}
292+
else
293+
{
294+
var content = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
295+
296+
// Try to parse the content as a V1Status object
297+
var genericObject = SafeJsonConvert.DeserializeObject<KubernetesObject>(content);
298+
V1Status status = null;
299+
300+
if (genericObject.ApiVersion == "v1" && genericObject.Kind == "Status")
301+
{
302+
status = SafeJsonConvert.DeserializeObject<V1Status>(content);
303+
}
304+
305+
var ex = new HttpOperationException($"The operation returned an invalid status code: {response.StatusCode}", wse)
306+
{
307+
Response = new HttpResponseMessageWrapper(response, content),
308+
Body = status != null ? (object)status : content,
309+
};
310+
311+
response.Dispose();
312+
313+
throw ex;
314+
}
315+
}
273316
catch (Exception ex)
274317
{
275318
if (_shouldTrace)

0 commit comments

Comments
 (0)