在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
开源软件名称:reactphp/http开源软件地址:https://github.com/reactphp/http开源编程语言:PHP 100.0%开源软件介绍:HTTPEvent-driven, streaming HTTP client and server implementation for ReactPHP. This HTTP library provides re-usable implementations for an HTTP client and
server based on ReactPHP's Table of contents
Quickstart exampleOnce installed, you can use the following code to access an HTTP web server and send some simple HTTP GET requests: <?php
require __DIR__ . '/vendor/autoload.php';
$client = new React\Http\Browser();
$client->get('http://www.google.com/')->then(function (Psr\Http\Message\ResponseInterface $response) {
var_dump($response->getHeaders(), (string)$response->getBody());
}, function (Exception $e) {
echo 'Error: ' . $e->getMessage() . PHP_EOL;
}); This is an HTTP server which responds with <?php
require __DIR__ . '/vendor/autoload.php';
$http = new React\Http\HttpServer(function (Psr\Http\Message\ServerRequestInterface $request) {
return React\Http\Message\Response::plaintext(
"Hello World!\n"
);
});
$socket = new React\Socket\SocketServer('127.0.0.1:8080');
$http->listen($socket); See also the examples. Client UsageRequest methodsMost importantly, this project provides a $browser->get($url, array $headers = array());
$browser->head($url, array $headers = array());
$browser->post($url, array $headers = array(), string|ReadableStreamInterface $body = '');
$browser->delete($url, array $headers = array(), string|ReadableStreamInterface $body = '');
$browser->put($url, array $headers = array(), string|ReadableStreamInterface $body = '');
$browser->patch($url, array $headers = array(), string|ReadableStreamInterface $body = ''); Each of these methods requires a You can optionally pass an associative array of additional If you're using a streaming request body, it will default
to using By default, all of the above methods default to sending requests using the
HTTP/1.1 protocol version. If you want to explicitly use the legacy HTTP/1.0
protocol version, you can use the Each of the above methods supports async operation and either fulfills with a
PSR-7 PromisesSending requests is async (non-blocking), so you can actually send multiple
requests in parallel.
The $browser->get($url)->then(
function (Psr\Http\Message\ResponseInterface $response) {
var_dump('Response received', $response);
},
function (Exception $e) {
echo 'Error: ' . $e->getMessage() . PHP_EOL;
}
); If this looks strange to you, you can also use the more traditional blocking API. Keep in mind that resolving the Promise with the full response message means the whole response body has to be kept in memory. This is easy to get started and works reasonably well for smaller responses (such as common HTML pages or RESTful or JSON API requests). You may also want to look into the streaming API:
CancellationThe returned Promise is implemented in such a way that it can be cancelled when it is still pending. Cancelling a pending promise will reject its value with an Exception and clean up any underlying resources. $promise = $browser->get($url);
Loop::addTimer(2.0, function () use ($promise) {
$promise->cancel();
}); TimeoutsThis library uses a very efficient HTTP implementation, so most HTTP requests
should usually be completed in mere milliseconds. However, when sending HTTP
requests over an unreliable network (the internet), there are a number of things
that can go wrong and may cause the request to fail after a time. As such, this
library respects PHP's Note that this timeout value covers creating the underlying transport connection, sending the HTTP request, receiving the HTTP response headers and its full response body and following any eventual redirects. See also redirects below to configure the number of redirects to follow (or disable following redirects altogether) and also streaming below to not take receiving large response bodies into account for this timeout. You can use the $browser = $browser->withTimeout(10.0);
$browser->get($url)->then(function (Psr\Http\Message\ResponseInterface $response) {
// response received within 10 seconds maximum
var_dump($response->getHeaders());
}, function (Exception $e) {
echo 'Error: ' . $e->getMessage() . PHP_EOL;
}); Similarly, you can use a bool If you're using a streaming response body, the time it takes to receive the response body stream will not be included in the timeout. This allows you to keep this incoming stream open for a longer time, such as when downloading a very large stream or when streaming data over a long-lived connection. If you're using a streaming request body, the time it takes to send the request body stream will not be included in the timeout. This allows you to keep this outgoing stream open for a longer time, such as when uploading a very large stream. Note that this timeout handling applies to the higher-level HTTP layer. Lower
layers such as socket and DNS may also apply (different) timeout values. In
particular, the underlying socket connection uses the same $browser = new React\Http\Browser(
new React\Socket\Connector(
array(
'timeout' => 5
)
)
); AuthenticationThis library supports HTTP Basic Authentication
using the By default, this library does not include an outgoing In order to pass authentication details, you can simply pass the username and password as part of the request URL like this: $promise = $browser->get('https://user:[email protected]/api'); Note that special characters in the authentication details have to be
percent-encoded, see also $token = 'abc123';
$promise = $browser->get(
'https://example.com/api',
array(
'Authorization' => 'Bearer ' . $token
)
); When following redirects, the RedirectsBy default, this library follows any redirects and obeys $browser->get($url, $headers)->then(function (Psr\Http\Message\ResponseInterface $response) {
// the final response will end up here
var_dump($response->getHeaders());
}, function (Exception $e) {
echo 'Error: ' . $e->getMessage() . PHP_EOL;
}); Any redirected requests will follow the semantics of the original request and
will include the same request headers as the original request except for those
listed below.
If the original request contained a request body, this request body will never
be passed to the redirected request. Accordingly, each redirected request will
remove any If the original request used HTTP authentication with an You can use the $browser = $browser->withFollowRedirects(false);
$browser->get($url)->then(function (Psr\Http\Message\ResponseInterface $response) {
// any redirects will now end up here
var_dump($response->getHeaders());
}, function (Exception $e) {
echo 'Error: ' . $e->getMessage() . PHP_EOL;
}); See also BlockingAs stated above, this library provides you a powerful, async API by default. If, however, you want to integrate this into your traditional, blocking environment, you should look into also using clue/reactphp-block. The resulting blocking code could look something like this: use Clue\React\Block;
$browser = new React\Http\Browser();
$promise = $browser->get('http://example.com/');
try {
$response = Block\await($promise, Loop::get());
// response successfully received
} catch (Exception $e) {
// an error occurred while performing the request
} Similarly, you can also process multiple requests concurrently and await an array of $promises = array(
$browser->get('http://example.com/'),
$browser->get('http://www.example.org/'),
);
$responses = Block\awaitAll($promises, Loop::get()); Please refer to clue/reactphp-block for more details. Keep in mind the above remark about buffering the whole response message in memory. As an alternative, you may also see one of the following chapters for the streaming API. ConcurrencyAs stated above, this library provides you a powerful, async API. Being able to send a large number of requests at once is one of the core features of this project. For instance, you can easily send 100 requests concurrently while processing SQL queries at the same time. Remember, with great power comes great responsibility. Sending an excessive number of requests may either take up all resources on your side or it may even get you banned by the remote side if it sees an unreasonable number of requests from your side. // watch out if array contains many elements
foreach ($urls as $url) {
$browser->get($url)->then(function (Psr\Http\Message\ResponseInterface $response) {
var_dump($response->getHeaders());
}, function (Exception $e) {
echo 'Error: ' . $e->getMessage() . PHP_EOL;
});
} As a consequence, it's usually recommended to limit concurrency on the sending side to a reasonable value. It's common to use a rather small limit, as doing more than a dozen of things at once may easily overwhelm the receiving side. You can use clue/reactphp-mq as a lightweight in-memory queue to concurrently do many (but not too many) things at once: // wraps Browser in a Queue object that executes no more than 10 operations at once
$q = new Clue\React\Mq\Queue(10, null, function ($url) use ($browser) {
return $browser->get($url);
});
foreach ($urls as $url) {
$q($url)->then(function (Psr\Http\Message\ResponseInterface $response) {
var_dump($response->getHeaders());
}, function (Exception $e) {
echo 'Error: ' . $e->getMessage() . PHP_EOL;
});
} Additional requests that exceed the concurrency limit will automatically be enqueued until one of the pending requests completes. This integrates nicely with the existing Promise-based API. Please refer to clue/reactphp-mq for more details. This in-memory approach works reasonably well for some thousand outstanding requests. If you're processing a very large input list (think millions of rows in a CSV or NDJSON file), you may want to look into using a streaming approach instead. See clue/reactphp-flux for more details. Streaming responseAll of the above examples assume you want to store the whole response body in memory. This is easy to get started and works reasonably well for smaller responses. However, there are several situations where it's usually a better idea to use a streaming approach, where only small chunks have to be kept in memory:
You can use the This means it resolves with a normal
PSR-7 $browser->requestStreaming('GET', $url)->then(function (Psr\Http\Message\ResponseInterface $response) {
$body = $response->getBody();
assert($body instanceof Psr\Http\Message\StreamInterface);
assert($body instanceof React\Stream\ReadableStreamInterface);
$body->on('data', function ($chunk) {
echo $chunk;
});
$body->on('error', function (Exception $e) {
echo 'Error: ' . $e->getMessage() . PHP_EOL;
});
$body->on('close', function () {
echo '[DONE]' . PHP_EOL;
});
}, function (Exception $e) {
echo 'Error: ' . $e->getMessage() . PHP_EOL;
}); See also the stream download benchmark example and the stream forwarding example. You can invoke the following methods on the message body: $body->on($event, $callback);
$body->eof();
$body->isReadable();
$body->pipe(React\Stream\WritableStreamInterface $dest, array $options = array());
$body->close();
$body->pause();
$body->resume(); Because the message body is in a streaming state, invoking the following methods doesn't make much sense: $body->__toString(); // ''
$body->detach(); // throws BadMethodCallException
$body->getSize(); // null
$body->tell(); // throws BadMethodCallException
$body->isSeekable(); // false
$body->seek(); // throws BadMethodCallException
$body->rewind(); // throws BadMethodCallException
$body->isWritable(); // false
$body->write(); // throws BadMethodCallException
$body->read(); // throws BadMethodCallException
$body->getContents(); // throws BadMethodCallException Note how timeouts apply slightly differently when using streaming. In streaming mode, the timeout value covers creating the underlying transport connection, sending the HTTP request, receiving the HTTP response headers and following any eventual redirects. In particular, the timeout value does not take receiving (possibly large) response bodies into account. If you want to integrate the streaming response into a higher level API, then working with Promise objects that resolve with Stream objects is often inconvenient. Consider looking into also using react/promise-stream. The resulting streaming code could look something like this: use React\Promise\Stream;
function download(Browser $browser, string $url): React\Stream\ReadableStreamInterface {
return Stream\unwrapReadable(
$browser->requestStreaming('GET', $url)->then(function (Psr\Http\Message\ResponseInterface $response) {
return $response->getBody();
})
);
}
$stream = download($browser, $url);
$stream->on('data', function ($data) {
echo $data;
});
$stream->on('error', function (Exception $e) {
echo 'Error: ' . $e->getMessage() . PHP_EOL;
}); See also the Streaming requestBesides streaming the response body, you can also stream the request body.
This can be useful if you want to send big POST requests (uploading files etc.)
or process many outgoing streams at once.
Instead of passing the body as a string, you can simply pass an instance
implementing ReactPHP's $browser->post($url, array(), $stream)->then(function (Psr\Http\Message\ResponseInterface $response) {
echo 'Successfully sent.';
}, function (Exception $e) {
echo 'Error: ' . $e->getMessage() . PHP_EOL;
}); If you're using a streaming request body ( $body = new React
|
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论