Skip to content

Add Request class to represent outgoing HTTP request message #480

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
);
}
}