Skip to content

Commit

Permalink
Merge pull request #480 from clue-labs/request
Browse files Browse the repository at this point in the history
Add `Request` class to represent outgoing HTTP request message
  • Loading branch information
WyriHaximus authored Nov 24, 2022
2 parents 383f984 + 7a27c49 commit aa75bcd
Show file tree
Hide file tree
Showing 9 changed files with 149 additions and 16 deletions.
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ multiple concurrent HTTP requests without blocking.
* [json()](#json)
* [plaintext()](#plaintext)
* [xml()](#xml)
* [Request](#request-1)
* [ServerRequest](#serverrequest)
* [ResponseException](#responseexception)
* [React\Http\Middleware](#reacthttpmiddleware)
Expand Down Expand Up @@ -2628,6 +2629,24 @@ $response = React\Http\Message\Response::xml(
)->withStatus(React\Http\Message\Response::STATUS_BAD_REQUEST);
```

#### Request

The `React\Http\Message\Request` class can be used to
respresent an outgoing HTTP request message.

This class implements the
[PSR-7 `RequestInterface`](https://www.php-fig.org/psr/psr-7/#32-psrhttpmessagerequestinterface)
which extends the
[PSR-7 `MessageInterface`](https://www.php-fig.org/psr/psr-7/#31-psrhttpmessagemessageinterface).

This is mostly used internally to represent each outgoing HTTP request
message for the HTTP client implementation. Likewise, you can also use this
class with other HTTP client implementations and for tests.

> Internally, this implementation builds on top of an existing outgoing
request message and only adds support for streaming. This base class is
considered an implementation detail that may change in the future.

#### ServerRequest

The `React\Http\Message\ServerRequest` class can be used to
Expand Down
7 changes: 1 addition & 6 deletions src/Browser.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@
namespace React\Http;

use Psr\Http\Message\ResponseInterface;
use RingCentral\Psr7\Request;
use RingCentral\Psr7\Uri;
use React\EventLoop\Loop;
use React\EventLoop\LoopInterface;
use React\Http\Io\ReadableBodyStream;
use React\Http\Io\Sender;
use React\Http\Io\Transaction;
use React\Http\Message\Request;
use React\Promise\PromiseInterface;
use React\Socket\ConnectorInterface;
use React\Stream\ReadableStreamInterface;
Expand Down Expand Up @@ -838,10 +837,6 @@ private function requestMayBeStreaming($method, $url, array $headers = array(),
$url = Uri::resolve($this->baseUrl, $url);
}

if ($body instanceof ReadableStreamInterface) {
$body = new ReadableBodyStream($body);
}

foreach ($this->defaultHeaders as $key => $value) {
$explicitHeaderExists = false;
foreach (\array_keys($headers) as $headerKey) {
Expand Down
5 changes: 2 additions & 3 deletions src/Io/Transaction.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,13 @@
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\UriInterface;
use React\Http\Message\Response;
use RingCentral\Psr7\Request;
use RingCentral\Psr7\Uri;
use React\EventLoop\LoopInterface;
use React\Http\Message\Response;
use React\Http\Message\ResponseException;
use React\Promise\Deferred;
use React\Promise\PromiseInterface;
use React\Stream\ReadableStreamInterface;
use RingCentral\Psr7\Uri;

/**
* @internal
Expand Down
58 changes: 58 additions & 0 deletions src/Message/Request.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?php

namespace React\Http\Message;

use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\StreamInterface;
use Psr\Http\Message\UriInterface;
use React\Http\Io\BufferedBody;
use React\Http\Io\ReadableBodyStream;
use React\Stream\ReadableStreamInterface;
use RingCentral\Psr7\Request as BaseRequest;

/**
* Respresents an outgoing HTTP request message.
*
* This class implements the
* [PSR-7 `RequestInterface`](https://www.php-fig.org/psr/psr-7/#32-psrhttpmessagerequestinterface)
* which extends the
* [PSR-7 `MessageInterface`](https://www.php-fig.org/psr/psr-7/#31-psrhttpmessagemessageinterface).
*
* This is mostly used internally to represent each outgoing HTTP request
* message for the HTTP client implementation. Likewise, you can also use this
* class with other HTTP client implementations and for tests.
*
* > Internally, this implementation builds on top of an existing outgoing
* request message and only adds support for streaming. This base class is
* considered an implementation detail that may change in the future.
*
* @see RequestInterface
*/
final class Request extends BaseRequest implements RequestInterface
{
/**
* @param string $method HTTP method for the request.
* @param string|UriInterface $url URL for the request.
* @param array<string,string|string[]> $headers Headers for the message.
* @param string|ReadableStreamInterface|StreamInterface $body Message body.
* @param string $version HTTP protocol version.
* @throws \InvalidArgumentException for an invalid URL or body
*/
public function __construct(
$method,
$url,
array $headers = array(),
$body = '',
$version = '1.1'
) {
if (\is_string($body)) {
$body = new BufferedBody($body);
} elseif ($body instanceof ReadableStreamInterface && !$body instanceof StreamInterface) {
$body = new ReadableBodyStream($body);
} elseif (!$body instanceof StreamInterface) {
throw new \InvalidArgumentException('Invalid request body given');
}

parent::__construct($method, $url, $headers, $body, $version);
}
}
4 changes: 2 additions & 2 deletions src/Message/ServerRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
use React\Http\Io\BufferedBody;
use React\Http\Io\HttpBodyStream;
use React\Stream\ReadableStreamInterface;
use RingCentral\Psr7\Request;
use RingCentral\Psr7\Request as BaseRequest;

/**
* Respresents an incoming server request message.
Expand All @@ -30,7 +30,7 @@
*
* @see ServerRequestInterface
*/
final class ServerRequest extends Request implements ServerRequestInterface
final class ServerRequest extends BaseRequest implements ServerRequestInterface
{
private $attributes = array();

Expand Down
3 changes: 1 addition & 2 deletions tests/FunctionalBrowserTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,15 @@
use React\EventLoop\Loop;
use React\Http\Browser;
use React\Http\HttpServer;
use React\Http\Message\Response;
use React\Http\Message\ResponseException;
use React\Http\Middleware\StreamingRequestMiddleware;
use React\Http\Message\Response;
use React\Promise\Promise;
use React\Promise\Stream;
use React\Socket\Connector;
use React\Socket\SocketServer;
use React\Stream\ReadableStreamInterface;
use React\Stream\ThroughStream;
use RingCentral\Psr7\Request;

class FunctionalBrowserTest extends TestCase
{
Expand Down
2 changes: 1 addition & 1 deletion tests/Io/SenderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
use React\Http\Client\RequestData;
use React\Http\Io\ReadableBodyStream;
use React\Http\Io\Sender;
use React\Http\Message\Request;
use React\Promise;
use React\Stream\ThroughStream;
use React\Tests\Http\TestCase;
use RingCentral\Psr7\Request;

class SenderTest extends TestCase
{
Expand Down
4 changes: 2 additions & 2 deletions tests/Io/TransactionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@
use Psr\Http\Message\ResponseInterface;
use React\Http\Io\ReadableBodyStream;
use React\Http\Io\Transaction;
use React\Http\Message\Request;
use React\Http\Message\Response;
use React\Http\Message\ResponseException;
use React\EventLoop\Loop;
use React\Promise;
use React\Promise\Deferred;
use React\Stream\ThroughStream;
use React\Tests\Http\TestCase;
use RingCentral\Psr7\Request;
use RingCentral\Psr7\Response;

class TransactionTest extends TestCase
{
Expand Down
63 changes: 63 additions & 0 deletions tests/Message/RequestTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?php

namespace React\Tests\Http\Message;

use React\Http\Io\HttpBodyStream;
use React\Http\Message\Request;
use React\Stream\ThroughStream;
use React\Tests\Http\TestCase;

class RequestTest extends TestCase
{
public function testConstructWithStringRequestBodyReturnsStringBodyWithAutomaticSize()
{
$request = new Request(
'GET',
'http://localhost',
array(),
'foo'
);

$body = $request->getBody();
$this->assertSame(3, $body->getSize());
$this->assertEquals('foo', (string) $body);
}

public function testConstructWithStreamingRequestBodyReturnsBodyWhichImplementsReadableStreamInterfaceWithUnknownSize()
{
$request = new Request(
'GET',
'http://localhost',
array(),
new ThroughStream()
);

$body = $request->getBody();
$this->assertInstanceOf('Psr\Http\Message\StreamInterface', $body);
$this->assertInstanceOf('React\Stream\ReadableStreamInterface', $body);
$this->assertNull($body->getSize());
}

public function testConstructWithHttpBodyStreamReturnsBodyAsIs()
{
$request = new Request(
'GET',
'http://localhost',
array(),
$body = new HttpBodyStream(new ThroughStream(), 100)
);

$this->assertSame($body, $request->getBody());
}

public function testConstructWithNullBodyThrows()
{
$this->setExpectedException('InvalidArgumentException', 'Invalid request body given');
new Request(
'GET',
'http://localhost',
array(),
null
);
}
}

0 comments on commit aa75bcd

Please sign in to comment.