Skip to content

Commit 16ad5a9

Browse files
authored
Merge pull request #368 from clue-labs/http-client
Add HTTP client implementation (import clue/reactphp-buzz v2.9.0)
2 parents 7b4e687 + 785ded0 commit 16ad5a9

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+8287
-87
lines changed

LICENSE

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) 2013 Christian Lück
14
Copyright (c) 2012 Igor Wiedler, Chris Boden
25

36
Permission is hereby granted, free of charge, to any person obtaining a copy

README.md

Lines changed: 1203 additions & 30 deletions
Large diffs are not rendered by default.

composer.json

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "react/http",
3-
"description": "Event-driven, streaming plaintext HTTP and secure HTTPS server for ReactPHP",
4-
"keywords": ["event-driven", "streaming", "HTTP", "HTTPS", "server", "ReactPHP"],
3+
"description": "Event-driven, streaming HTTP client and server implementation for ReactPHP",
4+
"keywords": ["HTTP client", "HTTP server", "HTTP", "HTTPS", "event-driven", "streaming", "client", "server", "PSR-7", "async", "ReactPHP"],
55
"license": "MIT",
66
"authors": [
77
{
@@ -27,15 +27,20 @@
2727
],
2828
"require": {
2929
"php": ">=5.3.0",
30-
"ringcentral/psr7": "^1.2",
31-
"react/socket": "^1.0 || ^0.8.3",
32-
"react/stream": "^1.0 || ^0.7.1",
33-
"react/promise": "^2.3 || ^1.2.1",
3430
"evenement/evenement": "^3.0 || ^2.0 || ^1.0",
35-
"react/promise-stream": "^1.1"
31+
"psr/http-message": "^1.0",
32+
"react/event-loop": "^1.0 || ^0.5",
33+
"react/promise": "^2.3 || ^1.2.1",
34+
"react/promise-stream": "^1.1",
35+
"react/socket": "^1.1",
36+
"react/stream": "^1.0 || ^0.7.5",
37+
"ringcentral/psr7": "^1.2"
3638
},
3739
"require-dev": {
3840
"clue/block-react": "^1.1",
41+
"clue/http-proxy-react": "^1.3",
42+
"clue/reactphp-ssh-proxy": "^1.0",
43+
"clue/socks-react": "^1.0",
3944
"phpunit/phpunit": "^9.0 || ^5.7 || ^4.8.35"
4045
},
4146
"autoload": {

examples/01-client-get-request.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
use React\Http\Browser;
4+
use Psr\Http\Message\ResponseInterface;
5+
6+
require __DIR__ . '/../vendor/autoload.php';
7+
8+
$loop = React\EventLoop\Factory::create();
9+
$client = new Browser($loop);
10+
11+
$client->get('http://google.com/')->then(function (ResponseInterface $response) {
12+
var_dump($response->getHeaders(), (string)$response->getBody());
13+
});
14+
15+
$loop->run();
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
use React\Http\Browser;
4+
use Psr\Http\Message\ResponseInterface;
5+
6+
require __DIR__ . '/../vendor/autoload.php';
7+
8+
$loop = React\EventLoop\Factory::create();
9+
$client = new Browser($loop);
10+
11+
$client->head('http://www.github.com/clue/http-react')->then(function (ResponseInterface $response) {
12+
var_dump($response->getHeaders(), (string)$response->getBody());
13+
});
14+
15+
$client->get('http://google.com/')->then(function (ResponseInterface $response) {
16+
var_dump($response->getHeaders(), (string)$response->getBody());
17+
});
18+
19+
$client->get('http://www.lueck.tv/psocksd')->then(function (ResponseInterface $response) {
20+
var_dump($response->getHeaders(), (string)$response->getBody());
21+
});
22+
23+
$loop->run();

examples/03-client-request-any.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
// concurrently request a number of URLs.
4+
// return immediately once the first is completed, cancel all others.
5+
6+
use React\Http\Browser;
7+
use Psr\Http\Message\ResponseInterface;
8+
9+
require __DIR__ . '/../vendor/autoload.php';
10+
11+
$loop = React\EventLoop\Factory::create();
12+
$client = new Browser($loop);
13+
14+
$promises = array(
15+
$client->head('http://www.github.com/clue/http-react'),
16+
$client->get('https://httpbin.org/'),
17+
$client->get('https://google.com'),
18+
$client->get('http://www.lueck.tv/psocksd'),
19+
$client->get('http://www.httpbin.org/absolute-redirect/5')
20+
);
21+
22+
React\Promise\any($promises)->then(function (ResponseInterface $response) use ($promises) {
23+
// first response arrived => cancel all other pending requests
24+
foreach ($promises as $promise) {
25+
$promise->cancel();
26+
}
27+
28+
var_dump($response->getHeaders());
29+
echo PHP_EOL . $response->getBody();
30+
});
31+
32+
$loop->run();

examples/04-client-post-json.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
use React\Http\Browser;
4+
use Psr\Http\Message\ResponseInterface;
5+
6+
require __DIR__ . '/../vendor/autoload.php';
7+
8+
$loop = React\EventLoop\Factory::create();
9+
$client = new Browser($loop);
10+
11+
$data = array(
12+
'name' => array(
13+
'first' => 'Alice',
14+
'name' => 'Smith'
15+
),
16+
'email' => '[email protected]'
17+
);
18+
19+
$client->post(
20+
'https://httpbin.org/post',
21+
array(
22+
'Content-Type' => 'application/json'
23+
),
24+
json_encode($data)
25+
)->then(function (ResponseInterface $response) {
26+
echo (string)$response->getBody();
27+
}, 'printf');
28+
29+
$loop->run();

examples/05-client-put-xml.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
use React\Http\Browser;
4+
use Psr\Http\Message\ResponseInterface;
5+
6+
require __DIR__ . '/../vendor/autoload.php';
7+
8+
$loop = React\EventLoop\Factory::create();
9+
$client = new Browser($loop);
10+
11+
$xml = new SimpleXMLElement('<users></users>');
12+
$child = $xml->addChild('user');
13+
$child->alias = 'clue';
14+
$child->name = 'Christian Lück';
15+
16+
$client->put(
17+
'https://httpbin.org/put',
18+
array(
19+
'Content-Type' => 'text/xml'
20+
),
21+
$xml->asXML()
22+
)->then(function (ResponseInterface $response) {
23+
echo (string)$response->getBody();
24+
}, 'printf');
25+
26+
$loop->run();
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
3+
// not already running a HTTP CONNECT proxy server?
4+
// Try LeProxy.org or this:
5+
//
6+
// $ php examples/72-server-http-connect-proxy.php 8080
7+
// $ php examples/11-client-http-connect-proxy.php
8+
9+
use React\Http\Browser;
10+
use Clue\React\HttpProxy\ProxyConnector as HttpConnectClient;
11+
use Psr\Http\Message\ResponseInterface;
12+
use React\EventLoop\Factory as LoopFactory;
13+
use React\Socket\Connector;
14+
15+
require __DIR__ . '/../vendor/autoload.php';
16+
17+
$loop = LoopFactory::create();
18+
19+
// create a new HTTP CONNECT proxy client which connects to a HTTP CONNECT proxy server listening on localhost:8080
20+
$proxy = new HttpConnectClient('127.0.0.1:8080', new Connector($loop));
21+
22+
// create a Browser object that uses the HTTP CONNECT proxy client for connections
23+
$connector = new Connector($loop, array(
24+
'tcp' => $proxy,
25+
'dns' => false
26+
));
27+
$browser = new Browser($loop, $connector);
28+
29+
// demo fetching HTTP headers (or bail out otherwise)
30+
$browser->get('https://www.google.com/')->then(function (ResponseInterface $response) {
31+
echo RingCentral\Psr7\str($response);
32+
}, 'printf');
33+
34+
$loop->run();

examples/12-client-socks-proxy.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
// not already running a SOCKS proxy server?
4+
// Try LeProxy.org or this: `ssh -D 1080 localhost`
5+
6+
use React\Http\Browser;
7+
use Clue\React\Socks\Client as SocksClient;
8+
use Psr\Http\Message\ResponseInterface;
9+
use React\EventLoop\Factory as LoopFactory;
10+
use React\Socket\Connector;
11+
12+
require __DIR__ . '/../vendor/autoload.php';
13+
14+
$loop = LoopFactory::create();
15+
16+
// create a new SOCKS proxy client which connects to a SOCKS proxy server listening on localhost:1080
17+
$proxy = new SocksClient('127.0.0.1:1080', new Connector($loop));
18+
19+
// create a Browser object that uses the SOCKS proxy client for connections
20+
$connector = new Connector($loop, array(
21+
'tcp' => $proxy,
22+
'dns' => false
23+
));
24+
$browser = new Browser($loop, $connector);
25+
26+
// demo fetching HTTP headers (or bail out otherwise)
27+
$browser->get('https://www.google.com/')->then(function (ResponseInterface $response) {
28+
echo RingCentral\Psr7\str($response);
29+
}, 'printf');
30+
31+
$loop->run();

examples/13-client-ssh-proxy.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
use React\Http\Browser;
4+
use Clue\React\SshProxy\SshSocksConnector;
5+
use Psr\Http\Message\ResponseInterface;
6+
use React\EventLoop\Factory as LoopFactory;
7+
use React\Socket\Connector;
8+
9+
require __DIR__ . '/../vendor/autoload.php';
10+
11+
$loop = LoopFactory::create();
12+
13+
// create a new SSH proxy client which connects to a SSH server listening on localhost:22
14+
// You can pass any SSH server address as first argument, e.g. [email protected]
15+
$proxy = new SshSocksConnector(isset($argv[1]) ? $argv[1] : 'localhost:22', $loop);
16+
17+
// create a Browser object that uses the SSH proxy client for connections
18+
$connector = new Connector($loop, array(
19+
'tcp' => $proxy,
20+
'dns' => false
21+
));
22+
$browser = new Browser($loop, $connector);
23+
24+
// demo fetching HTTP headers (or bail out otherwise)
25+
$browser->get('https://www.google.com/')->then(function (ResponseInterface $response) {
26+
echo RingCentral\Psr7\str($response);
27+
}, 'printf');
28+
29+
$loop->run();
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
use React\Http\Browser;
4+
use Psr\Http\Message\ResponseInterface;
5+
use React\EventLoop\Factory as LoopFactory;
6+
use React\Socket\FixedUriConnector;
7+
use React\Socket\UnixConnector;
8+
use RingCentral\Psr7;
9+
10+
require __DIR__ . '/../vendor/autoload.php';
11+
12+
$loop = LoopFactory::create();
13+
14+
// create a Browser object that uses the a Unix Domain Sockets (UDS) path for all requests
15+
$connector = new FixedUriConnector(
16+
'unix:///var/run/docker.sock',
17+
new UnixConnector($loop)
18+
);
19+
20+
$browser = new Browser($loop, $connector);
21+
22+
// demo fetching HTTP headers (or bail out otherwise)
23+
$browser->get('http://localhost/info')->then(function (ResponseInterface $response) {
24+
echo Psr7\str($response);
25+
}, 'printf');
26+
27+
$loop->run();
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
use React\Http\Browser;
4+
use Psr\Http\Message\ResponseInterface;
5+
use React\Stream\ReadableStreamInterface;
6+
use React\Stream\WritableResourceStream;
7+
use RingCentral\Psr7;
8+
9+
require __DIR__ . '/../vendor/autoload.php';
10+
11+
if (DIRECTORY_SEPARATOR === '\\') {
12+
fwrite(STDERR, 'Non-blocking console I/O not supported on Windows' . PHP_EOL);
13+
exit(1);
14+
}
15+
16+
$loop = React\EventLoop\Factory::create();
17+
$client = new Browser($loop);
18+
19+
$out = new WritableResourceStream(STDOUT, $loop);
20+
$info = new WritableResourceStream(STDERR, $loop);
21+
22+
$url = isset($argv[1]) ? $argv[1] : 'http://google.com/';
23+
$info->write('Requesting ' . $url . '' . PHP_EOL);
24+
25+
$client->requestStreaming('GET', $url)->then(function (ResponseInterface $response) use ($info, $out) {
26+
$info->write('Received' . PHP_EOL . Psr7\str($response));
27+
28+
$body = $response->getBody();
29+
assert($body instanceof ReadableStreamInterface);
30+
$body->pipe($out);
31+
}, 'printf');
32+
33+
$loop->run();
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
use React\Http\Browser;
4+
use Psr\Http\Message\ResponseInterface;
5+
use React\Stream\ReadableResourceStream;
6+
use RingCentral\Psr7;
7+
8+
require __DIR__ . '/../vendor/autoload.php';
9+
10+
if (DIRECTORY_SEPARATOR === '\\') {
11+
fwrite(STDERR, 'Non-blocking console I/O not supported on Windows' . PHP_EOL);
12+
exit(1);
13+
}
14+
15+
$loop = React\EventLoop\Factory::create();
16+
$client = new Browser($loop);
17+
18+
$in = new ReadableResourceStream(STDIN, $loop);
19+
20+
$url = isset($argv[1]) ? $argv[1] : 'https://httpbin.org/post';
21+
echo 'Sending STDIN as POST to ' . $url . '' . PHP_EOL;
22+
23+
$client->post($url, array(), $in)->then(function (ResponseInterface $response) {
24+
echo 'Received' . PHP_EOL . Psr7\str($response);
25+
}, 'printf');
26+
27+
$loop->run();
File renamed without changes.
File renamed without changes.
File renamed without changes.

examples/09-json-api.php renamed to examples/59-server-json-api.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// Simple JSON-based HTTP API example as a base to build RESTful/RESTish APIs
44
// Launch demo and use your favorite CLI tool to test API requests
55
//
6-
// $ php examples/09-json-api.php 8080
6+
// $ php examples/59-server-json-api.php 8080
77
// $ curl -v http://localhost:8080/ -H 'Content-Type: application/json' -d '{"name":"Alice"}'
88

99
use Psr\Http\Message\ServerRequestInterface;

examples/12-upload.php renamed to examples/62-server-form-upload.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// Simple HTML form with file upload
44
// Launch demo and use your favorite browser or CLI tool to test form submissions
55
//
6-
// $ php examples/12-upload.php 8080
6+
// $ php examples/62-server-form-upload.php 8080
77
// $ curl --form name=test --form age=30 http://localhost:8080/
88
// $ curl --form name=hi --form [email protected] http://localhost:8080/
99

examples/21-http-proxy.php renamed to examples/71-server-http-proxy.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
<?php
22

3+
// $ php examples/71-server-http-proxy.php 8080
4+
// $ curl -v --proxy http://localhost:8080 http://reactphp.org/
5+
36
use Psr\Http\Message\RequestInterface;
47
use React\EventLoop\Factory;
58
use React\Http\Response;

examples/22-connect-proxy.php renamed to examples/72-server-http-connect-proxy.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
<?php
22

3+
// $ php examples/72-server-http-connect-proxy.php 8080
4+
// $ curl -v --proxy http://localhost:8080 https://reactphp.org/
5+
36
use Psr\Http\Message\ServerRequestInterface;
47
use React\EventLoop\Factory;
58
use React\Http\Response;
File renamed without changes.
File renamed without changes.

0 commit comments

Comments
 (0)