reactphp / http-client Goto Github PK
View Code? Open in Web Editor NEW[Deprecated] Event-driven, streaming HTTP client for ReactPHP.
Home Page: https://reactphp.org/http-client/
License: MIT License
[Deprecated] Event-driven, streaming HTTP client for ReactPHP.
Home Page: https://reactphp.org/http-client/
License: MIT License
I've started on a followRedirects
(and maxRedirects
) option parameter.
It's not ready for a pull request yet, but the idea of where I'm headed should be clear.
Would appreciate any feedback to see if I'm headed in the right direction.
master...Beanow:feature/follow-redirects
if i have thousands of requests needed to send,how can i set a http client pool?
i'm try to implement request every 5 seconds, but not work :(
I use this exmple.
https://github.com/reactphp/http-client/blob/master/examples/02-post-json.php
Anyone can help me? Thanks.
Depends on reactphp-legacy/socket-client#41
I'm struggling to reproduce this and I can't anymore, but it's fairly clear in the code this is possible. There are two places where the data
event for a Response
can be triggered.
In Response::handleData the arguments are string
, Response
.
In Request::handleData the arguments are Psr\Http\Message\StreamInterface
, Response
.
The latter seems to be correct, happens all the time, and what I want to incrementally read from the stream, so I just wrap my own handleData
logic in $stream instanceof StreamInterface
but that feels smelly.
The thing I can't reproduce is when Response::handleData
gets called. It was happening to me every single time the responding server threw a fatal PHP error, now I can't make it happen. Also of interesting note it was returning only part of the PHP error text, although the stream itself yielded the entire text.
Also of note this is with v0.4.10 (I'll update to the latest) but the code is identical in your master branch.
I don't know how to reproduce problem using only this library, but with WyriHaximus/react-guzzle-psr7 this code
<?php
require_once __DIR__ . '/vendor/autoload.php';
$loop = React\EventLoop\Factory::create();
$handler = new WyriHaximus\React\GuzzlePsr7\HttpClientAdapter($loop);
$client = new GuzzleHttp\Client([
'handler' => GuzzleHttp\HandlerStack::create($handler),
]);
$request = new GuzzleHttp\Psr7\Request('GET', 'https://wizzair.com/');
$promise = $client->sendAsync($request)->then(function (Psr\Http\Message\ResponseInterface $response) {
echo (string)$response->getBody();
});
$promise->wait();
produces
PHP Fatal error: Uncaught Exception: Unable to validate "27C" as chunk length header in /home/mateusz/git/react-guzzle-test/vendor/react/http-client/src/ChunkedStreamDecoder.php:122
Stack trace:
#0 /home/mateusz/git/react-guzzle-test/vendor/react/http-client/src/ChunkedStreamDecoder.php(70): React\HttpClient\ChunkedStreamDecoder->iterateBuffer()
#1 [internal function]: React\HttpClient\ChunkedStreamDecoder->handleData('="Original" src...', Object(React\Stream\Stream))
#2 /home/mateusz/git/react-guzzle-test/vendor/evenement/evenement/src/Evenement/EventEmitterTrait.php(64): call_user_func_array(Array, Array)
#3 /home/mateusz/git/react-guzzle-test/vendor/react/stream/src/Stream.php(173): Evenement\EventEmitter->emit('data', Array)
#4 [internal function]: React\Stream\Stream->handleData(Resource id #96, Object(React\EventLoop\StreamSelectLoop))
#5 /home/mateusz/git/react-guzzle-test/vendor/react/event-loop/src/StreamSelectLoop.php(232): call_user_func(Array, Resource id #96, Object(React\EventLoop\StreamSelectLoop))
#6 /home/mat in /home/mateusz/git/react-guzzle-test/vendor/react/http-client/src/Request.php on line 150
Refs #5
The Response
is a ReadableStreamInterface
, however it does not currently obey its event semantics:
close
eventend
event if the underlying stream closesend
event with an error
if the underlying stream endsWe should obey the stream semantics here, see also reactphp/stream#59.
Note that this will result in a BC break, so we should target the v0.5.0 release here. Even the examples (#69) highlight how the end
event should actually be a close
event instead.
i wanted to reject the promise based on timer to cancel the request.
Kindly advise
PHP Fatal error: Uncaught TypeError: Argument 1 passed to {closure}() must be an instance of Exception, none given, called in /vendor/evenement/evenement/src/Evenement/EventEmitterTrait.php on line 123
public function call()
{
$this->request = $this->client->request($this->method, $this->url);
$deferred = new Deferred();
$this->request->on('response', function (\React\HttpClient\Response $response)use ($deferred) {
$response->on('data', function ($chunk) use ($deferred){
$deferred->resolve($chunk);
});
});
$this->request->on('error', function (\Exception $e) use ($deferred){
$deferred->reject($e->getMessage());
});
Error thrown here
// $this->request->on('close', function (\Exception $e) use ($deferred){
// $deferred->reject($e->getMessage());
// });
$this->request->end();
return $deferred->promise();
}
public function close(){
$this->request->close();
}
$mainLoop->addTimer(15.0, function () use ($requestEndpoints) {
$requestEndpoints->close();
});
Now when we support Transfer-Encoding: chunked it would be great to have at least basic continue support. I'll file example MR soon
The ResponseData version was changed to 1.0, but I don't see a way to change the version to 1.1 through the Client.
I'm using this code to send a POST request but it's not working.
<?php
require 'vendor/autoload.php';
$loop = React\EventLoop\Factory::create();
$dnsResolverFactory = new React\Dns\Resolver\Factory();
$dnsResolver = $dnsResolverFactory->createCached('8.8.8.8', $loop);
$factory = new React\HttpClient\Factory();
$client = $factory->create($loop, $dnsResolver);
$request = $client->request('POST', 'http://respondto.it/bomber');
$request->write("test=12345");
$request->on(
'response',
function ($response) {
echo "recived".PHP_EOL;
$response->on(
'data',
function ($data) {
var_dump($data);
}
);
}
);
$request->end();
$loop->run();
Result is
POST /bomber
Headers
Connect-Time: 1
Connection: close
Host: respondto.it
Total-Route-Time: 0
User-Agent: React/alpha
Version: HTTP/1.1
Via: 1.1 vegur
X-Forwarded-Port: 80
X-Forwarded-Proto: http
X-Request-Id: 6596bd3e-1505-45a9-adbd-a0a5f4c7ea52
I know that i'm doing something wrong but i couldn't find solution.
I am working on a project which will make a lot of connections to external APIs and I need to queue the requests so that I can limit the number of active requests. This is needed to manage the load on the API (also may be useful for APIs that enforce a request limit).
For this reason I want to build the request and attach all event handlers, also write some data, but not yet send it.
Currently write()
will directly open the connection and send the data.
Lines 103 to 107 in d779a3b
I suggest to add a method that allows adding data to $pendingWrites
without sending the request.
Refs #5
According to https://github.com/reactphp/socket-client/blob/master/src/Connector.php#L9 Connector is deprecated. This could allow to change https://github.com/reactphp/http-client/blob/master/src/Factory.php#L12 by providing a default NULL resolver and in that case use a TcpConnector instead of a DnsConnector.
This would require upping socket-client dependency to 0.5 from 0.3 but would allow reducing some boilerplate code especially for simple test apps and local installations.
Opening this for the reference and to raise awareness. Note that there's an ongoing discussion as to whether this component should be merged into the Http component.
See reactphp/http#148 for details.
Examples miss a really important point: error handly for a request like a simple timeout.
simply like this:
$request = $client->request('GET', $url);
$request->on('error', function ($e) {
$socketerror = $e->getPrevious();
echo "request failed with error: " . $e->getMessage() . PHP_EOL;
});
I spend too much time just for this so i think it should be added in the README or the exemple section.
Hello,
I encountered the following error using the react http client (v0.4.11) :
Call to undefined method React\HttpClient\ChunkedStreamDecoder::end()
Indeed in Response.php it seem that $this->stream->end()
is not (always?) resolved
Fixed my issue by getting back to 0.4.10.
Cheers.
Refs #5
Let's face it, this project is stable and has been used in production for years
However, we're currently following a v0.X.Y release scheme (http://sentimentalversioning.org/).
We should finally make this explicit and fully adhere to SemVer and release a stable v1.0.0.
To a large extend, a stable v1.0.0 helps making BC breaks more explicit and thus the whole project more reliable from a consumer perspective. This project is actively maintained and has received some major updates in the last weeks and has some major updates planned in the next weeks. Given our current versioning scheme, we'd like to ensure all anticipated BC breaks will be merged before the planned v1.0.0 release.
As such, I've set up a roadmap that enlists only the major changes for each version among with planned release dates towards a stable v1.0.0 release:
This ticket aims to serve as a basic overview and does not contain every single change. Please also see the milestone links and the CHANGELOG for more details.
Obviously, this roadmap is subject to change and I'll try to keep it updated as we progress. In order to avoid cluttering this, please keep discussion in this ticket to a minimum and consider reaching out to us through new tickets or Twitter etc.
Since the code is almost identical, can we make the same change in this package as it was done here: reactphp/http#65?
As the title suggests, please make sure that you don't use abandoned packages.
If the dns server is not available the script will hang forever, in this case it was blocked by firewall.
Currently, request timeouts can be implemented somewhat messily by specifying loop timers and attempting to manually close the request. They should ideally be in-built.
require_once __DIR__.'/vendor/autoload.php';
$inner = count($argv) > 1;
$loop = new \React\EventLoop\ExtEventLoop();
$connector = new React\Socket\Connector($loop);
runme($loop, $connector, $inner);
if (!$inner) {
echo "Outer start\n";
$loop->run();
}
function runme(\React\EventLoop\LoopInterface $loop, React\Socket\Connector $connector, $inner)
{
$connector->connect('tcp://127.0.0.1:3306')->
then(function (\React\Socket\ConnectionInterface $conn) {
echo ("Hello MySQL!\n");
$conn->close();
},function ($e) {
echo ("Bye MySQL!\n");
})->done();
if ($inner) {
echo "Inner start\n";
$loop->run();
}
echo "Exit runme\n";
}
it works proper and returns:
$ php ./testMysql.php
Exit runme
Outer start
Hello MySQL!
$ php ./testMysql.php --inner
Inner start
Hello MySQL!
Exit runme
But if you go into \React\Socket\TcpConnector::waitForStreamOnce() and remove $canceller function in new Promise object like below, than it hangs again. Looks like it works in latest version of react a kind of accidentally as socket not stored obvious way, and in fact similar to code in v0.4.6.
private function waitForStreamOnce($stream)
{
$loop = $this->loop;
return new Promise\Promise(function ($resolve, $reject) use ($loop, $stream) {
$loop->addWriteStream($stream, function ($stream) use ($loop, $resolve, $reject) {
$loop->removeWriteStream($stream);
// The following hack looks like the only way to
// detect connection refused errors with PHP's stream sockets.
if (false === stream_socket_get_name($stream, true)) {
fclose($stream);
$reject(new \RuntimeException('Connection refused'));
} else {
$resolve(new Connection($stream, $loop));
}
});
});
}
$ php ./testMysql.php --inner
Inner start
.....HANGING
$ php ./testMysql.php
Exit runme
Outer start
...HANGING
Initial discussion here: https://stackoverflow.com/questions/47551054/php-7-1-pecl-event-libevent-is-hanging-in-weird-case
Currently, calling close()
on a pending Request
stream does not necessarily close all underlying resources.
Also, it should probably cancel a pending connection attempt, so this likely depends on reactphp-legacy/socket-client#40
Hi, i have an remote API and i need to update echo $chunk everytime remote content change.
I use this exmple.
https://github.com/reactphp/http-client/blob/master/examples/02-post-json.php
Anyone can help me? Thanks.
...where they invariably fail.
I've got the following simple code which sends a request and displays the response.
Problem: the echoed buffer will always be string(0)
unless I declare it as &buffer
in the on('end')
. string(0)
is how the buffer is initialized:
$request = $client->request(
'POST',
$url,
array(
'Content-Length' => strlen($data),
'Content-Type' => 'application/json'
)
);
$request->on('response', function ($response) {
$buffer = '';
$response->on('data', function ($data, $response) use (&$buffer) {
$buffer .= (string) $data;
});
$response->on('end', function ($error) use ($response, $buffer /* < by ref matters */) {
echo(sprintf("HTTP %d\n", $response->getCode()));
if ($buffer) {
echo($buffer . PHP_EOL);
}
});
});
$request->end($data);
Might this be a problem with PHP-internal optimization?
Got an exception: strtolower() expects parameter 1 to be string, array given in /http-client/src/Response.php:36
Test url with problem: http://mosmama.info/org/user/2275/contact
Issues happens because header "transfer-encoding" contains "Transfer-Encoding: chunked, chunked"
Browser "Firefox" processes this case correctly.
Refs #44.
Wrong repos, sorry. Reposted the issue at reactphp-legacy/socket-client#69
Hi,
I'm using wyrihaximus/react-guzzle-psr7
to send async requests with Guzzle HTTP, however, the server I am requesting has recently started using chunked HTTP requests. I saw that chunked requests was recently introduced into the HTTP client by the creator of the package I am using however I am still getting the error Stream ended with incomplete control code
. Is this a client side problem?
Thanks
Hello,
Just a question, using the function $connection->write($data); is it blocking or sync?
I mean if i have to write 10000 times on a connection and one of these times it takes a while for some reasons, will it delay all the other writings or looping the write function and then $loop->run(); , everything starts as unique thread?
Thanks
..
http-client How to set time out
I am Chinese, My English is not good Please understand
When sending large contents via POST, specifically images (~90kb+) the connection simply hangs. I have already filed the same bug in for the WyriHaximus guzzle adapter here: WyriHaximus/react-guzzle-psr7#10.
Here is some short example code:
<?php
require_once 'vendor/autoload.php';
$mp = new p3k\Multipart;
$mp->addPart('field', 'value');
$mp->addFile('file', 'large-image', 'image/jpeg');
$url = "https://example.com";
$loop = React\EventLoop\Factory::create();
$dnsFactory = new React\Dns\Resolver\Factory();
$dns = $dnsFactory->createCached('192.168.2.1', $loop);
$factory = new React\HttpClient\Factory();
$client = $factory->create($loop, $dns);
$loop->nextTick(function() use ($client, $url, $mp) {
$request = $client->request("POST", $url, [
'Content-Type' => $mp->contentType(),
'Content-Length' => strlen($mp->data())
]);
$request->on('response', function($response) {
print "WE HAVE RESPONSE: ".$response->getCode()."\n";
print_r($response->getHeaders());
$response->on('data', function($data, $response) {
print "DATA ...\n";
print $data;
});
$response->on('end', function() {
die("IT'S OVER!\n");
});
});
$request->end($mp->data());
});
while (1) $loop->run();
print "DONE!\n";
You will need a URL to POST to as well as an image file to send. Both should not be hard to get a hold of to test this.
Accessing the HTTP response body is likely one of the main use cases for this library, however it's actually unnecessarily cumbersome.
This has come up several times already, so we way want to look into providing a simpler API.
Possibly related to #41.
I got stable exception "Unable to validate "1 " as chunk length header".
Test url "http://www.samaraphone.ru/530300.shtml".
Probably trim() could be solution;
Hello there
I met two problem.
I find that if I send more than 1000 requests at the same time, some requests will get timeout exception.
Some http header and body are concatenated by "\n\n", not "\r\n\r\n". this package cannnot handle theme correctly, but browser can.
ps: I encountered this problem on win, I do not know Linux will not have this problem
I'm writing simple parser. When trying to get contents of https://meduza.io/feature/2015/05/19/zaschita-astahova, I see some rubbish going through stream.
However, https://youtube.com or https://www.coursera.org/ works as normal.
What can this be?
Trying to access TLS servers, I keep getting errors. For example when trying to access https://www.google.com , I get this:
An error occurred in the underlying stream:
Unable to complete SSL/TLS handshake:
stream_socket_enable_crypto():
Peer certificate CN=`www.google.com' did not match expected CN=`74.125.140.106'
My code is:
$request = $this->client->request('GET', 'https://www.google.com', [ ]);
$request->on('error', function ($err) use ($callback) { $callback($err, NULL); });
$request->on('response', function ($response) {
$response->on('data', function ($data, $response) {
echo "Got response data";
var_dump([$data, $response]);
});
});
$request->end();
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.