Skip to content
This repository was archived by the owner on Jan 30, 2020. It is now read-only.

Feature/http2 support #173

Closed
wants to merge 9 commits into from
Closed
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
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ All notable changes to this project will be documented in this file, in reverse

### Added

- Nothing.
- [#173](https://github.com/zendframework/zend-http/pull/173) adds support for HTTP/2 requests and responses.

### Changed

Expand Down
2 changes: 1 addition & 1 deletion docs/book/client/intro.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ Parameter | Description
`strictredirects` | Whether to strictly follow the RFC when redirecting (see this section) | boolean | FALSE
`useragent` | User agent identifier string (sent in request headers) | string | `Zend\Http\Client`
`timeout` | Connection timeout (seconds) | integer | 10
`httpversion` | HTTP protocol version (usually '1.1' or '1.0') | string | 1.1
`httpversion` | HTTP protocol version (usually '1.1', '1.0' or '2'; 2 is only supported starting in 2.10.0) | string | 1.1
`adapter` | Connection adapter class to use (see this section) | mixed | `Zend\Http\Client\Adapter\Socket`
`keepalive` | Whether to enable keep-alive connections with the server. Useful and might improve performance if several consecutive requests to the same server are performed. | boolean | FALSE
`storeresponse` | Whether to store last response for later retrieval with getLastResponse(). If set to FALSE, getLastResponse() will return NULL. | boolean | TRUE
Expand Down
2 changes: 1 addition & 1 deletion docs/book/request.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ Method signature | De
`setUri(string|Uri $uri) : self` | Set the URI/URL for this request; this can be a string or an instance of `Zend\Uri\Http`.
`getUri() : Uri` | Return the URI for this request object.
`getUriString() : string` | Return the URI for this request object as a string.
`setVersion(string $version) : self` | Set the HTTP version for this object, one of 1.0 or 1.1 (`Request::VERSION_10`, `Request::VERSION_11`).
`setVersion(string $version) : self` | Set the HTTP version for this object, one of 1.0, 1.1 or 2 (`Request::VERSION_10`, `Request::VERSION_11`, `Request::VERSION_2`). HTTP/2 support was added in zend-http 2.10.0.
`getVersion() : string` | Return the HTTP version for this request.
`setQuery(Parameters $query) : self` | Provide an alternate Parameter Container implementation for query parameters in this object. (This is NOT the primary API for value setting; for that, see `getQuery()`).
`getQuery(string|null $name, mixed|null $default) : null|string|Parameters` | Return the parameter container responsible for query parameters or a single query parameter based on `$name`.
Expand Down
4 changes: 2 additions & 2 deletions docs/book/response.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,8 @@ Method signature | Descrip
`renderStatusLine() : string` | Render the status line header
`setHeaders(Headers $headers) : self` | Provide an alternate Parameter Container implementation for headers in this object. (This is NOT the primary API for value setting; for that, see `getHeaders()`.)
`getHeaders() : Headers` | Return the container responsible for storing HTTP headers. This container exposes the primary API for manipulating headers set in the HTTP response. See the section on [Headers](headers.md) for more information.
`setVersion(string $version) : self` | Set the HTTP version for this object, one of 1.0 or 1.1 (`Request::VERSION_10`, `Request::VERSION_11`).
`getVersion() : string` | Return the HTTP version for this request.
`setVersion(string $version) : self` | Set the HTTP version for this object, one of 1.0, 1.1 or 2 (`Response::VERSION_10`, `Response::VERSION_11`, `Response::VERSION_2`). HTTP/2 support was added in zend-http 2.10.0.
`getVersion() : string` | Return the HTTP version for this response.
`setStatusCode(int $code) : self` | Set HTTP status code.
`getStatusCode() : int` | Retrieve HTTP status code.
`setReasonPhrase(string $reasonPhrase) : self` | Set custom HTTP status message.
Expand Down
9 changes: 5 additions & 4 deletions src/AbstractMessage.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ abstract class AbstractMessage extends Message
*/
const VERSION_10 = '1.0';
const VERSION_11 = '1.1';
const VERSION_2 = '2';
/**#@-*/

/**
Expand All @@ -34,16 +35,16 @@ abstract class AbstractMessage extends Message
protected $headers;

/**
* Set the HTTP version for this object, one of 1.0 or 1.1
* (AbstractMessage::VERSION_10, AbstractMessage::VERSION_11)
* Set the HTTP version for this object, one of 1.0, 1.1 or 2
* (AbstractMessage::VERSION_10, AbstractMessage::VERSION_11, AbstractMessage::VERSION_2)
*
* @param string $version (Must be 1.0 or 1.1)
* @param string $version (Must be 1.0, 1.1 or 2)
* @return AbstractMessage
* @throws Exception\InvalidArgumentException
*/
public function setVersion($version)
{
if ($version != self::VERSION_10 && $version != self::VERSION_11) {
if (! in_array($version, [self::VERSION_10, self::VERSION_11, self::VERSION_2])) {
throw new Exception\InvalidArgumentException(
'Not valid or not supported HTTP version: ' . $version
);
Expand Down
2 changes: 1 addition & 1 deletion src/Response.php
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ public static function fromString($string)
*/
protected function parseStatusLine($line)
{
$regex = '/^HTTP\/(?P<version>1\.[01]) (?P<status>\d{3})(?:[ ]+(?P<reason>.*))?$/';
$regex = '/^HTTP\/(?P<version>1\.[01]|2) (?P<status>\d{3})(?:[ ]+(?P<reason>.*))?$/';
$matches = [];
if (! preg_match($regex, $line, $matches)) {
throw new Exception\InvalidArgumentException(
Expand Down
72 changes: 64 additions & 8 deletions test/ResponseTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,79 @@

class ResponseTest extends TestCase
{
public function testResponseFactoryFromStringCreatesValidResponse()
public function validHttpVersions()
{
$string = 'HTTP/1.0 200 OK' . "\r\n\r\n" . 'Foo Bar';
yield 'http/1.0' => ['1.0'];
yield 'http/1.1' => ['1.1'];
yield 'http/2' => ['2'];
}

public function validResponseHttpVersionProvider()
{
$responseTemplate = "HTTP/%s 200 OK\r\n\r\nFoo Bar";
foreach ($this->validHttpVersions() as $testCase => $data) {
$version = array_shift($data);
yield $testCase => [
'response' => sprintf($responseTemplate, $version),
'expectedVersion' => $version,
'expectedStatus' => '200',
'expectedContent' => 'Foo Bar',
];
}
}

/**
* @dataProvider validResponseHttpVersionProvider
* @param string $string Response string
* @param string $expectedVersion
* @param string $expectedStatus
* @param string $expectedContent
*/
public function testResponseFactoryFromStringCreatesValidResponse(
$string,
$expectedVersion,
$expectedStatus,
$expectedContent
) {
$response = Response::fromString($string);
$this->assertEquals(200, $response->getStatusCode());
$this->assertEquals('Foo Bar', $response->getContent());
$this->assertEquals($expectedVersion, $response->getVersion());
$this->assertEquals($expectedStatus, $response->getStatusCode());
$this->assertEquals($expectedContent, $response->getContent());
}

public function testResponseCanRenderStatusLine()
/**
* @dataProvider validHttpVersions
* @param string $version
*/
public function testResponseCanRenderStatusLineUsingDefaultReasonPhrase($version)
{
$expected = sprintf('HTTP/%s 404 Not Found', $version);
$response = new Response();
$response->setVersion(1.1);
$response->setVersion($version);
$response->setStatusCode(Response::STATUS_CODE_404);
$this->assertEquals('HTTP/1.1 404 Not Found', $response->renderStatusLine());
$this->assertEquals($expected, $response->renderStatusLine());
}

/**
* @dataProvider validHttpVersions
* @param string $version
*/
public function testResponseCanRenderStatusLineUsingCustomReasonPhrase($version)
{
$expected = sprintf('HTTP/%s 404 Foo Bar', $version);
$response = new Response();
$response->setVersion($version);
$response->setStatusCode(Response::STATUS_CODE_404);
$response->setReasonPhrase('Foo Bar');
$this->assertEquals('HTTP/1.1 404 Foo Bar', $response->renderStatusLine());
$this->assertEquals($expected, $response->renderStatusLine());
}

public function testInvalidHTTP2VersionString()
{
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('A valid response status line was not found in the provided string');
$string = 'HTTP/2.0 200 OK' . "\r\n\r\n" . 'Foo Bar';
$response = \Zend\Http\Response::fromString($string);
}

public function testResponseUsesHeadersContainerByDefault()
Expand Down