Skip to content

Unable to properly cancel request (Browser) #500

Description

@bileslav

Hello. The following code, contrary to expectations, doesn't return after 0.02 seconds. Or rather, not every run. Otherwise, it waits for something up to 10 seconds. The problem doesn't occur if you change React\Http\Browser::get() to React\Promise\Timer\sleep().

$browser = new React\Http\Browser();
$response = $browser->get('https://www.google.com/');

React\Promise\Timer\timeout($response, 0.02)
	->then('var_dump', 'var_dump');

React\EventLoop\Loop::run();

Activity

  1. changed the title [-]Unable to properly cancel request[/-] [+]Unable to properly cancel request (Browser)[/+] on Jun 23, 2023
  2. SimonFrings commented on Jun 26, 2023

    @SimonFrings
    Member

    Hey @bileslav, thanks for bringing this to our attention 🚀

    I tested the same example on my local machine and everything seems to be working fine, so I'm having difficulty reproducing the behavior you described. I even tried different timeouts, but the result remains consistent: it either throws a TimeoutException when the timeout triggers or returns a Response from google.com.

    Although I couldn't reproduce this issue, there is still a possibility that it might be a bug in ReactPHP. To confirm this, we would need a way to reproduce the behavior you're experiencing, which is also necessary in order to write tests for this. I think we need to gather more information in order to fully understand what's going on:

    • What is the state of the connection when this behavior occurs?
    • What output do you see when it returns after ~10 seconds?
    • How are you using the HTTP component of ReactPHP (version used, any advanced configuration, etc.)?

    As I mentioned above, I currently can't confirm that this is a bug, so I will close this ticket for now. However, if you can provide more evidence that this is indeed a bug in this package, we can always reopen the ticket and further investigate the issue.

  3. bileslav commented on Jun 26, 2023

    @bileslav
    Author

    Hi @SimonFrings! 😎

    I found that the problem only occurs when I'm connected to my VPN. Here are the steps to reproduce with Vagrant:

    mkdir issue500
    cd issue500
    
    vagrant init archlinux/archlinux
    vagrant up
    vagrant ssh
    
    sudo pacman -Syu --noconfirm
    
    logout
    vagrant reload
    vagrant ssh
    
    sudo pacman -S --noconfirm bat micro php composer wireguard-tools
    sudo pacman -S --noconfirm --asdeps systemd-resolvconf
    
    curl https://pastebin.com/raw/N345fGdP | tee issue500.php | bat
    curl https://pastebin.com/raw/JikZhmVZ | sudo tee /etc/wireguard/wg0.conf | bat
    
    composer require react/{http,promise-timer}
    
    curl https://ifconfig.co/ # your IP
    time php issue500.php 0.01 # fine
    
    wg-quick up wg0 # to disconnect: wg-quick down wg0
    
    curl https://ifconfig.co/ # new IP
    time php issue500.php 0.01 # here we go
    
    micro issue500.php # to edit
    
    logout
    vagrant destroy -f
    
    cd ..
    rm -r issue500
  4. SimonFrings commented on Jun 28, 2023

    @SimonFrings
    Member

    @bileslav Thanks for sharing this file 👍

    I'm not convinced that you using a VPN is causing this, ReactPHP doesn't really interact with this concept. The behavior you're describing is still odd and I think we have to answer the "when" question in order to figure out the "why". Do you have any information at which point the connection to google.com takes longer (is this happening at a specific point of the connection establishment)?

    I'm also curious if you've experimented with different timeouts. Does the problem persist regardless of the timeout setting?

  5. bileslav commented on Jun 29, 2023

    @bileslav
    Author

    @SimonFrings,

    ReactPHP doesn't really interact with this concept.

    Yeah, I understand your confusion. I'm confused too.

    I think we have to answer the "when" question in order to figure out the "why". Do you have any information at which point the connection to google.com takes longer (is this happening at a specific point of the connection establishment)? Does the problem persist regardless of the timeout setting?

    It's literally (always and only) when the WireGuard network interface (VPN) is up, but it seems like it's not a matter of the connection itself. Here are my stable observations:

    VPN state Timeout Output Time to output Total time
    any 0
    0.1
    TimeoutException same as timeout same as time to output
    off 0.01 TimeoutException same as timeout same as time to output
    on 0.01 TimeoutException same as timeout ~10
    any 1
    10
    Response (200 OK) 0.2-0.8 same as time to output

    This behavior is still reproducible with the commands above.

    What output do you see when it returns after ~10 seconds?

    Nothing, the script just exits. Relevant output happens much earlier, as expected.

    Important note: the problem is observed with a timeout of 0.01, but not 0.1, although the request itself takes up to a second in any case, which is also clear from the table. Because of this, I have absolutely no idea why this might be happening.

  6. SimonFrings commented on Dec 15, 2023

    @SimonFrings
    Member

    @bileslav thanks for the additional input on this, but I'm still not sure what could be causing this behavior. Another approach you can try is, instead of using the default React\Socket\Connector(), to create a custom connector in order to listen to specific connection events happening and then use this new connector inside the HTTP client (React\Http\Browser). This new connector would still use the default React\Socket\Connector() underneath and could look something like the example inside the socket documentation:

    $connector = new React\Socket\Connector();
    
    $connector->connect($uri)->then(function (React\Socket\ConnectionInterface $connection) {
        $connection->write('...');
        $connection->end();
    }, function (Exception $e) {
        echo 'Error: ' . $e->getMessage() . PHP_EOL;
    });

    The events you can listen to are described inside the reactphp/socket "Connection usage" chapter.

    It's been a while since your last message (my bad, had some busy months and now catching up outstanding ticket replies), maybe you found the cause or even a solution for this in the meantime? Happy about your input on this :)

  7. bileslav commented on Dec 16, 2023

    @bileslav
    Author

    Hey @SimonFrings,

    Glad to hear from you. Sorry, no news on this issue.

    I'm now using a different type of VPN, the problem was observed when using WireGuard tunnel, which I don't currently have on lease, so I have no way of confirming the bug at this time.

    In theory, I could install a WireGuard server on my VPS or even locally maybe, but I don't think I can find the time for this now, unfortunately.

  8. clue commented on Dec 16, 2023

    @clue
    Member

    @bileslav I've fixed a somewhat nasty bug earlier this week that might be related: reactphp/socket#311

    Perhaps you can update to the latest versions and try again? The problem specifically deals with cancellation of connection attempts during a very small 50ms time window depending on DNS resolution order between IPv4/IPv6, so this may indeed be indirectly affected by the kind of VPN you're using.

    Please report back if get more insights 👍

  9. bileslav commented on Dec 18, 2023

    @bileslav
    Author

    @clue,

    Nice job fixing that bug 👍

    As I wrote above, I no longer have access to the WireGuard configurations I was using. Russia recently started experimenting with blocking WireGuard, so I've switched to a more obscure protocol.

    However, I remembered that free VPN configurations can be found on the Internet. They're probably stealing personal data, dunno. The point is that I found a working config and tried to reproduce the problem.

    I was unable to reproduce it either with new versions or with those that were available at the time this issue was created.

    This is weird. There's a recipe above for reproducing the problem, which I tested on different computers. The only thing missing now is the WireGuard configuration from then. That config remained in the recipe (link to pastebin), but it has long expired.

    No ideas...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions