Search code examples
google-chrome-devtoolspuppeteerpuppeteer-sharp

Is there any way to delay a Chrome response payload using Puppeteer or Chrome DevTools?


Below is the code I am using to delay a request in the Chrome browser using the PuppeteerSharp library.

        public static void HandleRequestIntercepted(object sender, RequestEventArgs args)
        {
            Task.Run(async () => {
                await Task.Delay(1000);
                await args.Request.ContinueAsync();
            });
        }

        static void Main(string[] args)
        {
            Task.Run(async () =>
            {
                Browser b = await Puppeteer.LaunchAsync(new LaunchOptions()
                {
                    ExecutablePath = "C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe",
                    DefaultViewport = null,
                    Headless = false
                });

                Page[] pages = await b.PagesAsync();
                Page page = pages[0];


                CDPSession cdpSession = await page.Target.CreateCDPSessionAsync();
                JObject obj = await cdpSession.SendAsync("Network.enable");
                await page.SetRequestInterceptionAsync(true);

                // Subscribe to requests
                page.Request += HandleRequestIntercepted;
            }
        }

However, is it possible to similarly delay a response? Specifically, I would like Chrome to delay the response payload for X amount of time.


Solution

  • I was able to introduce a response delay with the following code:

            public static CDPSession _cdpSessionResponse;
    
            public static void CdpSessionMessageReceived(object sender, MessageEventArgs args)
            {
                if (args.MessageID == "Fetch.requestPaused")
                {
                    Task.Run(async () => 
                    {
                        await Task.Delay(3000); // Wait 3 seconds
                        await _cdpSessionResponse.SendAsync("Fetch.continueRequest",
                            new Dictionary<string, object>
                            {
                                { "requestId", args.MessageData.ToObject<FetchRequestPausedResponse>().RequestId }
                            });
                    });
                }
            }
    
            static void Main(string[] args)
            {
                Task.Run(async () =>
                {
                    Browser b = await Puppeteer.LaunchAsync(new LaunchOptions()
                    {
                        ExecutablePath = "C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe",
                        DefaultViewport = null,
                        Headless = false
                    });
    
                    Page[] pages = await b.PagesAsync();
                    Page page = pages[0];
    
                   
    
                    // Set up RESPONSE interception using PuppeteerSharp
                    
                    _cdpSessionResponse = await page.Target.CreateCDPSessionAsync();
    
                    JObject response = await _cdpSessionResponse.SendAsync("Fetch.enable",
                        new Dictionary<string, object>
                        {
                            {
                                "patterns", new Dictionary<string, object>[]
                                {
                                    new Dictionary<string, object>
                                    {
                                        { "requestStage", "Response" }
                                    }
                                }
                            }
                        });
    
                    _cdpSessionResponse.MessageReceived += CdpSessionMessageReceived;
                }
            }
    
            internal class FetchRequestPausedResponse
            {
                public string RequestId { get; set; }
    
                public string NetworkId { get; set; }
            }
    

    However, this is puzzling because here is what I see in the Chrome DevTools Network tab -- not all responses were delayed with a long blue line: enter image description here

    For comparison, if I change the line { "requestStage", "Response" } to { "requestStage", "Request" }, I see that all the requests were delayed with a long transparent line (queuing time): enter image description here

    I'm not sure why there is this difference - perhaps this is internal to Chrome DevTools Protocol?