Skip to content

Commit 36c391f

Browse files
Extends DevToolsPlugin with logging streamed responses. Closes #1298 (#1301)
1 parent b83451b commit 36c391f

File tree

2 files changed

+125
-22
lines changed

2 files changed

+125
-22
lines changed

DevProxy.Plugins/Inspection/CDPModel.cs

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
namespace DevProxy.Plugins.Inspection.CDP;
1111
#pragma warning restore IDE0130
1212

13-
public abstract class Message
13+
public class Message
1414
{
1515
[JsonPropertyName("id")]
1616
public int? Id { get; set; }
@@ -296,4 +296,38 @@ public class GetResponseBodyResultParams
296296
public string? Body { get; set; }
297297
[JsonPropertyName("base64Encoded")]
298298
public bool? Base64Encoded { get; set; }
299+
}
300+
301+
public class StreamResourceContentResult : MessageResult<StreamResourceContentResultParams>
302+
{
303+
}
304+
305+
public class StreamResourceContentResultParams
306+
{
307+
[JsonPropertyName("bufferedData")]
308+
public string? BufferedData { get; set; }
309+
}
310+
311+
public class DataReceivedMessage : Message<DataReceivedParams>
312+
{
313+
public DataReceivedMessage()
314+
{
315+
Method = "Network.dataReceived";
316+
}
317+
}
318+
319+
public class DataReceivedParams
320+
{
321+
[JsonPropertyName("data")]
322+
public string? Data { get; set; }
323+
[JsonPropertyName("dataLength")]
324+
public long? DataLength { get; set; }
325+
[JsonPropertyName("encodedDataLength")]
326+
public long? EncodedDataLength { get; set; }
327+
[JsonPropertyName("requestId")]
328+
public string? RequestId { get; set; }
329+
330+
[JsonPropertyName("timestamp")]
331+
public double? Timestamp { get; set; }
332+
299333
}

DevProxy.Plugins/Inspection/DevToolsPlugin.cs

Lines changed: 90 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
using System.Runtime.InteropServices;
1515
using System.Text.Json;
1616
using System.Globalization;
17+
using System.Text;
1718

1819
namespace DevProxy.Plugins.Inspection;
1920

@@ -192,6 +193,11 @@ public override async Task AfterResponseAsync(ProxyResponseArgs e, CancellationT
192193

193194
await _webSocket.SendAsync(responseReceivedMessage, cancellationToken);
194195

196+
if (e.Session.HttpClient.Response.ContentType == "text/event-stream")
197+
{
198+
await SendBodyAsDataReceivedAsync(requestId, body.Body, cancellationToken);
199+
}
200+
195201
var loadingFinishedMessage = new LoadingFinishedMessage
196202
{
197203
Params = new()
@@ -340,35 +346,98 @@ private void SocketMessageReceived(string msg)
340346

341347
try
342348
{
343-
var message = JsonSerializer.Deserialize<GetResponseBodyMessage>(msg, ProxyUtils.JsonSerializerOptions);
344-
if (message?.Method == "Network.getResponseBody")
349+
var message = JsonSerializer.Deserialize<Message>(msg, ProxyUtils.JsonSerializerOptions);
350+
switch (message?.Method)
345351
{
346-
var requestId = message.Params?.RequestId;
347-
if (requestId is null ||
348-
!_responseBody.TryGetValue(requestId, out var value) ||
349-
// should never happen because the message is sent from devtools
350-
// and Id is required on all socket messages but theoretically
351-
// it is possible
352-
message.Id is null)
353-
{
354-
return;
355-
}
356-
357-
var result = new GetResponseBodyResult
358-
{
359-
Id = (int)message.Id,
360-
Result = new()
352+
case "Network.getResponseBody":
353+
var getResponseBodyMessage = JsonSerializer.Deserialize<GetResponseBodyMessage>(msg, ProxyUtils.JsonSerializerOptions);
354+
if (getResponseBodyMessage is null)
361355
{
362-
Body = value.Body,
363-
Base64Encoded = value.Base64Encoded
356+
return;
364357
}
365-
};
366-
_ = _webSocket.SendAsync(result, _cancellationToken ?? CancellationToken.None);
358+
_ = HandleNetworkGetResponseBodyAsync(getResponseBodyMessage, _cancellationToken ?? CancellationToken.None);
359+
break;
360+
case "Network.streamResourceContent":
361+
_ = HandleNetworkStreamResourceContentAsync(message, _cancellationToken ?? CancellationToken.None);
362+
break;
363+
default:
364+
break;
367365
}
368366
}
369367
catch { }
370368
}
371369

370+
private async Task HandleNetworkStreamResourceContentAsync(Message message, CancellationToken cancellationToken)
371+
{
372+
if (_webSocket is null || message.Id is null)
373+
{
374+
return;
375+
}
376+
377+
var result = new StreamResourceContentResult
378+
{
379+
Id = (int)message.Id,
380+
Result = new()
381+
{
382+
BufferedData = string.Empty
383+
}
384+
};
385+
386+
await _webSocket.SendAsync(result, cancellationToken);
387+
}
388+
389+
private async Task HandleNetworkGetResponseBodyAsync(GetResponseBodyMessage message, CancellationToken cancellationToken)
390+
{
391+
if (_webSocket is null || message.Params?.RequestId is null)
392+
{
393+
return;
394+
}
395+
396+
if (!_responseBody.TryGetValue(message.Params.RequestId, out var value) ||
397+
// should never happen because the message is sent from devtools
398+
// and Id is required on all socket messages but theoretically
399+
// it is possible
400+
message.Id is null)
401+
{
402+
return;
403+
}
404+
405+
var result = new GetResponseBodyResult
406+
{
407+
Id = (int)message.Id,
408+
Result = new()
409+
{
410+
Body = value.Body,
411+
Base64Encoded = value.Base64Encoded
412+
}
413+
};
414+
415+
await _webSocket.SendAsync(result, cancellationToken);
416+
}
417+
418+
private async Task SendBodyAsDataReceivedAsync(string requestId, string? body, CancellationToken cancellationToken)
419+
{
420+
if (_webSocket is null || string.IsNullOrEmpty(body))
421+
{
422+
return;
423+
}
424+
425+
var base64Encoded = Convert.ToBase64String(Encoding.UTF8.GetBytes(body));
426+
var dataReceivedMessage = new DataReceivedMessage
427+
{
428+
Params = new()
429+
{
430+
RequestId = requestId,
431+
Timestamp = (double)DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() / 1000,
432+
Data = base64Encoded,
433+
DataLength = body.Length,
434+
EncodedDataLength = base64Encoded.Length
435+
}
436+
};
437+
438+
await _webSocket.SendAsync(dataReceivedMessage, cancellationToken);
439+
}
440+
372441
private static int GetFreePort()
373442
{
374443
using var listener = new TcpListener(IPAddress.Loopback, 0);

0 commit comments

Comments
 (0)