From 548c63a826bc8a168e2be3e381a561c83f932e60 Mon Sep 17 00:00:00 2001 From: MaceWindu Date: Wed, 27 Mar 2024 12:58:10 +0100 Subject: [PATCH] - handle error response from chrome - reduce noise on websocket connection closing --- ChromiumHtmlToPdfLib/Browser.cs | 4 +-- ChromiumHtmlToPdfLib/Connection.cs | 15 ++++++-- .../Protocol/PrintToPdfResponse.cs | 35 +++++++++++++++++-- 3 files changed, 47 insertions(+), 7 deletions(-) diff --git a/ChromiumHtmlToPdfLib/Browser.cs b/ChromiumHtmlToPdfLib/Browser.cs index 995db0e..69847a8 100644 --- a/ChromiumHtmlToPdfLib/Browser.cs +++ b/ChromiumHtmlToPdfLib/Browser.cs @@ -695,7 +695,7 @@ internal async Task PrintToPdfAsync(Stream outputStream, var printToPdfResponse = PrintToPdfResponse.FromJson(result); - if (string.IsNullOrEmpty(printToPdfResponse.Result.Stream)) + if (printToPdfResponse.Error != null || string.IsNullOrEmpty(printToPdfResponse.Result?.Stream)) throw new ConversionException($"Conversion failed ... did not get the expected response from Chromium, response '{result}'"); if (!outputStream.CanWrite) @@ -704,7 +704,7 @@ internal async Task PrintToPdfAsync(Stream outputStream, _logger?.Info("Resetting output stream to position 0"); message = new Message { Method = "IO.read" }; - message.AddParameter("handle", printToPdfResponse.Result.Stream!); + message.AddParameter("handle", printToPdfResponse.Result!.Stream!); message.AddParameter("size", 1048576); // Get the pdf in chunks of 1MB _logger?.Info("Reading generated PDF from IO stream with handle id {stream}", printToPdfResponse.Result.Stream); diff --git a/ChromiumHtmlToPdfLib/Connection.cs b/ChromiumHtmlToPdfLib/Connection.cs index 5492f7d..fc3c0b4 100644 --- a/ChromiumHtmlToPdfLib/Connection.cs +++ b/ChromiumHtmlToPdfLib/Connection.cs @@ -92,6 +92,11 @@ public class Connection : IDisposable, IAsyncDisposable /// private readonly int _timeout; + /// + /// Task to await for completion. + /// + private readonly Task _receiveTask; + /// /// Keeps track is we already disposed our resources /// @@ -114,7 +119,7 @@ internal Connection(string url, int timeout, Logger? logger) _webSocket = new ClientWebSocket(); _receiveLoopCts = new CancellationTokenSource(); OpenWebSocketAsync().GetAwaiter().GetResult(); - Task.Factory.StartNew(ReceiveLoop, new ReceiveLoopState(_logger, _webSocket, OnMessageReceived, _receiveLoopCts.Token), _receiveLoopCts.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default); + _receiveTask = Task.Factory.StartNew(ReceiveLoop, new ReceiveLoopState(_logger, _webSocket, OnMessageReceived, _receiveLoopCts.Token), _receiveLoopCts.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default); } #endregion @@ -160,6 +165,10 @@ private static async Task ReceiveLoop(object? stateData) { // Ignore } + catch (WebSocketException wsex) when (wsex.Message == "The remote party closed the WebSocket connection without completing the close handshake.") + { + // Ignore + } catch (Exception exception) { WebSocketOnError(state.Logger, new ErrorEventArgs(exception)); @@ -333,6 +342,8 @@ public async Task InternalDisposeAsync() _receiveLoopCts.Cancel(); + await (await _receiveTask.ConfigureAwait(false)).ConfigureAwait(false); + _logger?.Info("Disposing websocket connection to url '{url}'", _url); if (_webSocket.State == WebSocketState.Open) @@ -346,7 +357,7 @@ public async Task InternalDisposeAsync() } catch (Exception exception) { - _logger?.Error("An error occurred while closing the web socket, error: '{error}'", ExceptionHelpers.GetInnerException(exception)); + _logger?.Error(exception, "An error occurred while closing the web socket, error: '{error}'", ExceptionHelpers.GetInnerException(exception)); } _logger?.Info("Websocket connection closed"); diff --git a/ChromiumHtmlToPdfLib/Protocol/PrintToPdfResponse.cs b/ChromiumHtmlToPdfLib/Protocol/PrintToPdfResponse.cs index 5c681cb..0cca7f5 100644 --- a/ChromiumHtmlToPdfLib/Protocol/PrintToPdfResponse.cs +++ b/ChromiumHtmlToPdfLib/Protocol/PrintToPdfResponse.cs @@ -35,16 +35,25 @@ namespace ChromiumHtmlToPdfLib.Protocol; internal class PrintToPdfResponse { #region Properties + [JsonProperty("id")] + public int Id { get; set; } + /// /// /// [JsonProperty("result")] - public PrintToPdfResult Result { get; set; } = null!; + public PrintToPdfResult? Result { get; set; } + + /// + /// + /// + [JsonProperty("error")] + public PrintToPdfErrorResult? Error { get; set; } /// /// Returns as array of bytes /// - public byte[] Bytes => Convert.FromBase64String(Result.Data); + public byte[]? Bytes => Result != null ? Convert.FromBase64String(Result.Data) : null; #endregion #region FromJson @@ -78,4 +87,24 @@ internal class PrintToPdfResult [JsonProperty("stream")] public string? Stream { get; set; } #endregion -} \ No newline at end of file +} + +/// +/// Error result returned from the ConvertToPdf method +/// +internal class PrintToPdfErrorResult +{ + #region Properties + /// + /// Error code + /// + [JsonProperty("code")] + public int Code { get; set; } + + /// + /// Error message + /// + [JsonProperty("message")] + public string? Message { get; set; } + #endregion +}