diff --git a/.travis.yml b/.travis.yml index d6e27d3f..347e0d1d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,7 +9,6 @@ cache: env: global: - COMPOSER_ARGS="--no-interaction" - - COVERAGE_DEPS="php-coveralls/php-coveralls" - LEGACY_DEPS="phpunit/phpunit" matrix: @@ -31,6 +30,7 @@ matrix: - DEPS=locked - CHECK_CS=true - TEST_COVERAGE=true + - INTEGRATION_DEPS="php-coveralls/php-coveralls" - php: 7 env: - DEPS=latest @@ -52,6 +52,10 @@ matrix: - php: 7.2 env: - DEPS=latest + - php: 7.2 + name: Integration tests + env: + - INTEGRATION_DEPS="http-interop/http-factory-diactoros" before_install: - if [[ $TEST_COVERAGE != 'true' && "$(php --version | grep xdebug -ci)" -ge 1 ]]; then phpenv config-rm xdebug.ini || return 0 ; fi @@ -62,7 +66,7 @@ install: - if [[ $TRAVIS_PHP_VERSION =~ ^5.6 ]]; then travis_retry composer update $COMPOSER_ARGS --with-dependencies $LEGACY_DEPS ; fi - if [[ $DEPS == 'latest' ]]; then travis_retry composer update $COMPOSER_ARGS ; fi - if [[ $DEPS == 'lowest' ]]; then travis_retry composer update --prefer-lowest --prefer-stable $COMPOSER_ARGS ; fi - - if [[ $TEST_COVERAGE == 'true' ]]; then travis_retry composer require --dev $COMPOSER_ARGS $COVERAGE_DEPS ; fi + - if [[ $INTEGRATION_DEPS != '' ]]; then travis_retry composer require --dev $COMPOSER_ARGS $INTEGRATION_DEPS ; fi - stty cols 120 && composer show script: diff --git a/CHANGELOG.md b/CHANGELOG.md index 408b2c2d..c7c76bf6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,49 @@ All notable changes to this project will be documented in this file, in reverse - Nothing. +## 1.8.6 - 2018-09-05 + +### Added + +- Nothing. + +### Changed + +- [#325](https://github.com/zendframework/zend-diactoros/pull/325) changes the behavior of `ServerRequest::withParsedBody()`. Per +- PSR-7, it now no longer allows values other than `null`, arrays, or objects. + +- [#325](https://github.com/zendframework/zend-diactoros/pull/325) changes the behavior of each of `Request`, `ServerRequest`, and + `Response` in relation to the validation of header values. Previously, we + allowed empty arrays to be provided via `withHeader()`; however, this was + contrary to the PSR-7 specification. Empty arrays are no longer allowed. + +### Deprecated + +- Nothing. + +### Removed + +- Nothing. + +### Fixed + +- [#325](https://github.com/zendframework/zend-diactoros/pull/325) ensures that `Uri::withUserInfo()` no longer ignores values of + `0` (numeric zero). + +- [#325](https://github.com/zendframework/zend-diactoros/pull/325) fixes how header values are merged when calling + `withAddedHeader()`, ensuring that array keys are ignored. + +## 1.8.5 - 2018-08-10 + +### Added + +- Nothing. + +### Changed + +- Nothing. + +<<<<<<< HEAD ## 1.8.6 - TBD ### Added @@ -56,6 +99,8 @@ All notable changes to this project will be documented in this file, in reverse - Nothing. +======= +>>>>>>> feature/325-integration-tests ### Deprecated - Nothing. diff --git a/composer.json b/composer.json index fd36a529..ddb91d96 100644 --- a/composer.json +++ b/composer.json @@ -30,6 +30,7 @@ "require-dev": { "ext-dom": "*", "ext-libxml": "*", + "php-http/psr7-integration-tests": "dev-master", "phpunit/phpunit": "^5.7.16 || ^6.0.8 || ^7.2.7", "zendframework/zend-coding-standard": "~1.0" }, diff --git a/composer.lock b/composer.lock index e1a6ce1f..261ae10c 100644 --- a/composer.lock +++ b/composer.lock @@ -1,11 +1,10 @@ { "_readme": [ "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "hash": "05aee370693f6857d599da36d8a0d865", - "content-hash": "2f426f134b2d07e6f2dc4a83e7feb0a1", + "content-hash": "7ca0087aabf01eb8dbf67e0ae741f2f2", "packages": [ { "name": "psr/http-message", @@ -55,7 +54,7 @@ "request", "response" ], - "time": "2016-08-06 14:39:51" + "time": "2016-08-06T14:39:51+00:00" } ], "packages-dev": [ @@ -111,7 +110,7 @@ "constructor", "instantiate" ], - "time": "2015-06-14 21:17:01" + "time": "2015-06-14T21:17:01+00:00" }, { "name": "myclabs/deep-copy", @@ -156,7 +155,7 @@ "object", "object graph" ], - "time": "2017-10-19 19:58:43" + "time": "2017-10-19T19:58:43+00:00" }, { "name": "phar-io/manifest", @@ -211,7 +210,7 @@ } ], "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", - "time": "2017-03-05 18:14:27" + "time": "2017-03-05T18:14:27+00:00" }, { "name": "phar-io/version", @@ -258,7 +257,62 @@ } ], "description": "Library for handling version information and constraints", - "time": "2017-03-05 17:38:23" + "time": "2017-03-05T17:38:23+00:00" + }, + { + "name": "php-http/psr7-integration-tests", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/php-http/psr7-integration-tests.git", + "reference": "5dfefb2da33ca24ae20c971b725c9a6fe7403008" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/psr7-integration-tests/zipball/5dfefb2da33ca24ae20c971b725c9a6fe7403008", + "reference": "5dfefb2da33ca24ae20c971b725c9a6fe7403008", + "shasum": "" + }, + "require": { + "php": "^5.4 || ^7.0", + "phpunit/phpunit": "^5.4 || ^6.0 || ^7.0", + "psr/http-message": "^1.0" + }, + "require-dev": { + "guzzlehttp/psr7": "^1.4", + "nyholm/psr7": "dev-master", + "ringcentral/psr7": "^1.2", + "slim/http": "^0.3", + "zendframework/zend-diactoros": "^1.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "Http\\Psr7Test\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com" + } + ], + "description": "Test suite for PSR7", + "homepage": "http://php-http.org", + "keywords": [ + "psr-7", + "test" + ], + "time": "2018-09-02T10:01:55+00:00" }, { "name": "phpdocumentor/reflection-common", @@ -312,7 +366,7 @@ "reflection", "static analysis" ], - "time": "2017-09-11 18:02:19" + "time": "2017-09-11T18:02:19+00:00" }, { "name": "phpdocumentor/reflection-docblock", @@ -363,7 +417,7 @@ } ], "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "time": "2017-11-30 07:14:17" + "time": "2017-11-30T07:14:17+00:00" }, { "name": "phpdocumentor/type-resolver", @@ -410,7 +464,7 @@ "email": "me@mikevanriel.com" } ], - "time": "2017-07-14 14:27:02" + "time": "2017-07-14T14:27:02+00:00" }, { "name": "phpspec/prophecy", @@ -473,7 +527,7 @@ "spy", "stub" ], - "time": "2018-04-18 13:57:24" + "time": "2018-04-18T13:57:24+00:00" }, { "name": "phpunit/php-code-coverage", @@ -536,7 +590,7 @@ "testing", "xunit" ], - "time": "2018-04-06 15:36:58" + "time": "2018-04-06T15:36:58+00:00" }, { "name": "phpunit/php-file-iterator", @@ -583,7 +637,7 @@ "filesystem", "iterator" ], - "time": "2017-11-27 13:52:08" + "time": "2017-11-27T13:52:08+00:00" }, { "name": "phpunit/php-text-template", @@ -624,7 +678,7 @@ "keywords": [ "template" ], - "time": "2015-06-21 13:50:34" + "time": "2015-06-21T13:50:34+00:00" }, { "name": "phpunit/php-timer", @@ -673,7 +727,7 @@ "keywords": [ "timer" ], - "time": "2017-02-26 11:10:40" + "time": "2017-02-26T11:10:40+00:00" }, { "name": "phpunit/php-token-stream", @@ -722,7 +776,7 @@ "keywords": [ "tokenizer" ], - "time": "2017-11-27 05:48:46" + "time": "2017-11-27T05:48:46+00:00" }, { "name": "phpunit/phpunit", @@ -806,7 +860,7 @@ "testing", "xunit" ], - "time": "2018-07-03 06:40:40" + "time": "2018-07-03T06:40:40+00:00" }, { "name": "phpunit/phpunit-mock-objects", @@ -865,7 +919,7 @@ "mock", "xunit" ], - "time": "2018-07-13 03:27:23" + "time": "2018-07-13T03:27:23+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", @@ -910,7 +964,7 @@ ], "description": "Looks up which function or method a line of code belongs to", "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", - "time": "2017-03-04 06:30:41" + "time": "2017-03-04T06:30:41+00:00" }, { "name": "sebastian/comparator", @@ -974,7 +1028,7 @@ "compare", "equality" ], - "time": "2018-02-01 13:46:46" + "time": "2018-02-01T13:46:46+00:00" }, { "name": "sebastian/diff", @@ -1026,7 +1080,7 @@ "keywords": [ "diff" ], - "time": "2017-08-03 08:09:46" + "time": "2017-08-03T08:09:46+00:00" }, { "name": "sebastian/environment", @@ -1076,7 +1130,7 @@ "environment", "hhvm" ], - "time": "2017-07-01 08:51:00" + "time": "2017-07-01T08:51:00+00:00" }, { "name": "sebastian/exporter", @@ -1143,7 +1197,7 @@ "export", "exporter" ], - "time": "2017-04-03 13:19:02" + "time": "2017-04-03T13:19:02+00:00" }, { "name": "sebastian/global-state", @@ -1194,7 +1248,7 @@ "keywords": [ "global state" ], - "time": "2017-04-27 15:39:26" + "time": "2017-04-27T15:39:26+00:00" }, { "name": "sebastian/object-enumerator", @@ -1241,7 +1295,7 @@ ], "description": "Traverses array structures and object graphs to enumerate all referenced objects", "homepage": "https://github.com/sebastianbergmann/object-enumerator/", - "time": "2017-08-03 12:35:26" + "time": "2017-08-03T12:35:26+00:00" }, { "name": "sebastian/object-reflector", @@ -1286,7 +1340,7 @@ ], "description": "Allows reflection of object attributes, including inherited and non-public ones", "homepage": "https://github.com/sebastianbergmann/object-reflector/", - "time": "2017-03-29 09:07:27" + "time": "2017-03-29T09:07:27+00:00" }, { "name": "sebastian/recursion-context", @@ -1339,7 +1393,7 @@ ], "description": "Provides functionality to recursively process PHP variables", "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "time": "2017-03-03 06:23:57" + "time": "2017-03-03T06:23:57+00:00" }, { "name": "sebastian/resource-operations", @@ -1381,7 +1435,7 @@ ], "description": "Provides a list of PHP built-in functions that operate on resources", "homepage": "https://www.github.com/sebastianbergmann/resource-operations", - "time": "2015-07-28 20:34:47" + "time": "2015-07-28T20:34:47+00:00" }, { "name": "sebastian/version", @@ -1424,7 +1478,7 @@ ], "description": "Library that helps with managing the version number of Git-hosted PHP projects", "homepage": "https://github.com/sebastianbergmann/version", - "time": "2016-10-03 07:35:21" + "time": "2016-10-03T07:35:21+00:00" }, { "name": "squizlabs/php_codesniffer", @@ -1502,7 +1556,7 @@ "phpcs", "standards" ], - "time": "2017-05-22 02:43:20" + "time": "2017-05-22T02:43:20+00:00" }, { "name": "theseer/tokenizer", @@ -1542,7 +1596,7 @@ } ], "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", - "time": "2017-04-07 12:08:54" + "time": "2017-04-07T12:08:54+00:00" }, { "name": "webmozart/assert", @@ -1592,7 +1646,7 @@ "check", "validate" ], - "time": "2018-01-29 19:49:41" + "time": "2018-01-29T19:49:41+00:00" }, { "name": "zendframework/zend-coding-standard", @@ -1621,12 +1675,14 @@ "Coding Standard", "zf" ], - "time": "2016-11-09 21:30:43" + "time": "2016-11-09T21:30:43+00:00" } ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": { + "php-http/psr7-integration-tests": 20 + }, "prefer-stable": false, "prefer-lowest": false, "platform": { diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 6de09f62..aa69fe9b 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -10,4 +10,13 @@ src + + + + + + + + + diff --git a/src/MessageTrait.php b/src/MessageTrait.php index d249d86a..6b83be46 100644 --- a/src/MessageTrait.php +++ b/src/MessageTrait.php @@ -385,11 +385,18 @@ private function filterHeaderValue($values) $values = [$values]; } + if ([] === $values) { + throw new InvalidArgumentException( + 'Invalid header value: must be a string or array of strings; ' + . 'cannot be an empty array' + ); + } + return array_map(function ($value) { HeaderSecurity::assertValid($value); return (string) $value; - }, $values); + }, array_values($values)); } /** diff --git a/src/ServerRequest.php b/src/ServerRequest.php index bf98cd32..8523d59e 100644 --- a/src/ServerRequest.php +++ b/src/ServerRequest.php @@ -180,6 +180,14 @@ public function getParsedBody() */ public function withParsedBody($data) { + if (! is_array($data) && ! is_object($data) && null !== $data) { + throw new InvalidArgumentException(sprintf( + '%s expects a null, array, or object argument; received %s', + __METHOD__, + gettype($data) + )); + } + $new = clone $this; $new->parsedBody = $data; return $new; diff --git a/src/Uri.php b/src/Uri.php index 1181468f..5dcfb0e2 100644 --- a/src/Uri.php +++ b/src/Uri.php @@ -291,7 +291,7 @@ public function withUserInfo($user, $password = null) } $info = $this->filterUserInfoPart($user); - if ($password) { + if (null !== $password) { $info .= ':' . $this->filterUserInfoPart($password); } diff --git a/test/Integration/RequestTest.php b/test/Integration/RequestTest.php new file mode 100644 index 00000000..8b82e198 --- /dev/null +++ b/test/Integration/RequestTest.php @@ -0,0 +1,28 @@ +write('foobar'); + + return new UploadedFile($stream, $stream->getSize(), UPLOAD_ERR_OK); + } +} diff --git a/test/Integration/UriTest.php b/test/Integration/UriTest.php new file mode 100644 index 00000000..f70392c3 --- /dev/null +++ b/test/Integration/UriTest.php @@ -0,0 +1,28 @@ +assertSame('Foo,Bar', $message2->getHeaderLine('X-Foo')); } - public function testHeaderExistsIfWithNoValues() - { - $message = $this->message->withHeader('X-Foo', []); - - $this->assertTrue($message->hasHeader('X-Foo')); - } - - public function testHeaderWithNoValues() - { - $message = $this->message->withHeader('X-Foo', []); - - $this->assertSame([], $message->getHeader('X-Foo')); - $this->assertSame('', $message->getHeaderLine('X-Foo')); - } - - public function testCanRemoveHeaders() { $message = $this->message->withHeader('X-Foo', 'Foo');