chrome-php / chrome

Instrument headless chrome/chromium instances from PHP
MIT License
2.25k stars 276 forks source link

How to get the asynchronous response result of the specified URL? #623

Open quyunet opened 4 months ago

quyunet commented 4 months ago

I need to further operate the browser without closing the page and without closing the browser, becase the page will not change after the form is submitted, only the results are output asynchronously, the following methods always time out and cannot directly output asynchronous response results, unless printing at the network listening interruption point, but after I pass the result to the outside, it cannot be captured.

$responseData = null
$page->waitForElement('button[onclick="SaveDefaultNameservers();"]');

//Monitor network responses
$page->getSession()->on('method:Network.responseReceived', function ($response) use(&$responseData): void {
    if (strpos($response['response']['url'], 'https://example.com/updateDefaultNameservers') !== false) {
        $responseBody = $page->getSession()->sendMessageSync(new \HeadlessChromium\Communication\Message('Network.getResponseBody', ['requestId' => $response['requestId']]));      //Get asynchronous response
        //$page->getSession()->sendMessageSync(new \HeadlessChromium\Communication\Message('Page.stopLoading'));
        if (!isset($responseBody['error'])) {
            $responseData = $responseBody['result']['body'];
            //print_r($responseData);exit;    //Breakpoint printing can output the results correctly.
        }
    }
});

//submit Form
$page->evaluate(
    '(() => {
        document.querySelector("#accountDefaultNs").value = "ns1.netsto.net\nns2.netsto.net";
        document.querySelector("button[onclick=\'SaveDefaultNameservers();\']").click();
    })();'
)->waitForPageReload();

//Polling results.
while (!$responseData) {
    sleep(1);
}
var_dump($responseData);
quyunet commented 4 months ago

at present, I have come up with the following solutions, use try{} throw asynchronous response content in error form, but it may not be the optimal solution, is there a better solution?

$responseData = null
$page->waitForElement('button[onclick="SaveDefaultNameservers();"]');

try{
    //Monitor network responses
    $page->getSession()->on('method:Network.responseReceived', function ($response) use(&$responseData): void {
        if (strpos($response['response']['url'], 'https://example.com/updateDefaultNameservers') !== false) {
            $responseBody = $page->getSession()->sendMessageSync(new \HeadlessChromium\Communication\Message('Network.getResponseBody', ['requestId' => $response['requestId']]));      //Get asynchronous response
            //$page->getSession()->sendMessageSync(new \HeadlessChromium\Communication\Message('Page.stopLoading'));
            if (!isset($responseBody['error'])) {
                $responseData = $responseBody['result']['body'];
                throw new Exception($responseData);     //Throw asynchronous response content in error form.
            }
        }
    });

    //submit Form
    $page->evaluate(
        '(() => {
            document.querySelector("#accountDefaultNs").value = "ns1.netsto.net\nns2.netsto.net";
            document.querySelector("button[onclick=\'SaveDefaultNameservers();\']").click();
        })();'
    )->waitForPageReload();

} catch (Exception $e) {
    echo $e->getMessage();      //capture response content by capturing errors.
}