mirror of
https://github.com/netzbegruenung/user_saml.git
synced 2024-04-27 06:44:53 +02:00
only update Guzzle
Signed-off-by: Arthur Schiwon <blizzz@arthur-schiwon.de>
This commit is contained in:
parent
2e7da5c243
commit
9ac5588544
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"require-dev": {
|
||||
"behat/behat": "^3.3",
|
||||
"guzzlehttp/guzzle": "^6.2"
|
||||
"guzzlehttp/guzzle": "^6.3"
|
||||
}
|
||||
}
|
||||
|
|
92
tests/integration/composer.lock
generated
92
tests/integration/composer.lock
generated
|
@ -1,10 +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"
|
||||
],
|
||||
"content-hash": "66da188fa9ccc00a1dd1beb21e3fab71",
|
||||
"content-hash": "f0b4184dd0582f1a03bfc549bd3d1de0",
|
||||
"packages": [],
|
||||
"packages-dev": [
|
||||
{
|
||||
|
@ -217,32 +217,35 @@
|
|||
},
|
||||
{
|
||||
"name": "guzzlehttp/guzzle",
|
||||
"version": "6.2.2",
|
||||
"version": "6.3.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/guzzle/guzzle.git",
|
||||
"reference": "ebf29dee597f02f09f4d5bbecc68230ea9b08f60"
|
||||
"reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/ebf29dee597f02f09f4d5bbecc68230ea9b08f60",
|
||||
"reference": "ebf29dee597f02f09f4d5bbecc68230ea9b08f60",
|
||||
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/407b0cb880ace85c9b63c5f9551db498cb2d50ba",
|
||||
"reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"guzzlehttp/promises": "^1.0",
|
||||
"guzzlehttp/psr7": "^1.3.1",
|
||||
"guzzlehttp/psr7": "^1.4",
|
||||
"php": ">=5.5"
|
||||
},
|
||||
"require-dev": {
|
||||
"ext-curl": "*",
|
||||
"phpunit/phpunit": "^4.0",
|
||||
"phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0",
|
||||
"psr/log": "^1.0"
|
||||
},
|
||||
"suggest": {
|
||||
"psr/log": "Required for using the Log middleware"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "6.2-dev"
|
||||
"dev-master": "6.3-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
|
@ -275,7 +278,7 @@
|
|||
"rest",
|
||||
"web service"
|
||||
],
|
||||
"time": "2016-10-08T15:01:37+00:00"
|
||||
"time": "2018-04-22T15:46:56+00:00"
|
||||
},
|
||||
{
|
||||
"name": "guzzlehttp/promises",
|
||||
|
@ -330,32 +333,33 @@
|
|||
},
|
||||
{
|
||||
"name": "guzzlehttp/psr7",
|
||||
"version": "1.3.1",
|
||||
"version": "1.5.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/guzzle/psr7.git",
|
||||
"reference": "5c6447c9df362e8f8093bda8f5d8873fe5c7f65b"
|
||||
"reference": "9f83dded91781a01c63574e387eaa769be769115"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/guzzle/psr7/zipball/5c6447c9df362e8f8093bda8f5d8873fe5c7f65b",
|
||||
"reference": "5c6447c9df362e8f8093bda8f5d8873fe5c7f65b",
|
||||
"url": "https://api.github.com/repos/guzzle/psr7/zipball/9f83dded91781a01c63574e387eaa769be769115",
|
||||
"reference": "9f83dded91781a01c63574e387eaa769be769115",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.4.0",
|
||||
"psr/http-message": "~1.0"
|
||||
"psr/http-message": "~1.0",
|
||||
"ralouphie/getallheaders": "^2.0.5"
|
||||
},
|
||||
"provide": {
|
||||
"psr/http-message-implementation": "1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~4.0"
|
||||
"phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.8"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.4-dev"
|
||||
"dev-master": "1.5-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
|
@ -375,16 +379,24 @@
|
|||
"name": "Michael Dowling",
|
||||
"email": "mtdowling@gmail.com",
|
||||
"homepage": "https://github.com/mtdowling"
|
||||
},
|
||||
{
|
||||
"name": "Tobias Schultze",
|
||||
"homepage": "https://github.com/Tobion"
|
||||
}
|
||||
],
|
||||
"description": "PSR-7 message implementation",
|
||||
"description": "PSR-7 message implementation that also provides common utility methods",
|
||||
"keywords": [
|
||||
"http",
|
||||
"message",
|
||||
"psr-7",
|
||||
"request",
|
||||
"response",
|
||||
"stream",
|
||||
"uri"
|
||||
"uri",
|
||||
"url"
|
||||
],
|
||||
"time": "2016-06-24T23:00:38+00:00"
|
||||
"time": "2018-12-04T20:46:45+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/http-message",
|
||||
|
@ -483,6 +495,46 @@
|
|||
],
|
||||
"time": "2016-10-10T12:19:37+00:00"
|
||||
},
|
||||
{
|
||||
"name": "ralouphie/getallheaders",
|
||||
"version": "2.0.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/ralouphie/getallheaders.git",
|
||||
"reference": "5601c8a83fbba7ef674a7369456d12f1e0d0eafa"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/5601c8a83fbba7ef674a7369456d12f1e0d0eafa",
|
||||
"reference": "5601c8a83fbba7ef674a7369456d12f1e0d0eafa",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~3.7.0",
|
||||
"satooshi/php-coveralls": ">=1.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"files": [
|
||||
"src/getallheaders.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Ralph Khattar",
|
||||
"email": "ralph.khattar@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "A polyfill for getallheaders.",
|
||||
"time": "2016-02-11T07:05:27+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/class-loader",
|
||||
"version": "v3.2.1",
|
||||
|
|
|
@ -55,6 +55,7 @@ class ClassLoader
|
|||
private $classMap = array();
|
||||
private $classMapAuthoritative = false;
|
||||
private $missingClasses = array();
|
||||
private $apcuPrefix;
|
||||
|
||||
public function getPrefixes()
|
||||
{
|
||||
|
@ -271,6 +272,26 @@ class ClassLoader
|
|||
return $this->classMapAuthoritative;
|
||||
}
|
||||
|
||||
/**
|
||||
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
|
||||
*
|
||||
* @param string|null $apcuPrefix
|
||||
*/
|
||||
public function setApcuPrefix($apcuPrefix)
|
||||
{
|
||||
$this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The APCu prefix in use, or null if APCu caching is not enabled.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getApcuPrefix()
|
||||
{
|
||||
return $this->apcuPrefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers this instance as an autoloader.
|
||||
*
|
||||
|
@ -313,11 +334,6 @@ class ClassLoader
|
|||
*/
|
||||
public function findFile($class)
|
||||
{
|
||||
// work around for PHP 5.3.0 - 5.3.2 https://bugs.php.net/50731
|
||||
if ('\\' == $class[0]) {
|
||||
$class = substr($class, 1);
|
||||
}
|
||||
|
||||
// class map lookup
|
||||
if (isset($this->classMap[$class])) {
|
||||
return $this->classMap[$class];
|
||||
|
@ -325,6 +341,12 @@ class ClassLoader
|
|||
if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
|
||||
return false;
|
||||
}
|
||||
if (null !== $this->apcuPrefix) {
|
||||
$file = apcu_fetch($this->apcuPrefix.$class, $hit);
|
||||
if ($hit) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
||||
$file = $this->findFileWithExtension($class, '.php');
|
||||
|
||||
|
@ -333,6 +355,10 @@ class ClassLoader
|
|||
$file = $this->findFileWithExtension($class, '.hh');
|
||||
}
|
||||
|
||||
if (null !== $this->apcuPrefix) {
|
||||
apcu_add($this->apcuPrefix.$class, $file);
|
||||
}
|
||||
|
||||
if (false === $file) {
|
||||
// Remember that this class does not exist.
|
||||
$this->missingClasses[$class] = true;
|
||||
|
@ -348,10 +374,14 @@ class ClassLoader
|
|||
|
||||
$first = $class[0];
|
||||
if (isset($this->prefixLengthsPsr4[$first])) {
|
||||
foreach ($this->prefixLengthsPsr4[$first] as $prefix => $length) {
|
||||
if (0 === strpos($class, $prefix)) {
|
||||
foreach ($this->prefixDirsPsr4[$prefix] as $dir) {
|
||||
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) {
|
||||
$subPath = $class;
|
||||
while (false !== $lastPos = strrpos($subPath, '\\')) {
|
||||
$subPath = substr($subPath, 0, $lastPos);
|
||||
$search = $subPath . '\\';
|
||||
if (isset($this->prefixDirsPsr4[$search])) {
|
||||
$pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
|
||||
foreach ($this->prefixDirsPsr4[$search] as $dir) {
|
||||
if (file_exists($file = $dir . $pathEnd)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
|
2
tests/integration/vendor/composer/LICENSE
vendored
2
tests/integration/vendor/composer/LICENSE
vendored
|
@ -1,5 +1,5 @@
|
|||
|
||||
Copyright (c) 2016 Nils Adermann, Jordi Boggiano
|
||||
Copyright (c) Nils Adermann, Jordi Boggiano
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
|
@ -7,6 +7,7 @@ $baseDir = dirname($vendorDir);
|
|||
|
||||
return array(
|
||||
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
|
||||
'7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php',
|
||||
'c964ee0ededf28c96ebd9db5099ef910' => $vendorDir . '/guzzlehttp/promises/src/functions_include.php',
|
||||
'a0edc8309cc5e1d60e3047b5df6b7052' => $vendorDir . '/guzzlehttp/psr7/src/functions_include.php',
|
||||
'37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php',
|
||||
|
|
|
@ -8,6 +8,7 @@ class ComposerStaticInit2b078a63e93bc9e9825cefae96ca1eb3
|
|||
{
|
||||
public static $files = array (
|
||||
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
|
||||
'7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php',
|
||||
'c964ee0ededf28c96ebd9db5099ef910' => __DIR__ . '/..' . '/guzzlehttp/promises/src/functions_include.php',
|
||||
'a0edc8309cc5e1d60e3047b5df6b7052' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/functions_include.php',
|
||||
'37a3dc5111fe8f707ab4c132ef1dbc62' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/functions_include.php',
|
||||
|
|
1808
tests/integration/vendor/composer/installed.json
vendored
1808
tests/integration/vendor/composer/installed.json
vendored
File diff suppressed because it is too large
Load diff
|
@ -1,41 +0,0 @@
|
|||
language: php
|
||||
|
||||
sudo: false
|
||||
|
||||
php:
|
||||
- 5.5
|
||||
- 5.6
|
||||
- 7.0
|
||||
- 7.1
|
||||
- hhvm
|
||||
|
||||
before_script:
|
||||
- curl --version
|
||||
- composer install --no-interaction --prefer-source --dev
|
||||
- ~/.nvm/nvm.sh install v0.6.14
|
||||
- ~/.nvm/nvm.sh run v0.6.14
|
||||
- '[ "$TRAVIS_PHP_VERSION" != "7.0" ] || echo "xdebug.overload_var_dump = 1" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini'
|
||||
|
||||
script: make test
|
||||
|
||||
matrix:
|
||||
allow_failures:
|
||||
- php: hhvm
|
||||
fast_finish: true
|
||||
|
||||
before_deploy:
|
||||
- rvm 1.9.3 do gem install mime-types -v 2.6.2
|
||||
- make package
|
||||
|
||||
deploy:
|
||||
provider: releases
|
||||
api_key:
|
||||
secure: UpypqlYgsU68QT/x40YzhHXvzWjFwCNo9d+G8KAdm7U9+blFfcWhV1aMdzugvPMl6woXgvJj7qHq5tAL4v6oswCORhpSBfLgOQVFaica5LiHsvWlAedOhxGmnJqMTwuepjBCxXhs3+I8Kof1n4oUL9gKytXjOVCX/f7XU1HiinU=
|
||||
file:
|
||||
- build/artifacts/guzzle.phar
|
||||
- build/artifacts/guzzle.zip
|
||||
on:
|
||||
repo: guzzle/guzzle
|
||||
tags: true
|
||||
all_branches: true
|
||||
php: 5.5
|
|
@ -1,4 +1,52 @@
|
|||
# CHANGELOG
|
||||
# Change Log
|
||||
|
||||
## 6.3.3 - 2018-04-22
|
||||
|
||||
* Fix: Default headers when decode_content is specified
|
||||
|
||||
|
||||
## 6.3.2 - 2018-03-26
|
||||
|
||||
* Fix: Release process
|
||||
|
||||
|
||||
## 6.3.1 - 2018-03-26
|
||||
|
||||
* Bug fix: Parsing 0 epoch expiry times in cookies [#2014](https://github.com/guzzle/guzzle/pull/2014)
|
||||
* Improvement: Better ConnectException detection [#2012](https://github.com/guzzle/guzzle/pull/2012)
|
||||
* Bug fix: Malformed domain that contains a "/" [#1999](https://github.com/guzzle/guzzle/pull/1999)
|
||||
* Bug fix: Undefined offset when a cookie has no first key-value pair [#1998](https://github.com/guzzle/guzzle/pull/1998)
|
||||
* Improvement: Support PHPUnit 6 [#1953](https://github.com/guzzle/guzzle/pull/1953)
|
||||
* Bug fix: Support empty headers [#1915](https://github.com/guzzle/guzzle/pull/1915)
|
||||
* Bug fix: Ignore case during header modifications [#1916](https://github.com/guzzle/guzzle/pull/1916)
|
||||
|
||||
+ Minor code cleanups, documentation fixes and clarifications.
|
||||
|
||||
|
||||
## 6.3.0 - 2017-06-22
|
||||
|
||||
* Feature: force IP resolution (ipv4 or ipv6) [#1608](https://github.com/guzzle/guzzle/pull/1608), [#1659](https://github.com/guzzle/guzzle/pull/1659)
|
||||
* Improvement: Don't include summary in exception message when body is empty [#1621](https://github.com/guzzle/guzzle/pull/1621)
|
||||
* Improvement: Handle `on_headers` option in MockHandler [#1580](https://github.com/guzzle/guzzle/pull/1580)
|
||||
* Improvement: Added SUSE Linux CA path [#1609](https://github.com/guzzle/guzzle/issues/1609)
|
||||
* Improvement: Use class reference for getting the name of the class instead of using hardcoded strings [#1641](https://github.com/guzzle/guzzle/pull/1641)
|
||||
* Feature: Added `read_timeout` option [#1611](https://github.com/guzzle/guzzle/pull/1611)
|
||||
* Bug fix: PHP 7.x fixes [#1685](https://github.com/guzzle/guzzle/pull/1685), [#1686](https://github.com/guzzle/guzzle/pull/1686), [#1811](https://github.com/guzzle/guzzle/pull/1811)
|
||||
* Deprecation: BadResponseException instantiation without a response [#1642](https://github.com/guzzle/guzzle/pull/1642)
|
||||
* Feature: Added NTLM auth [#1569](https://github.com/guzzle/guzzle/pull/1569)
|
||||
* Feature: Track redirect HTTP status codes [#1711](https://github.com/guzzle/guzzle/pull/1711)
|
||||
* Improvement: Check handler type during construction [#1745](https://github.com/guzzle/guzzle/pull/1745)
|
||||
* Improvement: Always include the Content-Length if there's a body [#1721](https://github.com/guzzle/guzzle/pull/1721)
|
||||
* Feature: Added convenience method to access a cookie by name [#1318](https://github.com/guzzle/guzzle/pull/1318)
|
||||
* Bug fix: Fill `CURLOPT_CAPATH` and `CURLOPT_CAINFO` properly [#1684](https://github.com/guzzle/guzzle/pull/1684)
|
||||
* Improvement: Use `\GuzzleHttp\Promise\rejection_for` function instead of object init [#1827](https://github.com/guzzle/guzzle/pull/1827)
|
||||
|
||||
|
||||
+ Minor code cleanups, documentation fixes and clarifications.
|
||||
|
||||
## 6.2.3 - 2017-02-28
|
||||
|
||||
* Fix deprecations with guzzle/psr7 version 1.4
|
||||
|
||||
## 6.2.2 - 2016-10-08
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Copyright (c) 2011-2016 Michael Dowling, https://github.com/mtdowling <mtdowling@gmail.com>
|
||||
Copyright (c) 2011-2018 Michael Dowling, https://github.com/mtdowling <mtdowling@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
Guzzle, PHP HTTP client
|
||||
=======================
|
||||
|
||||
[![Build Status](https://travis-ci.org/guzzle/guzzle.svg?branch=master)](https://travis-ci.org/guzzle/guzzle)
|
||||
[![Latest Version](https://img.shields.io/github/release/guzzle/guzzle.svg?style=flat-square)](https://github.com/guzzle/guzzle/releases)
|
||||
[![Build Status](https://img.shields.io/travis/guzzle/guzzle.svg?style=flat-square)](https://travis-ci.org/guzzle/guzzle)
|
||||
[![Total Downloads](https://img.shields.io/packagist/dt/guzzlehttp/guzzle.svg?style=flat-square)](https://packagist.org/packages/guzzlehttp/guzzle)
|
||||
|
||||
Guzzle is a PHP HTTP client that makes it easy to send HTTP requests and
|
||||
trivial to integrate with web services.
|
||||
|
@ -19,15 +21,13 @@ trivial to integrate with web services.
|
|||
|
||||
```php
|
||||
$client = new \GuzzleHttp\Client();
|
||||
$res = $client->request('GET', 'https://api.github.com/user', [
|
||||
'auth' => ['user', 'pass']
|
||||
]);
|
||||
$res = $client->request('GET', 'https://api.github.com/repos/guzzle/guzzle');
|
||||
echo $res->getStatusCode();
|
||||
// 200
|
||||
echo $res->getHeaderLine('content-type');
|
||||
// 'application/json; charset=utf8'
|
||||
echo $res->getBody();
|
||||
// {"type":"User"...'
|
||||
// '{"id": 1420053, "name": "guzzle", ...}'
|
||||
|
||||
// Send an asynchronous request.
|
||||
$request = new \GuzzleHttp\Psr7\Request('GET', 'http://httpbin.org');
|
||||
|
@ -40,7 +40,7 @@ $promise->wait();
|
|||
## Help and docs
|
||||
|
||||
- [Documentation](http://guzzlephp.org/)
|
||||
- [stackoverflow](http://stackoverflow.com/questions/tagged/guzzle)
|
||||
- [Stack Overflow](http://stackoverflow.com/questions/tagged/guzzle)
|
||||
- [Gitter](https://gitter.im/guzzle/guzzle)
|
||||
|
||||
|
||||
|
@ -75,14 +75,15 @@ composer.phar update
|
|||
|
||||
## Version Guidance
|
||||
|
||||
| Version | Status | Packagist | Namespace | Repo | Docs | PSR-7 |
|
||||
|---------|-------------|---------------------|--------------|---------------------|---------------------|-------|
|
||||
| 3.x | EOL | `guzzle/guzzle` | `Guzzle` | [v3][guzzle-3-repo] | [v3][guzzle-3-docs] | No |
|
||||
| 4.x | EOL | `guzzlehttp/guzzle` | `GuzzleHttp` | N/A | N/A | No |
|
||||
| 5.x | Maintained | `guzzlehttp/guzzle` | `GuzzleHttp` | [v5][guzzle-5-repo] | [v5][guzzle-5-docs] | No |
|
||||
| 6.x | Latest | `guzzlehttp/guzzle` | `GuzzleHttp` | [v6][guzzle-6-repo] | [v6][guzzle-6-docs] | Yes |
|
||||
| Version | Status | Packagist | Namespace | Repo | Docs | PSR-7 | PHP Version |
|
||||
|---------|------------|---------------------|--------------|---------------------|---------------------|-------|-------------|
|
||||
| 3.x | EOL | `guzzle/guzzle` | `Guzzle` | [v3][guzzle-3-repo] | [v3][guzzle-3-docs] | No | >= 5.3.3 |
|
||||
| 4.x | EOL | `guzzlehttp/guzzle` | `GuzzleHttp` | [v4][guzzle-4-repo] | N/A | No | >= 5.4 |
|
||||
| 5.x | Maintained | `guzzlehttp/guzzle` | `GuzzleHttp` | [v5][guzzle-5-repo] | [v5][guzzle-5-docs] | No | >= 5.4 |
|
||||
| 6.x | Latest | `guzzlehttp/guzzle` | `GuzzleHttp` | [v6][guzzle-6-repo] | [v6][guzzle-6-docs] | Yes | >= 5.5 |
|
||||
|
||||
[guzzle-3-repo]: https://github.com/guzzle/guzzle3
|
||||
[guzzle-4-repo]: https://github.com/guzzle/guzzle/tree/4.x
|
||||
[guzzle-5-repo]: https://github.com/guzzle/guzzle/tree/5.3
|
||||
[guzzle-6-repo]: https://github.com/guzzle/guzzle
|
||||
[guzzle-3-docs]: http://guzzle3.readthedocs.org/en/latest/
|
||||
|
|
|
@ -14,12 +14,12 @@
|
|||
],
|
||||
"require": {
|
||||
"php": ">=5.5",
|
||||
"guzzlehttp/psr7": "^1.3.1",
|
||||
"guzzlehttp/psr7": "^1.4",
|
||||
"guzzlehttp/promises": "^1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"ext-curl": "*",
|
||||
"phpunit/phpunit": "^4.0",
|
||||
"phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0",
|
||||
"psr/log": "^1.0"
|
||||
},
|
||||
"autoload": {
|
||||
|
@ -33,9 +33,12 @@
|
|||
"GuzzleHttp\\Tests\\": "tests/"
|
||||
}
|
||||
},
|
||||
"suggest": {
|
||||
"psr/log": "Required for using the Log middleware"
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "6.2-dev"
|
||||
"dev-master": "6.3-dev"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,6 +63,8 @@ class Client implements ClientInterface
|
|||
{
|
||||
if (!isset($config['handler'])) {
|
||||
$config['handler'] = HandlerStack::create();
|
||||
} elseif (!is_callable($config['handler'])) {
|
||||
throw new \InvalidArgumentException('handler must be a callable');
|
||||
}
|
||||
|
||||
// Convert the base_uri to a UriInterface
|
||||
|
@ -142,7 +144,7 @@ class Client implements ClientInterface
|
|||
$uri = Psr7\uri_for($uri === null ? '' : $uri);
|
||||
|
||||
if (isset($config['base_uri'])) {
|
||||
$uri = Psr7\Uri::resolve(Psr7\uri_for($config['base_uri']), $uri);
|
||||
$uri = Psr7\UriResolver::resolve(Psr7\uri_for($config['base_uri']), $uri);
|
||||
}
|
||||
|
||||
return $uri->getScheme() === '' && $uri->getHost() !== '' ? $uri->withScheme('http') : $uri;
|
||||
|
@ -288,7 +290,14 @@ class Client implements ClientInterface
|
|||
*/
|
||||
private function applyOptions(RequestInterface $request, array &$options)
|
||||
{
|
||||
$modify = [];
|
||||
$modify = [
|
||||
'set_headers' => [],
|
||||
];
|
||||
|
||||
if (isset($options['headers'])) {
|
||||
$modify['set_headers'] = $options['headers'];
|
||||
unset($options['headers']);
|
||||
}
|
||||
|
||||
if (isset($options['form_params'])) {
|
||||
if (isset($options['multipart'])) {
|
||||
|
@ -300,6 +309,8 @@ class Client implements ClientInterface
|
|||
}
|
||||
$options['body'] = http_build_query($options['form_params'], '', '&');
|
||||
unset($options['form_params']);
|
||||
// Ensure that we don't have the header in different case and set the new value.
|
||||
$options['_conditional'] = Psr7\_caseless_remove(['Content-Type'], $options['_conditional']);
|
||||
$options['_conditional']['Content-Type'] = 'application/x-www-form-urlencoded';
|
||||
}
|
||||
|
||||
|
@ -311,24 +322,19 @@ class Client implements ClientInterface
|
|||
if (isset($options['json'])) {
|
||||
$options['body'] = \GuzzleHttp\json_encode($options['json']);
|
||||
unset($options['json']);
|
||||
// Ensure that we don't have the header in different case and set the new value.
|
||||
$options['_conditional'] = Psr7\_caseless_remove(['Content-Type'], $options['_conditional']);
|
||||
$options['_conditional']['Content-Type'] = 'application/json';
|
||||
}
|
||||
|
||||
if (!empty($options['decode_content'])
|
||||
&& $options['decode_content'] !== true
|
||||
) {
|
||||
// Ensure that we don't have the header in different case and set the new value.
|
||||
$options['_conditional'] = Psr7\_caseless_remove(['Accept-Encoding'], $options['_conditional']);
|
||||
$modify['set_headers']['Accept-Encoding'] = $options['decode_content'];
|
||||
}
|
||||
|
||||
if (isset($options['headers'])) {
|
||||
if (isset($modify['set_headers'])) {
|
||||
$modify['set_headers'] = $options['headers'] + $modify['set_headers'];
|
||||
} else {
|
||||
$modify['set_headers'] = $options['headers'];
|
||||
}
|
||||
unset($options['headers']);
|
||||
}
|
||||
|
||||
if (isset($options['body'])) {
|
||||
if (is_array($options['body'])) {
|
||||
$this->invalidBody();
|
||||
|
@ -342,6 +348,8 @@ class Client implements ClientInterface
|
|||
$type = isset($value[2]) ? strtolower($value[2]) : 'basic';
|
||||
switch ($type) {
|
||||
case 'basic':
|
||||
// Ensure that we don't have the header in different case and set the new value.
|
||||
$modify['set_headers'] = Psr7\_caseless_remove(['Authorization'], $modify['set_headers']);
|
||||
$modify['set_headers']['Authorization'] = 'Basic '
|
||||
. base64_encode("$value[0]:$value[1]");
|
||||
break;
|
||||
|
@ -350,6 +358,10 @@ class Client implements ClientInterface
|
|||
$options['curl'][CURLOPT_HTTPAUTH] = CURLAUTH_DIGEST;
|
||||
$options['curl'][CURLOPT_USERPWD] = "$value[0]:$value[1]";
|
||||
break;
|
||||
case 'ntlm':
|
||||
$options['curl'][CURLOPT_HTTPAUTH] = CURLAUTH_NTLM;
|
||||
$options['curl'][CURLOPT_USERPWD] = "$value[0]:$value[1]";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -376,6 +388,8 @@ class Client implements ClientInterface
|
|||
$request = Psr7\modify_request($request, $modify);
|
||||
if ($request->getBody() instanceof Psr7\MultipartStream) {
|
||||
// Use a multipart/form-data POST if a Content-Type is not set.
|
||||
// Ensure that we don't have the header in different case and set the new value.
|
||||
$options['_conditional'] = Psr7\_caseless_remove(['Content-Type'], $options['_conditional']);
|
||||
$options['_conditional']['Content-Type'] = 'multipart/form-data; boundary='
|
||||
. $request->getBody()->getBoundary();
|
||||
}
|
||||
|
@ -402,7 +416,7 @@ class Client implements ClientInterface
|
|||
throw new \InvalidArgumentException('Passing in the "body" request '
|
||||
. 'option as an array to send a POST request has been deprecated. '
|
||||
. 'Please use the "form_params" request option to send a '
|
||||
. 'application/x-www-form-urlencoded request, or a the "multipart" '
|
||||
. 'application/x-www-form-urlencoded request, or the "multipart" '
|
||||
. 'request option to send a multipart/form-data request.');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ use Psr\Http\Message\UriInterface;
|
|||
*/
|
||||
interface ClientInterface
|
||||
{
|
||||
const VERSION = '6.2.1';
|
||||
const VERSION = '6.3.3';
|
||||
|
||||
/**
|
||||
* Send an HTTP request.
|
||||
|
|
|
@ -86,6 +86,25 @@ class CookieJar implements CookieJarInterface
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds and returns the cookie based on the name
|
||||
*
|
||||
* @param string $name cookie name to search for
|
||||
* @return SetCookie|null cookie that was found or null if not found
|
||||
*/
|
||||
public function getCookieByName($name)
|
||||
{
|
||||
// don't allow a null name
|
||||
if ($name === null) {
|
||||
return null;
|
||||
}
|
||||
foreach ($this->cookies as $cookie) {
|
||||
if ($cookie->getName() !== null && strcasecmp($cookie->getName(), $name) === 0) {
|
||||
return $cookie;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function toArray()
|
||||
{
|
||||
return array_map(function (SetCookie $cookie) {
|
||||
|
@ -216,11 +235,41 @@ class CookieJar implements CookieJarInterface
|
|||
if (!$sc->getDomain()) {
|
||||
$sc->setDomain($request->getUri()->getHost());
|
||||
}
|
||||
if (0 !== strpos($sc->getPath(), '/')) {
|
||||
$sc->setPath($this->getCookiePathFromRequest($request));
|
||||
}
|
||||
$this->setCookie($sc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes cookie path following RFC 6265 section 5.1.4
|
||||
*
|
||||
* @link https://tools.ietf.org/html/rfc6265#section-5.1.4
|
||||
*
|
||||
* @param RequestInterface $request
|
||||
* @return string
|
||||
*/
|
||||
private function getCookiePathFromRequest(RequestInterface $request)
|
||||
{
|
||||
$uriPath = $request->getUri()->getPath();
|
||||
if ('' === $uriPath) {
|
||||
return '/';
|
||||
}
|
||||
if (0 !== strpos($uriPath, '/')) {
|
||||
return '/';
|
||||
}
|
||||
if ('/' === $uriPath) {
|
||||
return '/';
|
||||
}
|
||||
if (0 === $lastSlashPos = strrpos($uriPath, '/')) {
|
||||
return '/';
|
||||
}
|
||||
|
||||
return substr($uriPath, 0, $lastSlashPos);
|
||||
}
|
||||
|
||||
public function withCookieHeader(RequestInterface $request)
|
||||
{
|
||||
$values = [];
|
||||
|
|
|
@ -15,7 +15,7 @@ class SessionCookieJar extends CookieJar
|
|||
/**
|
||||
* Create a new SessionCookieJar object
|
||||
*
|
||||
* @param string $sessionKey Session key name to store the cookie
|
||||
* @param string $sessionKey Session key name to store the cookie
|
||||
* data in session
|
||||
* @param bool $storeSessionCookies Set to true to store session cookies
|
||||
* in the cookie jar.
|
||||
|
|
|
@ -35,14 +35,13 @@ class SetCookie
|
|||
$data = self::$defaults;
|
||||
// Explode the cookie string using a series of semicolons
|
||||
$pieces = array_filter(array_map('trim', explode(';', $cookie)));
|
||||
// The name of the cookie (first kvp) must include an equal sign.
|
||||
if (empty($pieces) || !strpos($pieces[0], '=')) {
|
||||
// The name of the cookie (first kvp) must exist and include an equal sign.
|
||||
if (empty($pieces[0]) || !strpos($pieces[0], '=')) {
|
||||
return new self($data);
|
||||
}
|
||||
|
||||
// Add the cookie pieces into the parsed data array
|
||||
foreach ($pieces as $part) {
|
||||
|
||||
$cookieParts = explode('=', $part, 2);
|
||||
$key = trim($cookieParts[0]);
|
||||
$value = isset($cookieParts[1])
|
||||
|
@ -349,7 +348,7 @@ class SetCookie
|
|||
return false;
|
||||
}
|
||||
|
||||
return (bool) preg_match('/\.' . preg_quote($cookieDomain) . '$/', $domain);
|
||||
return (bool) preg_match('/\.' . preg_quote($cookieDomain, '/') . '$/', $domain);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -359,7 +358,7 @@ class SetCookie
|
|||
*/
|
||||
public function isExpired()
|
||||
{
|
||||
return $this->getExpires() && time() > $this->getExpires();
|
||||
return $this->getExpires() !== null && time() > $this->getExpires();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -378,8 +377,8 @@ class SetCookie
|
|||
// Check if any of the invalid characters are present in the cookie name
|
||||
if (preg_match(
|
||||
'/[\x00-\x20\x22\x28-\x29\x2c\x2f\x3a-\x40\x5c\x7b\x7d\x7f]/',
|
||||
$name)
|
||||
) {
|
||||
$name
|
||||
)) {
|
||||
return 'Cookie name must not contain invalid characters: ASCII '
|
||||
. 'Control characters (0-31;127), space, tab and the '
|
||||
. 'following characters: ()<>@,;:\"/?={}';
|
||||
|
|
|
@ -1,7 +1,27 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Exception;
|
||||
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
/**
|
||||
* Exception when an HTTP error occurs (4xx or 5xx error)
|
||||
*/
|
||||
class BadResponseException extends RequestException {}
|
||||
class BadResponseException extends RequestException
|
||||
{
|
||||
public function __construct(
|
||||
$message,
|
||||
RequestInterface $request,
|
||||
ResponseInterface $response = null,
|
||||
\Exception $previous = null,
|
||||
array $handlerContext = []
|
||||
) {
|
||||
if (null === $response) {
|
||||
@trigger_error(
|
||||
'Instantiating the ' . __CLASS__ . ' class without a Response is deprecated since version 6.3 and will be removed in 7.0.',
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
}
|
||||
parent::__construct($message, $request, $response, $previous, $handlerContext);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,13 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Exception;
|
||||
|
||||
/**
|
||||
* @method string getMessage()
|
||||
* @method \Throwable|null getPrevious()
|
||||
* @method mixed getCode()
|
||||
* @method string getFile()
|
||||
* @method int getLine()
|
||||
* @method array getTrace()
|
||||
* @method string getTraceAsString()
|
||||
*/
|
||||
interface GuzzleException {}
|
||||
|
|
|
@ -81,10 +81,10 @@ class RequestException extends TransferException
|
|||
$level = (int) floor($response->getStatusCode() / 100);
|
||||
if ($level === 4) {
|
||||
$label = 'Client error';
|
||||
$className = __NAMESPACE__ . '\\ClientException';
|
||||
$className = ClientException::class;
|
||||
} elseif ($level === 5) {
|
||||
$label = 'Server error';
|
||||
$className = __NAMESPACE__ . '\\ServerException';
|
||||
$className = ServerException::class;
|
||||
} else {
|
||||
$label = 'Unsuccessful request';
|
||||
$className = __CLASS__;
|
||||
|
@ -93,13 +93,15 @@ class RequestException extends TransferException
|
|||
$uri = $request->getUri();
|
||||
$uri = static::obfuscateUri($uri);
|
||||
|
||||
// Server Error: `GET /` resulted in a `404 Not Found` response:
|
||||
// Client Error: `GET /` resulted in a `404 Not Found` response:
|
||||
// <html> ... (truncated)
|
||||
$message = sprintf(
|
||||
'%s: `%s` resulted in a `%s` response',
|
||||
'%s: `%s %s` resulted in a `%s %s` response',
|
||||
$label,
|
||||
$request->getMethod() . ' ' . $uri,
|
||||
$response->getStatusCode() . ' ' . $response->getReasonPhrase()
|
||||
$request->getMethod(),
|
||||
$uri,
|
||||
$response->getStatusCode(),
|
||||
$response->getReasonPhrase()
|
||||
);
|
||||
|
||||
$summary = static::getResponseBodySummary($response);
|
||||
|
@ -129,6 +131,11 @@ class RequestException extends TransferException
|
|||
}
|
||||
|
||||
$size = $body->getSize();
|
||||
|
||||
if ($size === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$summary = $body->read(120);
|
||||
$body->rewind();
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@ namespace GuzzleHttp\Handler;
|
|||
use GuzzleHttp\Exception\RequestException;
|
||||
use GuzzleHttp\Exception\ConnectException;
|
||||
use GuzzleHttp\Promise\FulfilledPromise;
|
||||
use GuzzleHttp\Promise\RejectedPromise;
|
||||
use GuzzleHttp\Psr7;
|
||||
use GuzzleHttp\Psr7\LazyOpenStream;
|
||||
use GuzzleHttp\TransferStats;
|
||||
|
@ -16,7 +15,7 @@ use Psr\Http\Message\RequestInterface;
|
|||
class CurlFactory implements CurlFactoryInterface
|
||||
{
|
||||
/** @var array */
|
||||
private $handles;
|
||||
private $handles = [];
|
||||
|
||||
/** @var int Total number of idle handles to keep in cache */
|
||||
private $maxHandles;
|
||||
|
@ -163,7 +162,7 @@ class CurlFactory implements CurlFactoryInterface
|
|||
// If an exception was encountered during the onHeaders event, then
|
||||
// return a rejected promise that wraps that exception.
|
||||
if ($easy->onHeadersException) {
|
||||
return new RejectedPromise(
|
||||
return \GuzzleHttp\Promise\rejection_for(
|
||||
new RequestException(
|
||||
'An error was encountered during the on_headers event',
|
||||
$easy->request,
|
||||
|
@ -186,7 +185,7 @@ class CurlFactory implements CurlFactoryInterface
|
|||
? new ConnectException($message, $easy->request, null, $ctx)
|
||||
: new RequestException($message, $easy->request, $easy->response, null, $ctx);
|
||||
|
||||
return new RejectedPromise($error);
|
||||
return \GuzzleHttp\Promise\rejection_for($error);
|
||||
}
|
||||
|
||||
private function getDefaultConf(EasyHandle $easy)
|
||||
|
@ -288,7 +287,14 @@ class CurlFactory implements CurlFactoryInterface
|
|||
{
|
||||
foreach ($conf['_headers'] as $name => $values) {
|
||||
foreach ($values as $value) {
|
||||
$conf[CURLOPT_HTTPHEADER][] = "$name: $value";
|
||||
$value = (string) $value;
|
||||
if ($value === '') {
|
||||
// cURL requires a special format for empty headers.
|
||||
// See https://github.com/guzzle/guzzle/issues/1882 for more details.
|
||||
$conf[CURLOPT_HTTPHEADER][] = "$name;";
|
||||
} else {
|
||||
$conf[CURLOPT_HTTPHEADER][] = "$name: $value";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -326,12 +332,20 @@ class CurlFactory implements CurlFactoryInterface
|
|||
$conf[CURLOPT_SSL_VERIFYHOST] = 2;
|
||||
$conf[CURLOPT_SSL_VERIFYPEER] = true;
|
||||
if (is_string($options['verify'])) {
|
||||
$conf[CURLOPT_CAINFO] = $options['verify'];
|
||||
// Throw an error if the file/folder/link path is not valid or doesn't exist.
|
||||
if (!file_exists($options['verify'])) {
|
||||
throw new \InvalidArgumentException(
|
||||
"SSL CA bundle not found: {$options['verify']}"
|
||||
);
|
||||
}
|
||||
// If it's a directory or a link to a directory use CURLOPT_CAPATH.
|
||||
// If not, it's probably a file, or a link to a file, so use CURLOPT_CAINFO.
|
||||
if (is_dir($options['verify']) ||
|
||||
(is_link($options['verify']) && is_dir(readlink($options['verify'])))) {
|
||||
$conf[CURLOPT_CAPATH] = $options['verify'];
|
||||
} else {
|
||||
$conf[CURLOPT_CAINFO] = $options['verify'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -370,15 +384,30 @@ class CurlFactory implements CurlFactoryInterface
|
|||
$conf[CURLOPT_FILE] = fopen('php://temp', 'w+');
|
||||
$easy->sink = Psr7\stream_for($conf[CURLOPT_FILE]);
|
||||
}
|
||||
|
||||
$timeoutRequiresNoSignal = false;
|
||||
if (isset($options['timeout'])) {
|
||||
$timeoutRequiresNoSignal |= $options['timeout'] < 1;
|
||||
$conf[CURLOPT_TIMEOUT_MS] = $options['timeout'] * 1000;
|
||||
}
|
||||
|
||||
// CURL default value is CURL_IPRESOLVE_WHATEVER
|
||||
if (isset($options['force_ip_resolve'])) {
|
||||
if ('v4' === $options['force_ip_resolve']) {
|
||||
$conf[CURLOPT_IPRESOLVE] = CURL_IPRESOLVE_V4;
|
||||
} elseif ('v6' === $options['force_ip_resolve']) {
|
||||
$conf[CURLOPT_IPRESOLVE] = CURL_IPRESOLVE_V6;
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($options['connect_timeout'])) {
|
||||
$timeoutRequiresNoSignal |= $options['connect_timeout'] < 1;
|
||||
$conf[CURLOPT_CONNECTTIMEOUT_MS] = $options['connect_timeout'] * 1000;
|
||||
}
|
||||
|
||||
if ($timeoutRequiresNoSignal && strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN') {
|
||||
$conf[CURLOPT_NOSIGNAL] = true;
|
||||
}
|
||||
|
||||
if (isset($options['proxy'])) {
|
||||
if (!is_array($options['proxy'])) {
|
||||
$conf[CURLOPT_PROXY] = $options['proxy'];
|
||||
|
|
|
@ -65,7 +65,9 @@ class CurlMultiHandler
|
|||
|
||||
$promise = new Promise(
|
||||
[$this, 'execute'],
|
||||
function () use ($id) { return $this->cancel($id); }
|
||||
function () use ($id) {
|
||||
return $this->cancel($id);
|
||||
}
|
||||
);
|
||||
|
||||
$this->addRequest(['easy' => $easy, 'deferred' => $promise]);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Handler;
|
||||
|
||||
use GuzzleHttp\Exception\RequestException;
|
||||
use GuzzleHttp\HandlerStack;
|
||||
use GuzzleHttp\Promise\PromiseInterface;
|
||||
use GuzzleHttp\Promise\RejectedPromise;
|
||||
|
@ -13,7 +14,7 @@ use Psr\Http\Message\ResponseInterface;
|
|||
*/
|
||||
class MockHandler implements \Countable
|
||||
{
|
||||
private $queue;
|
||||
private $queue = [];
|
||||
private $lastRequest;
|
||||
private $lastOptions;
|
||||
private $onFulfilled;
|
||||
|
@ -73,12 +74,24 @@ class MockHandler implements \Countable
|
|||
$this->lastOptions = $options;
|
||||
$response = array_shift($this->queue);
|
||||
|
||||
if (isset($options['on_headers'])) {
|
||||
if (!is_callable($options['on_headers'])) {
|
||||
throw new \InvalidArgumentException('on_headers must be callable');
|
||||
}
|
||||
try {
|
||||
$options['on_headers']($response);
|
||||
} catch (\Exception $e) {
|
||||
$msg = 'An error was encountered during the on_headers event';
|
||||
$response = new RequestException($msg, $request, $response, $e);
|
||||
}
|
||||
}
|
||||
|
||||
if (is_callable($response)) {
|
||||
$response = call_user_func($response, $request, $options);
|
||||
}
|
||||
|
||||
$response = $response instanceof \Exception
|
||||
? new RejectedPromise($response)
|
||||
? \GuzzleHttp\Promise\rejection_for($response)
|
||||
: \GuzzleHttp\Promise\promise_for($response);
|
||||
|
||||
return $response->then(
|
||||
|
@ -107,7 +120,7 @@ class MockHandler implements \Countable
|
|||
if ($this->onRejected) {
|
||||
call_user_func($this->onRejected, $reason);
|
||||
}
|
||||
return new RejectedPromise($reason);
|
||||
return \GuzzleHttp\Promise\rejection_for($reason);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -145,7 +158,7 @@ class MockHandler implements \Countable
|
|||
/**
|
||||
* Get the last received request options.
|
||||
*
|
||||
* @return RequestInterface
|
||||
* @return array
|
||||
*/
|
||||
public function getLastOptions()
|
||||
{
|
||||
|
|
|
@ -4,7 +4,6 @@ namespace GuzzleHttp\Handler;
|
|||
use GuzzleHttp\Exception\RequestException;
|
||||
use GuzzleHttp\Exception\ConnectException;
|
||||
use GuzzleHttp\Promise\FulfilledPromise;
|
||||
use GuzzleHttp\Promise\RejectedPromise;
|
||||
use GuzzleHttp\Promise\PromiseInterface;
|
||||
use GuzzleHttp\Psr7;
|
||||
use GuzzleHttp\TransferStats;
|
||||
|
@ -61,13 +60,14 @@ class StreamHandler
|
|||
if (strpos($message, 'getaddrinfo') // DNS lookup failed
|
||||
|| strpos($message, 'Connection refused')
|
||||
|| strpos($message, "couldn't connect to host") // error on HHVM
|
||||
|| strpos($message, "connection attempt failed")
|
||||
) {
|
||||
$e = new ConnectException($e->getMessage(), $request, $e);
|
||||
}
|
||||
$e = RequestException::wrapException($request, $e);
|
||||
$this->invokeStats($options, $request, $startTime, null, $e);
|
||||
|
||||
return new RejectedPromise($e);
|
||||
return \GuzzleHttp\Promise\rejection_for($e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -103,7 +103,7 @@ class StreamHandler
|
|||
$status = $parts[1];
|
||||
$reason = isset($parts[2]) ? $parts[2] : null;
|
||||
$headers = \GuzzleHttp\headers_from_lines($hdrs);
|
||||
list ($stream, $headers) = $this->checkDecode($options, $headers, $stream);
|
||||
list($stream, $headers) = $this->checkDecode($options, $headers, $stream);
|
||||
$stream = Psr7\stream_for($stream);
|
||||
$sink = $stream;
|
||||
|
||||
|
@ -119,7 +119,7 @@ class StreamHandler
|
|||
} catch (\Exception $e) {
|
||||
$msg = 'An error was encountered during the on_headers event';
|
||||
$ex = new RequestException($msg, $request, $response, $e);
|
||||
return new RejectedPromise($ex);
|
||||
return \GuzzleHttp\Promise\rejection_for($ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -276,7 +276,7 @@ class StreamHandler
|
|||
}
|
||||
|
||||
$params = [];
|
||||
$context = $this->getDefaultContext($request, $options);
|
||||
$context = $this->getDefaultContext($request);
|
||||
|
||||
if (isset($options['on_headers']) && !is_callable($options['on_headers'])) {
|
||||
throw new \InvalidArgumentException('on_headers must be callable');
|
||||
|
@ -301,6 +301,17 @@ class StreamHandler
|
|||
);
|
||||
}
|
||||
|
||||
// Microsoft NTLM authentication only supported with curl handler
|
||||
if (isset($options['auth'])
|
||||
&& is_array($options['auth'])
|
||||
&& isset($options['auth'][2])
|
||||
&& 'ntlm' == $options['auth'][2]
|
||||
) {
|
||||
throw new \InvalidArgumentException('Microsoft NTLM authentication only supported with curl handler');
|
||||
}
|
||||
|
||||
$uri = $this->resolveHost($request, $options);
|
||||
|
||||
$context = $this->createResource(
|
||||
function () use ($context, $params) {
|
||||
return stream_context_create($context, $params);
|
||||
|
@ -308,14 +319,45 @@ class StreamHandler
|
|||
);
|
||||
|
||||
return $this->createResource(
|
||||
function () use ($request, &$http_response_header, $context) {
|
||||
$resource = fopen((string) $request->getUri()->withFragment(''), 'r', null, $context);
|
||||
function () use ($uri, &$http_response_header, $context, $options) {
|
||||
$resource = fopen((string) $uri, 'r', null, $context);
|
||||
$this->lastHeaders = $http_response_header;
|
||||
|
||||
if (isset($options['read_timeout'])) {
|
||||
$readTimeout = $options['read_timeout'];
|
||||
$sec = (int) $readTimeout;
|
||||
$usec = ($readTimeout - $sec) * 100000;
|
||||
stream_set_timeout($resource, $sec, $usec);
|
||||
}
|
||||
|
||||
return $resource;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private function resolveHost(RequestInterface $request, array $options)
|
||||
{
|
||||
$uri = $request->getUri();
|
||||
|
||||
if (isset($options['force_ip_resolve']) && !filter_var($uri->getHost(), FILTER_VALIDATE_IP)) {
|
||||
if ('v4' === $options['force_ip_resolve']) {
|
||||
$records = dns_get_record($uri->getHost(), DNS_A);
|
||||
if (!isset($records[0]['ip'])) {
|
||||
throw new ConnectException(sprintf("Could not resolve IPv4 address for host '%s'", $uri->getHost()), $request);
|
||||
}
|
||||
$uri = $uri->withHost($records[0]['ip']);
|
||||
} elseif ('v6' === $options['force_ip_resolve']) {
|
||||
$records = dns_get_record($uri->getHost(), DNS_AAAA);
|
||||
if (!isset($records[0]['ipv6'])) {
|
||||
throw new ConnectException(sprintf("Could not resolve IPv6 address for host '%s'", $uri->getHost()), $request);
|
||||
}
|
||||
$uri = $uri->withHost('[' . $records[0]['ipv6'] . ']');
|
||||
}
|
||||
}
|
||||
|
||||
return $uri;
|
||||
}
|
||||
|
||||
private function getDefaultContext(RequestInterface $request)
|
||||
{
|
||||
$headers = '';
|
||||
|
|
|
@ -22,7 +22,7 @@ class HandlerStack
|
|||
* Creates a default handler stack that can be used by clients.
|
||||
*
|
||||
* The returned handler will wrap the provided handler or use the most
|
||||
* appropriate default handler for you system. The returned HandlerStack has
|
||||
* appropriate default handler for your system. The returned HandlerStack has
|
||||
* support for cookies, redirects, HTTP error exceptions, and preparing a body
|
||||
* before sending.
|
||||
*
|
||||
|
|
|
@ -19,7 +19,6 @@ use Psr\Http\Message\ResponseInterface;
|
|||
* - {host}: Host of the request
|
||||
* - {method}: Method of the request
|
||||
* - {uri}: URI of the request
|
||||
* - {host}: Host of the request
|
||||
* - {version}: Protocol version
|
||||
* - {target}: Request target of the request (path + query + fragment)
|
||||
* - {hostname}: Hostname of the machine that sent the request
|
||||
|
@ -74,7 +73,6 @@ class MessageFormatter
|
|||
return preg_replace_callback(
|
||||
'/{\s*([A-Za-z_\-\.0-9]+)\s*}/',
|
||||
function (array $matches) use ($request, $response, $error, &$cache) {
|
||||
|
||||
if (isset($cache[$matches[1]])) {
|
||||
return $cache[$matches[1]];
|
||||
}
|
||||
|
|
|
@ -34,10 +34,11 @@ final class Middleware
|
|||
$cookieJar = $options['cookies'];
|
||||
$request = $cookieJar->withCookieHeader($request);
|
||||
return $handler($request, $options)
|
||||
->then(function ($response) use ($cookieJar, $request) {
|
||||
$cookieJar->extractCookies($request, $response);
|
||||
return $response;
|
||||
}
|
||||
->then(
|
||||
function ($response) use ($cookieJar, $request) {
|
||||
$cookieJar->extractCookies($request, $response);
|
||||
return $response;
|
||||
}
|
||||
);
|
||||
};
|
||||
};
|
||||
|
@ -72,7 +73,7 @@ final class Middleware
|
|||
/**
|
||||
* Middleware that pushes history data to an ArrayAccess container.
|
||||
*
|
||||
* @param array $container Container to hold the history (by reference).
|
||||
* @param array|\ArrayAccess $container Container to hold the history (by reference).
|
||||
*
|
||||
* @return callable Returns a function that accepts the next handler.
|
||||
* @throws \InvalidArgumentException if container is not an array or ArrayAccess.
|
||||
|
@ -102,7 +103,7 @@ final class Middleware
|
|||
'error' => $reason,
|
||||
'options' => $options
|
||||
];
|
||||
return new RejectedPromise($reason);
|
||||
return \GuzzleHttp\Promise\rejection_for($reason);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
|
|
@ -14,9 +14,6 @@ class PrepareBodyMiddleware
|
|||
/** @var callable */
|
||||
private $nextHandler;
|
||||
|
||||
/** @var array */
|
||||
private static $skipMethods = ['GET' => true, 'HEAD' => true];
|
||||
|
||||
/**
|
||||
* @param callable $nextHandler Next handler to invoke.
|
||||
*/
|
||||
|
@ -36,9 +33,7 @@ class PrepareBodyMiddleware
|
|||
$fn = $this->nextHandler;
|
||||
|
||||
// Don't do anything if the request has no body.
|
||||
if (isset(self::$skipMethods[$request->getMethod()])
|
||||
|| $request->getBody()->getSize() === 0
|
||||
) {
|
||||
if ($request->getBody()->getSize() === 0) {
|
||||
return $fn($request, $options);
|
||||
}
|
||||
|
||||
|
@ -54,8 +49,7 @@ class PrepareBodyMiddleware
|
|||
}
|
||||
|
||||
// Add a default content-length or transfer-encoding header.
|
||||
if (!isset(self::$skipMethods[$request->getMethod()])
|
||||
&& !$request->hasHeader('Content-Length')
|
||||
if (!$request->hasHeader('Content-Length')
|
||||
&& !$request->hasHeader('Transfer-Encoding')
|
||||
) {
|
||||
$size = $request->getBody()->getSize();
|
||||
|
|
|
@ -19,6 +19,8 @@ class RedirectMiddleware
|
|||
{
|
||||
const HISTORY_HEADER = 'X-Guzzle-Redirect-History';
|
||||
|
||||
const STATUS_HISTORY_HEADER = 'X-Guzzle-Redirect-Status-History';
|
||||
|
||||
public static $defaultSettings = [
|
||||
'max' => 5,
|
||||
'protocols' => ['http', 'https'],
|
||||
|
@ -108,23 +110,27 @@ class RedirectMiddleware
|
|||
if (!empty($options['allow_redirects']['track_redirects'])) {
|
||||
return $this->withTracking(
|
||||
$promise,
|
||||
(string) $nextRequest->getUri()
|
||||
(string) $nextRequest->getUri(),
|
||||
$response->getStatusCode()
|
||||
);
|
||||
}
|
||||
|
||||
return $promise;
|
||||
}
|
||||
|
||||
private function withTracking(PromiseInterface $promise, $uri)
|
||||
private function withTracking(PromiseInterface $promise, $uri, $statusCode)
|
||||
{
|
||||
return $promise->then(
|
||||
function (ResponseInterface $response) use ($uri) {
|
||||
function (ResponseInterface $response) use ($uri, $statusCode) {
|
||||
// Note that we are pushing to the front of the list as this
|
||||
// would be an earlier response than what is currently present
|
||||
// in the history header.
|
||||
$header = $response->getHeader(self::HISTORY_HEADER);
|
||||
array_unshift($header, $uri);
|
||||
return $response->withHeader(self::HISTORY_HEADER, $header);
|
||||
$historyHeader = $response->getHeader(self::HISTORY_HEADER);
|
||||
$statusHeader = $response->getHeader(self::STATUS_HISTORY_HEADER);
|
||||
array_unshift($historyHeader, $uri);
|
||||
array_unshift($statusHeader, $statusCode);
|
||||
return $response->withHeader(self::HISTORY_HEADER, $historyHeader)
|
||||
->withHeader(self::STATUS_HISTORY_HEADER, $statusHeader);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -208,9 +214,9 @@ class RedirectMiddleware
|
|||
ResponseInterface $response,
|
||||
array $protocols
|
||||
) {
|
||||
$location = Psr7\Uri::resolve(
|
||||
$location = Psr7\UriResolver::resolve(
|
||||
$request->getUri(),
|
||||
$response->getHeaderLine('Location')
|
||||
new Psr7\Uri($response->getHeaderLine('Location'))
|
||||
);
|
||||
|
||||
// Ensure that the redirect URI is allowed based on the protocols.
|
||||
|
|
|
@ -43,8 +43,8 @@ final class RequestOptions
|
|||
const AUTH = 'auth';
|
||||
|
||||
/**
|
||||
* body: (string|null|callable|iterator|object) Body to send in the
|
||||
* request.
|
||||
* body: (resource|string|null|int|float|StreamInterface|callable|\Iterator)
|
||||
* Body to send in the request.
|
||||
*/
|
||||
const BODY = 'body';
|
||||
|
||||
|
@ -237,8 +237,19 @@ final class RequestOptions
|
|||
*/
|
||||
const TIMEOUT = 'timeout';
|
||||
|
||||
/**
|
||||
* read_timeout: (float, default=default_socket_timeout ini setting) Float describing
|
||||
* the body read timeout, for stream requests.
|
||||
*/
|
||||
const READ_TIMEOUT = 'read_timeout';
|
||||
|
||||
/**
|
||||
* version: (float) Specifies the HTTP protocol version to attempt to use.
|
||||
*/
|
||||
const VERSION = 'version';
|
||||
|
||||
/**
|
||||
* force_ip_resolve: (bool) Force client to use only ipv4 or ipv6 protocol
|
||||
*/
|
||||
const FORCE_IP_RESOLVE = 'force_ip_resolve';
|
||||
}
|
||||
|
|
|
@ -97,7 +97,7 @@ class RetryMiddleware
|
|||
null,
|
||||
$reason
|
||||
)) {
|
||||
return new RejectedPromise($reason);
|
||||
return \GuzzleHttp\Promise\rejection_for($reason);
|
||||
}
|
||||
return $this->doRetry($req, $options);
|
||||
};
|
||||
|
|
|
@ -107,7 +107,6 @@ class UriTemplate
|
|||
$useQuery = self::$operatorHash[$parsed['operator']]['query'];
|
||||
|
||||
foreach ($parsed['values'] as $value) {
|
||||
|
||||
if (!isset($this->variables[$value['value']])) {
|
||||
continue;
|
||||
}
|
||||
|
@ -117,11 +116,9 @@ class UriTemplate
|
|||
$expanded = '';
|
||||
|
||||
if (is_array($variable)) {
|
||||
|
||||
$isAssoc = $this->isAssoc($variable);
|
||||
$kvp = [];
|
||||
foreach ($variable as $key => $var) {
|
||||
|
||||
if ($isAssoc) {
|
||||
$key = rawurlencode($key);
|
||||
$isNestedArray = is_array($var);
|
||||
|
@ -179,7 +176,6 @@ class UriTemplate
|
|||
}
|
||||
$expanded = implode(',', $kvp);
|
||||
}
|
||||
|
||||
} else {
|
||||
if ($value['modifier'] === ':') {
|
||||
$variable = substr($variable, 0, $value['position']);
|
||||
|
|
|
@ -167,6 +167,8 @@ function default_ca_bundle()
|
|||
'/etc/ssl/certs/ca-certificates.crt',
|
||||
// FreeBSD (provided by the ca_root_nss package)
|
||||
'/usr/local/share/certs/ca-root-nss.crt',
|
||||
// SLES 12 (provided by the ca-certificates package)
|
||||
'/var/lib/ca-certificates/ca-bundle.pem',
|
||||
// OS X provided by homebrew (using the default path)
|
||||
'/usr/local/etc/openssl/cert.pem',
|
||||
// Google app engine
|
||||
|
@ -300,7 +302,8 @@ function json_decode($json, $assoc = false, $depth = 512, $options = 0)
|
|||
$data = \json_decode($json, $assoc, $depth, $options);
|
||||
if (JSON_ERROR_NONE !== json_last_error()) {
|
||||
throw new \InvalidArgumentException(
|
||||
'json_decode error: ' . json_last_error_msg());
|
||||
'json_decode error: ' . json_last_error_msg()
|
||||
);
|
||||
}
|
||||
|
||||
return $data;
|
||||
|
@ -322,7 +325,8 @@ function json_encode($value, $options = 0, $depth = 512)
|
|||
$json = \json_encode($value, $options, $depth);
|
||||
if (JSON_ERROR_NONE !== json_last_error()) {
|
||||
throw new \InvalidArgumentException(
|
||||
'json_encode error: ' . json_last_error_msg());
|
||||
'json_encode error: ' . json_last_error_msg()
|
||||
);
|
||||
}
|
||||
|
||||
return $json;
|
||||
|
|
9
tests/integration/vendor/guzzlehttp/psr7/.editorconfig
vendored
Normal file
9
tests/integration/vendor/guzzlehttp/psr7/.editorconfig
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
indent_size = 4
|
||||
indent_style = space
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
|
@ -1,11 +0,0 @@
|
|||
phpunit.xml
|
||||
composer.phar
|
||||
composer.lock
|
||||
composer-test.lock
|
||||
vendor/
|
||||
build/artifacts/
|
||||
artifacts/
|
||||
docs/_build
|
||||
docs/*.pyc
|
||||
.idea
|
||||
.DS_STORE
|
|
@ -1,20 +0,0 @@
|
|||
language: php
|
||||
|
||||
php:
|
||||
- 5.4
|
||||
- 5.5
|
||||
- 5.6
|
||||
- 7.0
|
||||
- hhvm
|
||||
|
||||
sudo: false
|
||||
|
||||
install:
|
||||
- travis_retry composer install --no-interaction --prefer-source
|
||||
|
||||
script: make test
|
||||
|
||||
matrix:
|
||||
allow_failures:
|
||||
- php: hhvm
|
||||
fast_finish: true
|
|
@ -1,65 +1,203 @@
|
|||
# CHANGELOG
|
||||
# Change Log
|
||||
|
||||
## 1.3.1 - 2016-06-25
|
||||
|
||||
* Fix `Uri::__toString` for network path references, e.g. `//example.org`.
|
||||
* Fix missing lowercase normalization for host.
|
||||
* Fix handling of URI components in case they are `'0'` in a lot of places,
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
|
||||
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
||||
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
|
||||
## [1.5.2] - 2018-12-04
|
||||
|
||||
### Fixed
|
||||
|
||||
- Check body size when getting the message summary
|
||||
|
||||
|
||||
## [1.5.1] - 2018-12-04
|
||||
|
||||
### Fixed
|
||||
|
||||
- Get the summary of a body only if it is readable
|
||||
|
||||
|
||||
## [1.5.0] - 2018-12-03
|
||||
|
||||
### Added
|
||||
|
||||
- Response first-line to response string exception (fixes #145)
|
||||
- A test for #129 behavior
|
||||
- `get_message_body_summary` function in order to get the message summary
|
||||
- `3gp` and `mkv` mime types
|
||||
|
||||
### Changed
|
||||
|
||||
- Clarify exception message when stream is detached
|
||||
|
||||
### Deprecated
|
||||
|
||||
- Deprecated parsing folded header lines as per RFC 7230
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix `AppendStream::detach` to not close streams
|
||||
- `InflateStream` preserves `isSeekable` attribute of the underlying stream
|
||||
- `ServerRequest::getUriFromGlobals` to support URLs in query parameters
|
||||
|
||||
|
||||
Several other fixes and improvements.
|
||||
|
||||
|
||||
## [1.4.2] - 2017-03-20
|
||||
|
||||
### Fixed
|
||||
|
||||
- Reverted BC break to `Uri::resolve` and `Uri::removeDotSegments` by removing
|
||||
calls to `trigger_error` when deprecated methods are invoked.
|
||||
|
||||
|
||||
## [1.4.1] - 2017-02-27
|
||||
|
||||
### Added
|
||||
|
||||
- Rriggering of silenced deprecation warnings.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Reverted BC break by reintroducing behavior to automagically fix a URI with a
|
||||
relative path and an authority by adding a leading slash to the path. It's only
|
||||
deprecated now.
|
||||
|
||||
|
||||
## [1.4.0] - 2017-02-21
|
||||
|
||||
### Added
|
||||
|
||||
- Added common URI utility methods based on RFC 3986 (see documentation in the readme):
|
||||
- `Uri::isDefaultPort`
|
||||
- `Uri::isAbsolute`
|
||||
- `Uri::isNetworkPathReference`
|
||||
- `Uri::isAbsolutePathReference`
|
||||
- `Uri::isRelativePathReference`
|
||||
- `Uri::isSameDocumentReference`
|
||||
- `Uri::composeComponents`
|
||||
- `UriNormalizer::normalize`
|
||||
- `UriNormalizer::isEquivalent`
|
||||
- `UriResolver::relativize`
|
||||
|
||||
### Changed
|
||||
|
||||
- Ensure `ServerRequest::getUriFromGlobals` returns a URI in absolute form.
|
||||
- Allow `parse_response` to parse a response without delimiting space and reason.
|
||||
- Ensure each URI modification results in a valid URI according to PSR-7 discussions.
|
||||
Invalid modifications will throw an exception instead of returning a wrong URI or
|
||||
doing some magic.
|
||||
- `(new Uri)->withPath('foo')->withHost('example.com')` will throw an exception
|
||||
because the path of a URI with an authority must start with a slash "/" or be empty
|
||||
- `(new Uri())->withScheme('http')` will return `'http://localhost'`
|
||||
|
||||
### Deprecated
|
||||
|
||||
- `Uri::resolve` in favor of `UriResolver::resolve`
|
||||
- `Uri::removeDotSegments` in favor of `UriResolver::removeDotSegments`
|
||||
|
||||
### Fixed
|
||||
|
||||
- `Stream::read` when length parameter <= 0.
|
||||
- `copy_to_stream` reads bytes in chunks instead of `maxLen` into memory.
|
||||
- `ServerRequest::getUriFromGlobals` when `Host` header contains port.
|
||||
- Compatibility of URIs with `file` scheme and empty host.
|
||||
|
||||
|
||||
## [1.3.1] - 2016-06-25
|
||||
|
||||
### Fixed
|
||||
|
||||
- `Uri::__toString` for network path references, e.g. `//example.org`.
|
||||
- Missing lowercase normalization for host.
|
||||
- Handling of URI components in case they are `'0'` in a lot of places,
|
||||
e.g. as a user info password.
|
||||
* Fix `Uri::withAddedHeader` to correctly merge headers with different case.
|
||||
* Fix trimming of header values in `Uri::withAddedHeader`. Header values may
|
||||
- `Uri::withAddedHeader` to correctly merge headers with different case.
|
||||
- Trimming of header values in `Uri::withAddedHeader`. Header values may
|
||||
be surrounded by whitespace which should be ignored according to RFC 7230
|
||||
Section 3.2.4. This does not apply to header names.
|
||||
* Fix `Uri::withAddedHeader` with an array of header values.
|
||||
* Fix `Uri::resolve` when base path has no slash and handling of fragment.
|
||||
* Fix handling of encoding in `Uri::with(out)QueryValue` so one can pass the
|
||||
- `Uri::withAddedHeader` with an array of header values.
|
||||
- `Uri::resolve` when base path has no slash and handling of fragment.
|
||||
- Handling of encoding in `Uri::with(out)QueryValue` so one can pass the
|
||||
key/value both in encoded as well as decoded form to those methods. This is
|
||||
consistent with withPath, withQuery etc.
|
||||
* Fix `ServerRequest::withoutAttribute` when attribute value is null.
|
||||
- `ServerRequest::withoutAttribute` when attribute value is null.
|
||||
|
||||
## 1.3.0 - 2016-04-13
|
||||
|
||||
* Added remaining interfaces needed for full PSR7 compatibility
|
||||
## [1.3.0] - 2016-04-13
|
||||
|
||||
### Added
|
||||
|
||||
- Remaining interfaces needed for full PSR7 compatibility
|
||||
(ServerRequestInterface, UploadedFileInterface, etc.).
|
||||
* Added support for stream_for from scalars.
|
||||
* Can now extend Uri.
|
||||
* Fixed a bug in validating request methods by making it more permissive.
|
||||
- Support for stream_for from scalars.
|
||||
|
||||
## 1.2.3 - 2016-02-18
|
||||
### Changed
|
||||
|
||||
* Fixed support in `GuzzleHttp\Psr7\CachingStream` for seeking forward on remote
|
||||
- Can now extend Uri.
|
||||
|
||||
### Fixed
|
||||
- A bug in validating request methods by making it more permissive.
|
||||
|
||||
|
||||
## [1.2.3] - 2016-02-18
|
||||
|
||||
### Fixed
|
||||
|
||||
- Support in `GuzzleHttp\Psr7\CachingStream` for seeking forward on remote
|
||||
streams, which can sometimes return fewer bytes than requested with `fread`.
|
||||
* Fixed handling of gzipped responses with FNAME headers.
|
||||
- Handling of gzipped responses with FNAME headers.
|
||||
|
||||
## 1.2.2 - 2016-01-22
|
||||
|
||||
* Added support for URIs without any authority.
|
||||
* Added support for HTTP 451 'Unavailable For Legal Reasons.'
|
||||
* Added support for using '0' as a filename.
|
||||
* Added support for including non-standard ports in Host headers.
|
||||
## [1.2.2] - 2016-01-22
|
||||
|
||||
## 1.2.1 - 2015-11-02
|
||||
### Added
|
||||
|
||||
* Now supporting negative offsets when seeking to SEEK_END.
|
||||
- Support for URIs without any authority.
|
||||
- Support for HTTP 451 'Unavailable For Legal Reasons.'
|
||||
- Support for using '0' as a filename.
|
||||
- Support for including non-standard ports in Host headers.
|
||||
|
||||
## 1.2.0 - 2015-08-15
|
||||
|
||||
* Body as `"0"` is now properly added to a response.
|
||||
* Now allowing forward seeking in CachingStream.
|
||||
* Now properly parsing HTTP requests that contain proxy targets in
|
||||
## [1.2.1] - 2015-11-02
|
||||
|
||||
### Changes
|
||||
|
||||
- Now supporting negative offsets when seeking to SEEK_END.
|
||||
|
||||
|
||||
## [1.2.0] - 2015-08-15
|
||||
|
||||
### Changed
|
||||
|
||||
- Body as `"0"` is now properly added to a response.
|
||||
- Now allowing forward seeking in CachingStream.
|
||||
- Now properly parsing HTTP requests that contain proxy targets in
|
||||
`parse_request`.
|
||||
* functions.php is now conditionally required.
|
||||
* user-info is no longer dropped when resolving URIs.
|
||||
- functions.php is now conditionally required.
|
||||
- user-info is no longer dropped when resolving URIs.
|
||||
|
||||
## 1.1.0 - 2015-06-24
|
||||
|
||||
* URIs can now be relative.
|
||||
* `multipart/form-data` headers are now overridden case-insensitively.
|
||||
* URI paths no longer encode the following characters because they are allowed
|
||||
## [1.1.0] - 2015-06-24
|
||||
|
||||
### Changed
|
||||
|
||||
- URIs can now be relative.
|
||||
- `multipart/form-data` headers are now overridden case-insensitively.
|
||||
- URI paths no longer encode the following characters because they are allowed
|
||||
in URIs: "(", ")", "*", "!", "'"
|
||||
* A port is no longer added to a URI when the scheme is missing and no port is
|
||||
- A port is no longer added to a URI when the scheme is missing and no port is
|
||||
present.
|
||||
|
||||
|
||||
## 1.0.0 - 2015-05-19
|
||||
|
||||
Initial release.
|
||||
|
@ -68,3 +206,20 @@ Currently unsupported:
|
|||
|
||||
- `Psr\Http\Message\ServerRequestInterface`
|
||||
- `Psr\Http\Message\UploadedFileInterface`
|
||||
|
||||
|
||||
|
||||
[Unreleased]: https://github.com/guzzle/psr7/compare/1.5.2...HEAD
|
||||
[1.5.2]: https://github.com/guzzle/psr7/compare/1.5.1...1.5.2
|
||||
[1.5.1]: https://github.com/guzzle/psr7/compare/1.5.0...1.5.1
|
||||
[1.5.0]: https://github.com/guzzle/psr7/compare/1.4.2...1.5.0
|
||||
[1.4.2]: https://github.com/guzzle/psr7/compare/1.4.1...1.4.2
|
||||
[1.4.1]: https://github.com/guzzle/psr7/compare/1.4.0...1.4.1
|
||||
[1.4.0]: https://github.com/guzzle/psr7/compare/1.3.1...1.4.0
|
||||
[1.3.1]: https://github.com/guzzle/psr7/compare/1.3.0...1.3.1
|
||||
[1.3.0]: https://github.com/guzzle/psr7/compare/1.2.3...1.3.0
|
||||
[1.2.3]: https://github.com/guzzle/psr7/compare/1.2.2...1.2.3
|
||||
[1.2.2]: https://github.com/guzzle/psr7/compare/1.2.1...1.2.2
|
||||
[1.2.1]: https://github.com/guzzle/psr7/compare/1.2.0...1.2.1
|
||||
[1.2.0]: https://github.com/guzzle/psr7/compare/1.1.0...1.2.0
|
||||
[1.1.0]: https://github.com/guzzle/psr7/compare/1.0.0...1.1.0
|
||||
|
|
|
@ -1,29 +0,0 @@
|
|||
all: clean test
|
||||
|
||||
test:
|
||||
vendor/bin/phpunit $(TEST)
|
||||
|
||||
coverage:
|
||||
vendor/bin/phpunit --coverage-html=artifacts/coverage $(TEST)
|
||||
|
||||
view-coverage:
|
||||
open artifacts/coverage/index.html
|
||||
|
||||
check-tag:
|
||||
$(if $(TAG),,$(error TAG is not defined. Pass via "make tag TAG=4.2.1"))
|
||||
|
||||
tag: check-tag
|
||||
@echo Tagging $(TAG)
|
||||
chag update $(TAG)
|
||||
git commit -a -m '$(TAG) release'
|
||||
chag tag
|
||||
@echo "Release has been created. Push using 'make release'"
|
||||
@echo "Changes made in the release commit"
|
||||
git diff HEAD~1 HEAD
|
||||
|
||||
release: check-tag
|
||||
git push origin master
|
||||
git push origin $(TAG)
|
||||
|
||||
clean:
|
||||
rm -rf artifacts/*
|
222
tests/integration/vendor/guzzlehttp/psr7/README.md
vendored
222
tests/integration/vendor/guzzlehttp/psr7/README.md
vendored
|
@ -372,7 +372,7 @@ This method accepts the following `$resource` types:
|
|||
$stream = GuzzleHttp\Psr7\stream_for('foo');
|
||||
$stream = GuzzleHttp\Psr7\stream_for(fopen('/path/to/file', 'r'));
|
||||
|
||||
$generator function ($bytes) {
|
||||
$generator = function ($bytes) {
|
||||
for ($i = 0; $i < $bytes; $i++) {
|
||||
yield ' ';
|
||||
}
|
||||
|
@ -519,51 +519,227 @@ Determines the mimetype of a file by looking at its extension.
|
|||
Maps a file extensions to a mimetype.
|
||||
|
||||
|
||||
# Static URI methods
|
||||
# Additional URI Methods
|
||||
|
||||
The `GuzzleHttp\Psr7\Uri` class has several static methods to manipulate URIs.
|
||||
Aside from the standard `Psr\Http\Message\UriInterface` implementation in form of the `GuzzleHttp\Psr7\Uri` class,
|
||||
this library also provides additional functionality when working with URIs as static methods.
|
||||
|
||||
## URI Types
|
||||
|
||||
## `GuzzleHttp\Psr7\Uri::removeDotSegments`
|
||||
An instance of `Psr\Http\Message\UriInterface` can either be an absolute URI or a relative reference.
|
||||
An absolute URI has a scheme. A relative reference is used to express a URI relative to another URI,
|
||||
the base URI. Relative references can be divided into several forms according to
|
||||
[RFC 3986 Section 4.2](https://tools.ietf.org/html/rfc3986#section-4.2):
|
||||
|
||||
`public static function removeDotSegments(string $path): string`
|
||||
- network-path references, e.g. `//example.com/path`
|
||||
- absolute-path references, e.g. `/path`
|
||||
- relative-path references, e.g. `subpath`
|
||||
|
||||
Removes dot segments from a path and returns the new path.
|
||||
The following methods can be used to identify the type of the URI.
|
||||
|
||||
See http://tools.ietf.org/html/rfc3986#section-5.2.4
|
||||
### `GuzzleHttp\Psr7\Uri::isAbsolute`
|
||||
|
||||
`public static function isAbsolute(UriInterface $uri): bool`
|
||||
|
||||
## `GuzzleHttp\Psr7\Uri::resolve`
|
||||
Whether the URI is absolute, i.e. it has a scheme.
|
||||
|
||||
`public static function resolve(UriInterface $base, $rel): UriInterface`
|
||||
### `GuzzleHttp\Psr7\Uri::isNetworkPathReference`
|
||||
|
||||
Resolve a base URI with a relative URI and return a new URI.
|
||||
`public static function isNetworkPathReference(UriInterface $uri): bool`
|
||||
|
||||
See http://tools.ietf.org/html/rfc3986#section-5
|
||||
Whether the URI is a network-path reference. A relative reference that begins with two slash characters is
|
||||
termed an network-path reference.
|
||||
|
||||
### `GuzzleHttp\Psr7\Uri::isAbsolutePathReference`
|
||||
|
||||
## `GuzzleHttp\Psr7\Uri::withQueryValue`
|
||||
`public static function isAbsolutePathReference(UriInterface $uri): bool`
|
||||
|
||||
`public static function withQueryValue(UriInterface $uri, $key, $value): UriInterface`
|
||||
Whether the URI is a absolute-path reference. A relative reference that begins with a single slash character is
|
||||
termed an absolute-path reference.
|
||||
|
||||
Create a new URI with a specific query string value.
|
||||
### `GuzzleHttp\Psr7\Uri::isRelativePathReference`
|
||||
|
||||
Any existing query string values that exactly match the provided key are
|
||||
removed and replaced with the given key value pair.
|
||||
`public static function isRelativePathReference(UriInterface $uri): bool`
|
||||
|
||||
Whether the URI is a relative-path reference. A relative reference that does not begin with a slash character is
|
||||
termed a relative-path reference.
|
||||
|
||||
## `GuzzleHttp\Psr7\Uri::withoutQueryValue`
|
||||
### `GuzzleHttp\Psr7\Uri::isSameDocumentReference`
|
||||
|
||||
`public static function withoutQueryValue(UriInterface $uri, $key): UriInterface`
|
||||
`public static function isSameDocumentReference(UriInterface $uri, UriInterface $base = null): bool`
|
||||
|
||||
Create a new URI with a specific query string value removed.
|
||||
Whether the URI is a same-document reference. A same-document reference refers to a URI that is, aside from its
|
||||
fragment component, identical to the base URI. When no base URI is given, only an empty URI reference
|
||||
(apart from its fragment) is considered a same-document reference.
|
||||
|
||||
Any existing query string values that exactly match the provided key are
|
||||
removed.
|
||||
## URI Components
|
||||
|
||||
Additional methods to work with URI components.
|
||||
|
||||
## `GuzzleHttp\Psr7\Uri::fromParts`
|
||||
### `GuzzleHttp\Psr7\Uri::isDefaultPort`
|
||||
|
||||
`public static function isDefaultPort(UriInterface $uri): bool`
|
||||
|
||||
Whether the URI has the default port of the current scheme. `Psr\Http\Message\UriInterface::getPort` may return null
|
||||
or the standard port. This method can be used independently of the implementation.
|
||||
|
||||
### `GuzzleHttp\Psr7\Uri::composeComponents`
|
||||
|
||||
`public static function composeComponents($scheme, $authority, $path, $query, $fragment): string`
|
||||
|
||||
Composes a URI reference string from its various components according to
|
||||
[RFC 3986 Section 5.3](https://tools.ietf.org/html/rfc3986#section-5.3). Usually this method does not need to be called
|
||||
manually but instead is used indirectly via `Psr\Http\Message\UriInterface::__toString`.
|
||||
|
||||
### `GuzzleHttp\Psr7\Uri::fromParts`
|
||||
|
||||
`public static function fromParts(array $parts): UriInterface`
|
||||
|
||||
Create a `GuzzleHttp\Psr7\Uri` object from a hash of `parse_url` parts.
|
||||
Creates a URI from a hash of [`parse_url`](http://php.net/manual/en/function.parse-url.php) components.
|
||||
|
||||
|
||||
### `GuzzleHttp\Psr7\Uri::withQueryValue`
|
||||
|
||||
`public static function withQueryValue(UriInterface $uri, $key, $value): UriInterface`
|
||||
|
||||
Creates a new URI with a specific query string value. Any existing query string values that exactly match the
|
||||
provided key are removed and replaced with the given key value pair. A value of null will set the query string
|
||||
key without a value, e.g. "key" instead of "key=value".
|
||||
|
||||
### `GuzzleHttp\Psr7\Uri::withQueryValues`
|
||||
|
||||
`public static function withQueryValues(UriInterface $uri, array $keyValueArray): UriInterface`
|
||||
|
||||
Creates a new URI with multiple query string values. It has the same behavior as `withQueryValue()` but for an
|
||||
associative array of key => value.
|
||||
|
||||
### `GuzzleHttp\Psr7\Uri::withoutQueryValue`
|
||||
|
||||
`public static function withoutQueryValue(UriInterface $uri, $key): UriInterface`
|
||||
|
||||
Creates a new URI with a specific query string value removed. Any existing query string values that exactly match the
|
||||
provided key are removed.
|
||||
|
||||
## Reference Resolution
|
||||
|
||||
`GuzzleHttp\Psr7\UriResolver` provides methods to resolve a URI reference in the context of a base URI according
|
||||
to [RFC 3986 Section 5](https://tools.ietf.org/html/rfc3986#section-5). This is for example also what web browsers
|
||||
do when resolving a link in a website based on the current request URI.
|
||||
|
||||
### `GuzzleHttp\Psr7\UriResolver::resolve`
|
||||
|
||||
`public static function resolve(UriInterface $base, UriInterface $rel): UriInterface`
|
||||
|
||||
Converts the relative URI into a new URI that is resolved against the base URI.
|
||||
|
||||
### `GuzzleHttp\Psr7\UriResolver::removeDotSegments`
|
||||
|
||||
`public static function removeDotSegments(string $path): string`
|
||||
|
||||
Removes dot segments from a path and returns the new path according to
|
||||
[RFC 3986 Section 5.2.4](https://tools.ietf.org/html/rfc3986#section-5.2.4).
|
||||
|
||||
### `GuzzleHttp\Psr7\UriResolver::relativize`
|
||||
|
||||
`public static function relativize(UriInterface $base, UriInterface $target): UriInterface`
|
||||
|
||||
Returns the target URI as a relative reference from the base URI. This method is the counterpart to resolve():
|
||||
|
||||
```php
|
||||
(string) $target === (string) UriResolver::resolve($base, UriResolver::relativize($base, $target))
|
||||
```
|
||||
|
||||
One use-case is to use the current request URI as base URI and then generate relative links in your documents
|
||||
to reduce the document size or offer self-contained downloadable document archives.
|
||||
|
||||
```php
|
||||
$base = new Uri('http://example.com/a/b/');
|
||||
echo UriResolver::relativize($base, new Uri('http://example.com/a/b/c')); // prints 'c'.
|
||||
echo UriResolver::relativize($base, new Uri('http://example.com/a/x/y')); // prints '../x/y'.
|
||||
echo UriResolver::relativize($base, new Uri('http://example.com/a/b/?q')); // prints '?q'.
|
||||
echo UriResolver::relativize($base, new Uri('http://example.org/a/b/')); // prints '//example.org/a/b/'.
|
||||
```
|
||||
|
||||
## Normalization and Comparison
|
||||
|
||||
`GuzzleHttp\Psr7\UriNormalizer` provides methods to normalize and compare URIs according to
|
||||
[RFC 3986 Section 6](https://tools.ietf.org/html/rfc3986#section-6).
|
||||
|
||||
### `GuzzleHttp\Psr7\UriNormalizer::normalize`
|
||||
|
||||
`public static function normalize(UriInterface $uri, $flags = self::PRESERVING_NORMALIZATIONS): UriInterface`
|
||||
|
||||
Returns a normalized URI. The scheme and host component are already normalized to lowercase per PSR-7 UriInterface.
|
||||
This methods adds additional normalizations that can be configured with the `$flags` parameter which is a bitmask
|
||||
of normalizations to apply. The following normalizations are available:
|
||||
|
||||
- `UriNormalizer::PRESERVING_NORMALIZATIONS`
|
||||
|
||||
Default normalizations which only include the ones that preserve semantics.
|
||||
|
||||
- `UriNormalizer::CAPITALIZE_PERCENT_ENCODING`
|
||||
|
||||
All letters within a percent-encoding triplet (e.g., "%3A") are case-insensitive, and should be capitalized.
|
||||
|
||||
Example: `http://example.org/a%c2%b1b` → `http://example.org/a%C2%B1b`
|
||||
|
||||
- `UriNormalizer::DECODE_UNRESERVED_CHARACTERS`
|
||||
|
||||
Decodes percent-encoded octets of unreserved characters. For consistency, percent-encoded octets in the ranges of
|
||||
ALPHA (%41–%5A and %61–%7A), DIGIT (%30–%39), hyphen (%2D), period (%2E), underscore (%5F), or tilde (%7E) should
|
||||
not be created by URI producers and, when found in a URI, should be decoded to their corresponding unreserved
|
||||
characters by URI normalizers.
|
||||
|
||||
Example: `http://example.org/%7Eusern%61me/` → `http://example.org/~username/`
|
||||
|
||||
- `UriNormalizer::CONVERT_EMPTY_PATH`
|
||||
|
||||
Converts the empty path to "/" for http and https URIs.
|
||||
|
||||
Example: `http://example.org` → `http://example.org/`
|
||||
|
||||
- `UriNormalizer::REMOVE_DEFAULT_HOST`
|
||||
|
||||
Removes the default host of the given URI scheme from the URI. Only the "file" scheme defines the default host
|
||||
"localhost". All of `file:/myfile`, `file:///myfile`, and `file://localhost/myfile` are equivalent according to
|
||||
RFC 3986.
|
||||
|
||||
Example: `file://localhost/myfile` → `file:///myfile`
|
||||
|
||||
- `UriNormalizer::REMOVE_DEFAULT_PORT`
|
||||
|
||||
Removes the default port of the given URI scheme from the URI.
|
||||
|
||||
Example: `http://example.org:80/` → `http://example.org/`
|
||||
|
||||
- `UriNormalizer::REMOVE_DOT_SEGMENTS`
|
||||
|
||||
Removes unnecessary dot-segments. Dot-segments in relative-path references are not removed as it would
|
||||
change the semantics of the URI reference.
|
||||
|
||||
Example: `http://example.org/../a/b/../c/./d.html` → `http://example.org/a/c/d.html`
|
||||
|
||||
- `UriNormalizer::REMOVE_DUPLICATE_SLASHES`
|
||||
|
||||
Paths which include two or more adjacent slashes are converted to one. Webservers usually ignore duplicate slashes
|
||||
and treat those URIs equivalent. But in theory those URIs do not need to be equivalent. So this normalization
|
||||
may change the semantics. Encoded slashes (%2F) are not removed.
|
||||
|
||||
Example: `http://example.org//foo///bar.html` → `http://example.org/foo/bar.html`
|
||||
|
||||
- `UriNormalizer::SORT_QUERY_PARAMETERS`
|
||||
|
||||
Sort query parameters with their values in alphabetical order. However, the order of parameters in a URI may be
|
||||
significant (this is not defined by the standard). So this normalization is not safe and may change the semantics
|
||||
of the URI.
|
||||
|
||||
Example: `?lang=en&article=fred` → `?article=fred&lang=en`
|
||||
|
||||
### `GuzzleHttp\Psr7\UriNormalizer::isEquivalent`
|
||||
|
||||
`public static function isEquivalent(UriInterface $uri1, UriInterface $uri2, $normalizations = self::PRESERVING_NORMALIZATIONS): bool`
|
||||
|
||||
Whether two URIs can be considered equivalent. Both URIs are normalized automatically before comparison with the given
|
||||
`$normalizations` bitmask. The method also accepts relative URI references and returns true when they are equivalent.
|
||||
This of course assumes they will be resolved against the same base URI. If this is not the case, determination of
|
||||
equivalence or difference of relative references does not mean anything.
|
||||
|
|
|
@ -1,22 +1,27 @@
|
|||
{
|
||||
"name": "guzzlehttp/psr7",
|
||||
"type": "library",
|
||||
"description": "PSR-7 message implementation",
|
||||
"keywords": ["message", "stream", "http", "uri"],
|
||||
"description": "PSR-7 message implementation that also provides common utility methods",
|
||||
"keywords": ["request", "response", "message", "stream", "http", "uri", "url", "psr-7"],
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Michael Dowling",
|
||||
"email": "mtdowling@gmail.com",
|
||||
"homepage": "https://github.com/mtdowling"
|
||||
},
|
||||
{
|
||||
"name": "Tobias Schultze",
|
||||
"homepage": "https://github.com/Tobion"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.4.0",
|
||||
"psr/http-message": "~1.0"
|
||||
"psr/http-message": "~1.0",
|
||||
"ralouphie/getallheaders": "^2.0.5"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~4.0"
|
||||
"phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.8"
|
||||
},
|
||||
"provide": {
|
||||
"psr/http-message-implementation": "1.0"
|
||||
|
@ -27,9 +32,14 @@
|
|||
},
|
||||
"files": ["src/functions_include.php"]
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"GuzzleHttp\\Tests\\Psr7\\": "tests/"
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.4-dev"
|
||||
"dev-master": "1.5-dev"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit bootstrap="./tests/bootstrap.php"
|
||||
colors="true">
|
||||
<testsuites>
|
||||
<testsuite>
|
||||
<directory>tests</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
<filter>
|
||||
<whitelist>
|
||||
<directory suffix=".php">src</directory>
|
||||
<exclude>
|
||||
<directory suffix="Interface.php">src/</directory>
|
||||
</exclude>
|
||||
</whitelist>
|
||||
</filter>
|
||||
</phpunit>
|
|
@ -16,7 +16,6 @@ class AppendStream implements StreamInterface
|
|||
private $seekable = true;
|
||||
private $current = 0;
|
||||
private $pos = 0;
|
||||
private $detached = false;
|
||||
|
||||
/**
|
||||
* @param StreamInterface[] $streams Streams to decorate. Each stream must
|
||||
|
@ -73,6 +72,7 @@ class AppendStream implements StreamInterface
|
|||
public function close()
|
||||
{
|
||||
$this->pos = $this->current = 0;
|
||||
$this->seekable = true;
|
||||
|
||||
foreach ($this->streams as $stream) {
|
||||
$stream->close();
|
||||
|
@ -82,14 +82,22 @@ class AppendStream implements StreamInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* Detaches each attached stream
|
||||
* Detaches each attached stream.
|
||||
*
|
||||
* Returns null as it's not clear which underlying stream resource to return.
|
||||
*
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function detach()
|
||||
{
|
||||
$this->close();
|
||||
$this->detached = true;
|
||||
$this->pos = $this->current = 0;
|
||||
$this->seekable = true;
|
||||
|
||||
foreach ($this->streams as $stream) {
|
||||
$stream->detach();
|
||||
}
|
||||
|
||||
$this->streams = [];
|
||||
}
|
||||
|
||||
public function tell()
|
||||
|
|
|
@ -52,6 +52,15 @@ class FnStream implements StreamInterface
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An unserialize would allow the __destruct to run when the unserialized value goes out of scope.
|
||||
* @throws \LogicException
|
||||
*/
|
||||
public function __wakeup()
|
||||
{
|
||||
throw new \LogicException('FnStream should never be unserialized');
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds custom functionality to an underlying stream by intercepting
|
||||
* specific method calls.
|
||||
|
|
|
@ -27,7 +27,7 @@ class InflateStream implements StreamInterface
|
|||
$stream = new LimitStream($stream, -1, 10 + $filenameHeaderLength);
|
||||
$resource = StreamWrapper::getResource($stream);
|
||||
stream_filter_append($resource, 'zlib.inflate', STREAM_FILTER_READ);
|
||||
$this->stream = new Stream($resource);
|
||||
$this->stream = $stream->isSeekable() ? new Stream($resource) : new NoSeekStream(new Stream($resource));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -21,7 +21,7 @@ class LimitStream implements StreamInterface
|
|||
* @param StreamInterface $stream Stream to wrap
|
||||
* @param int $limit Total number of bytes to allow to be read
|
||||
* from the stream. Pass -1 for no limit.
|
||||
* @param int|null $offset Position to seek to before reading (only
|
||||
* @param int $offset Position to seek to before reading (only
|
||||
* works on seekable streams).
|
||||
*/
|
||||
public function __construct(
|
||||
|
|
|
@ -27,7 +27,7 @@ class MultipartStream implements StreamInterface
|
|||
*/
|
||||
public function __construct(array $elements = [], $boundary = null)
|
||||
{
|
||||
$this->boundary = $boundary ?: uniqid();
|
||||
$this->boundary = $boundary ?: sha1(uniqid('', true));
|
||||
$this->stream = $this->createStream($elements);
|
||||
}
|
||||
|
||||
|
@ -108,7 +108,7 @@ class MultipartStream implements StreamInterface
|
|||
/**
|
||||
* @return array
|
||||
*/
|
||||
private function createElement($name, $stream, $filename, array $headers)
|
||||
private function createElement($name, StreamInterface $stream, $filename, array $headers)
|
||||
{
|
||||
// Set a default content-disposition header if one was no provided
|
||||
$disposition = $this->getHeader($headers, 'content-disposition');
|
||||
|
|
|
@ -19,7 +19,7 @@ class Request implements RequestInterface
|
|||
/** @var null|string */
|
||||
private $requestTarget;
|
||||
|
||||
/** @var null|UriInterface */
|
||||
/** @var UriInterface */
|
||||
private $uri;
|
||||
|
||||
/**
|
||||
|
@ -45,7 +45,7 @@ class Request implements RequestInterface
|
|||
$this->setHeaders($headers);
|
||||
$this->protocol = $version;
|
||||
|
||||
if (!$this->hasHeader('Host')) {
|
||||
if (!isset($this->headerNames['host'])) {
|
||||
$this->updateHostFromUri();
|
||||
}
|
||||
|
||||
|
@ -110,7 +110,7 @@ class Request implements RequestInterface
|
|||
$new = clone $this;
|
||||
$new->uri = $uri;
|
||||
|
||||
if (!$preserveHost) {
|
||||
if (!$preserveHost || !isset($this->headerNames['host'])) {
|
||||
$new->updateHostFromUri();
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
namespace GuzzleHttp\Psr7;
|
||||
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\StreamInterface;
|
||||
|
||||
/**
|
||||
* PSR-7 response implementation.
|
||||
|
@ -92,6 +93,10 @@ class Response implements ResponseInterface
|
|||
$version = '1.1',
|
||||
$reason = null
|
||||
) {
|
||||
if (filter_var($status, FILTER_VALIDATE_INT) === false) {
|
||||
throw new \InvalidArgumentException('Status code must be an integer value.');
|
||||
}
|
||||
|
||||
$this->statusCode = (int) $status;
|
||||
|
||||
if ($body !== '' && $body !== null) {
|
||||
|
@ -100,7 +105,7 @@ class Response implements ResponseInterface
|
|||
|
||||
$this->setHeaders($headers);
|
||||
if ($reason == '' && isset(self::$phrases[$this->statusCode])) {
|
||||
$this->reasonPhrase = self::$phrases[$status];
|
||||
$this->reasonPhrase = self::$phrases[$this->statusCode];
|
||||
} else {
|
||||
$this->reasonPhrase = (string) $reason;
|
||||
}
|
||||
|
|
18
tests/integration/vendor/guzzlehttp/psr7/src/Rfc7230.php
vendored
Normal file
18
tests/integration/vendor/guzzlehttp/psr7/src/Rfc7230.php
vendored
Normal file
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
namespace GuzzleHttp\Psr7;
|
||||
|
||||
final class Rfc7230
|
||||
{
|
||||
/**
|
||||
* Header related regular expressions (copied from amphp/http package)
|
||||
* (Note: once we require PHP 7.x we could just depend on the upstream package)
|
||||
*
|
||||
* Note: header delimiter (\r\n) is modified to \r?\n to accept line feed only delimiters for BC reasons.
|
||||
*
|
||||
* @link https://github.com/amphp/http/blob/v1.0.1/src/Rfc7230.php#L12-L15
|
||||
* @license https://github.com/amphp/http/blob/v1.0.1/LICENSE
|
||||
*/
|
||||
const HEADER_REGEX = "(^([^()<>@,;:\\\"/[\]?={}\x01-\x20\x7F]++):[ \t]*+((?:[ \t]*+[\x21-\x7E\x80-\xFF]++)*+)[ \t]*+\r?\n)m";
|
||||
const HEADER_FOLD_REGEX = "(\r?\n[ \t]++)";
|
||||
}
|
|
@ -166,7 +166,7 @@ class ServerRequest extends Request implements ServerRequestInterface
|
|||
public static function fromGlobals()
|
||||
{
|
||||
$method = isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : 'GET';
|
||||
$headers = function_exists('getallheaders') ? getallheaders() : [];
|
||||
$headers = getallheaders();
|
||||
$uri = self::getUriFromGlobals();
|
||||
$body = new LazyOpenStream('php://input', 'r+');
|
||||
$protocol = isset($_SERVER['SERVER_PROTOCOL']) ? str_replace('HTTP/', '', $_SERVER['SERVER_PROTOCOL']) : '1.1';
|
||||
|
@ -180,33 +180,63 @@ class ServerRequest extends Request implements ServerRequestInterface
|
|||
->withUploadedFiles(self::normalizeFiles($_FILES));
|
||||
}
|
||||
|
||||
private static function extractHostAndPortFromAuthority($authority)
|
||||
{
|
||||
$uri = 'http://'.$authority;
|
||||
$parts = parse_url($uri);
|
||||
if (false === $parts) {
|
||||
return [null, null];
|
||||
}
|
||||
|
||||
$host = isset($parts['host']) ? $parts['host'] : null;
|
||||
$port = isset($parts['port']) ? $parts['port'] : null;
|
||||
|
||||
return [$host, $port];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a Uri populated with values from $_SERVER.
|
||||
*
|
||||
* @return UriInterface
|
||||
*/
|
||||
public static function getUriFromGlobals() {
|
||||
public static function getUriFromGlobals()
|
||||
{
|
||||
$uri = new Uri('');
|
||||
|
||||
if (isset($_SERVER['HTTPS'])) {
|
||||
$uri = $uri->withScheme($_SERVER['HTTPS'] == 'on' ? 'https' : 'http');
|
||||
}
|
||||
$uri = $uri->withScheme(!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' ? 'https' : 'http');
|
||||
|
||||
$hasPort = false;
|
||||
if (isset($_SERVER['HTTP_HOST'])) {
|
||||
$uri = $uri->withHost($_SERVER['HTTP_HOST']);
|
||||
list($host, $port) = self::extractHostAndPortFromAuthority($_SERVER['HTTP_HOST']);
|
||||
if ($host !== null) {
|
||||
$uri = $uri->withHost($host);
|
||||
}
|
||||
|
||||
if ($port !== null) {
|
||||
$hasPort = true;
|
||||
$uri = $uri->withPort($port);
|
||||
}
|
||||
} elseif (isset($_SERVER['SERVER_NAME'])) {
|
||||
$uri = $uri->withHost($_SERVER['SERVER_NAME']);
|
||||
} elseif (isset($_SERVER['SERVER_ADDR'])) {
|
||||
$uri = $uri->withHost($_SERVER['SERVER_ADDR']);
|
||||
}
|
||||
|
||||
if (isset($_SERVER['SERVER_PORT'])) {
|
||||
if (!$hasPort && isset($_SERVER['SERVER_PORT'])) {
|
||||
$uri = $uri->withPort($_SERVER['SERVER_PORT']);
|
||||
}
|
||||
|
||||
$hasQuery = false;
|
||||
if (isset($_SERVER['REQUEST_URI'])) {
|
||||
$uri = $uri->withPath(current(explode('?', $_SERVER['REQUEST_URI'])));
|
||||
$requestUriParts = explode('?', $_SERVER['REQUEST_URI'], 2);
|
||||
$uri = $uri->withPath($requestUriParts[0]);
|
||||
if (isset($requestUriParts[1])) {
|
||||
$hasQuery = true;
|
||||
$uri = $uri->withQuery($requestUriParts[1]);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($_SERVER['QUERY_STRING'])) {
|
||||
if (!$hasQuery && isset($_SERVER['QUERY_STRING'])) {
|
||||
$uri = $uri->withQuery($_SERVER['QUERY_STRING']);
|
||||
}
|
||||
|
||||
|
|
|
@ -24,11 +24,11 @@ class Stream implements StreamInterface
|
|||
'r' => true, 'w+' => true, 'r+' => true, 'x+' => true, 'c+' => true,
|
||||
'rb' => true, 'w+b' => true, 'r+b' => true, 'x+b' => true,
|
||||
'c+b' => true, 'rt' => true, 'w+t' => true, 'r+t' => true,
|
||||
'x+t' => true, 'c+t' => true, 'a+' => true
|
||||
'x+t' => true, 'c+t' => true, 'a+' => true, 'rb+' => true,
|
||||
],
|
||||
'write' => [
|
||||
'w' => true, 'w+' => true, 'rw' => true, 'r+' => true, 'x+' => true,
|
||||
'c+' => true, 'wb' => true, 'w+b' => true, 'r+b' => true,
|
||||
'c+' => true, 'wb' => true, 'w+b' => true, 'r+b' => true, 'rb+' => true,
|
||||
'x+b' => true, 'c+b' => true, 'w+t' => true, 'r+t' => true,
|
||||
'x+t' => true, 'c+t' => true, 'a' => true, 'a+' => true
|
||||
]
|
||||
|
@ -70,15 +70,6 @@ class Stream implements StreamInterface
|
|||
$this->uri = $this->getMetadata('uri');
|
||||
}
|
||||
|
||||
public function __get($name)
|
||||
{
|
||||
if ($name == 'stream') {
|
||||
throw new \RuntimeException('The stream is detached');
|
||||
}
|
||||
|
||||
throw new \BadMethodCallException('No value for ' . $name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the stream when the destructed
|
||||
*/
|
||||
|
@ -99,6 +90,10 @@ class Stream implements StreamInterface
|
|||
|
||||
public function getContents()
|
||||
{
|
||||
if (!isset($this->stream)) {
|
||||
throw new \RuntimeException('Stream is detached');
|
||||
}
|
||||
|
||||
$contents = stream_get_contents($this->stream);
|
||||
|
||||
if ($contents === false) {
|
||||
|
@ -173,11 +168,19 @@ class Stream implements StreamInterface
|
|||
|
||||
public function eof()
|
||||
{
|
||||
return !$this->stream || feof($this->stream);
|
||||
if (!isset($this->stream)) {
|
||||
throw new \RuntimeException('Stream is detached');
|
||||
}
|
||||
|
||||
return feof($this->stream);
|
||||
}
|
||||
|
||||
public function tell()
|
||||
{
|
||||
if (!isset($this->stream)) {
|
||||
throw new \RuntimeException('Stream is detached');
|
||||
}
|
||||
|
||||
$result = ftell($this->stream);
|
||||
|
||||
if ($result === false) {
|
||||
|
@ -194,9 +197,13 @@ class Stream implements StreamInterface
|
|||
|
||||
public function seek($offset, $whence = SEEK_SET)
|
||||
{
|
||||
if (!isset($this->stream)) {
|
||||
throw new \RuntimeException('Stream is detached');
|
||||
}
|
||||
if (!$this->seekable) {
|
||||
throw new \RuntimeException('Stream is not seekable');
|
||||
} elseif (fseek($this->stream, $offset, $whence) === -1) {
|
||||
}
|
||||
if (fseek($this->stream, $offset, $whence) === -1) {
|
||||
throw new \RuntimeException('Unable to seek to stream position '
|
||||
. $offset . ' with whence ' . var_export($whence, true));
|
||||
}
|
||||
|
@ -204,15 +211,33 @@ class Stream implements StreamInterface
|
|||
|
||||
public function read($length)
|
||||
{
|
||||
if (!isset($this->stream)) {
|
||||
throw new \RuntimeException('Stream is detached');
|
||||
}
|
||||
if (!$this->readable) {
|
||||
throw new \RuntimeException('Cannot read from non-readable stream');
|
||||
}
|
||||
if ($length < 0) {
|
||||
throw new \RuntimeException('Length parameter cannot be negative');
|
||||
}
|
||||
|
||||
return fread($this->stream, $length);
|
||||
if (0 === $length) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$string = fread($this->stream, $length);
|
||||
if (false === $string) {
|
||||
throw new \RuntimeException('Unable to read from stream');
|
||||
}
|
||||
|
||||
return $string;
|
||||
}
|
||||
|
||||
public function write($string)
|
||||
{
|
||||
if (!isset($this->stream)) {
|
||||
throw new \RuntimeException('Stream is detached');
|
||||
}
|
||||
if (!$this->writable) {
|
||||
throw new \RuntimeException('Cannot write to a non-writable stream');
|
||||
}
|
||||
|
|
|
@ -38,9 +38,21 @@ class StreamWrapper
|
|||
. 'writable, or both.');
|
||||
}
|
||||
|
||||
return fopen('guzzle://stream', $mode, null, stream_context_create([
|
||||
return fopen('guzzle://stream', $mode, null, self::createStreamContext($stream));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a stream context that can be used to open a stream as a php stream resource.
|
||||
*
|
||||
* @param StreamInterface $stream
|
||||
*
|
||||
* @return resource
|
||||
*/
|
||||
public static function createStreamContext(StreamInterface $stream)
|
||||
{
|
||||
return stream_context_create([
|
||||
'guzzle' => ['stream' => $stream]
|
||||
]));
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -94,12 +106,21 @@ class StreamWrapper
|
|||
return true;
|
||||
}
|
||||
|
||||
public function stream_cast($cast_as)
|
||||
{
|
||||
$stream = clone($this->stream);
|
||||
|
||||
return $stream->detach();
|
||||
}
|
||||
|
||||
public function stream_stat()
|
||||
{
|
||||
static $modeMap = [
|
||||
'r' => 33060,
|
||||
'rb' => 33060,
|
||||
'r+' => 33206,
|
||||
'w' => 33188
|
||||
'w' => 33188,
|
||||
'wb' => 33188
|
||||
];
|
||||
|
||||
return [
|
||||
|
@ -118,4 +139,23 @@ class StreamWrapper
|
|||
'blocks' => 0
|
||||
];
|
||||
}
|
||||
|
||||
public function url_stat($path, $flags)
|
||||
{
|
||||
return [
|
||||
'dev' => 0,
|
||||
'ino' => 0,
|
||||
'mode' => 0,
|
||||
'nlink' => 0,
|
||||
'uid' => 0,
|
||||
'gid' => 0,
|
||||
'rdev' => 0,
|
||||
'size' => 0,
|
||||
'atime' => 0,
|
||||
'mtime' => 0,
|
||||
'ctime' => 0,
|
||||
'blksize' => 0,
|
||||
'blocks' => 0
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
496
tests/integration/vendor/guzzlehttp/psr7/src/Uri.php
vendored
496
tests/integration/vendor/guzzlehttp/psr7/src/Uri.php
vendored
|
@ -12,9 +12,26 @@ use Psr\Http\Message\UriInterface;
|
|||
*/
|
||||
class Uri implements UriInterface
|
||||
{
|
||||
private static $schemes = [
|
||||
/**
|
||||
* Absolute http and https URIs require a host per RFC 7230 Section 2.7
|
||||
* but in generic URIs the host can be empty. So for http(s) URIs
|
||||
* we apply this default host when no host is given yet to form a
|
||||
* valid URI.
|
||||
*/
|
||||
const HTTP_DEFAULT_HOST = 'localhost';
|
||||
|
||||
private static $defaultPorts = [
|
||||
'http' => 80,
|
||||
'https' => 443,
|
||||
'ftp' => 21,
|
||||
'gopher' => 70,
|
||||
'nntp' => 119,
|
||||
'news' => 119,
|
||||
'telnet' => 23,
|
||||
'tn3270' => 23,
|
||||
'imap' => 143,
|
||||
'pop' => 110,
|
||||
'ldap' => 389,
|
||||
];
|
||||
|
||||
private static $charUnreserved = 'a-zA-Z0-9_\-\.~';
|
||||
|
@ -47,6 +64,7 @@ class Uri implements UriInterface
|
|||
*/
|
||||
public function __construct($uri = '')
|
||||
{
|
||||
// weak type check to also accept null until we can add scalar type hints
|
||||
if ($uri != '') {
|
||||
$parts = parse_url($uri);
|
||||
if ($parts === false) {
|
||||
|
@ -58,7 +76,7 @@ class Uri implements UriInterface
|
|||
|
||||
public function __toString()
|
||||
{
|
||||
return self::createUriString(
|
||||
return self::composeComponents(
|
||||
$this->scheme,
|
||||
$this->getAuthority(),
|
||||
$this->path,
|
||||
|
@ -67,57 +85,199 @@ class Uri implements UriInterface
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Composes a URI reference string from its various components.
|
||||
*
|
||||
* Usually this method does not need to be called manually but instead is used indirectly via
|
||||
* `Psr\Http\Message\UriInterface::__toString`.
|
||||
*
|
||||
* PSR-7 UriInterface treats an empty component the same as a missing component as
|
||||
* getQuery(), getFragment() etc. always return a string. This explains the slight
|
||||
* difference to RFC 3986 Section 5.3.
|
||||
*
|
||||
* Another adjustment is that the authority separator is added even when the authority is missing/empty
|
||||
* for the "file" scheme. This is because PHP stream functions like `file_get_contents` only work with
|
||||
* `file:///myfile` but not with `file:/myfile` although they are equivalent according to RFC 3986. But
|
||||
* `file:///` is the more common syntax for the file scheme anyway (Chrome for example redirects to
|
||||
* that format).
|
||||
*
|
||||
* @param string $scheme
|
||||
* @param string $authority
|
||||
* @param string $path
|
||||
* @param string $query
|
||||
* @param string $fragment
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @link https://tools.ietf.org/html/rfc3986#section-5.3
|
||||
*/
|
||||
public static function composeComponents($scheme, $authority, $path, $query, $fragment)
|
||||
{
|
||||
$uri = '';
|
||||
|
||||
// weak type checks to also accept null until we can add scalar type hints
|
||||
if ($scheme != '') {
|
||||
$uri .= $scheme . ':';
|
||||
}
|
||||
|
||||
if ($authority != ''|| $scheme === 'file') {
|
||||
$uri .= '//' . $authority;
|
||||
}
|
||||
|
||||
$uri .= $path;
|
||||
|
||||
if ($query != '') {
|
||||
$uri .= '?' . $query;
|
||||
}
|
||||
|
||||
if ($fragment != '') {
|
||||
$uri .= '#' . $fragment;
|
||||
}
|
||||
|
||||
return $uri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the URI has the default port of the current scheme.
|
||||
*
|
||||
* `Psr\Http\Message\UriInterface::getPort` may return null or the standard port. This method can be used
|
||||
* independently of the implementation.
|
||||
*
|
||||
* @param UriInterface $uri
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function isDefaultPort(UriInterface $uri)
|
||||
{
|
||||
return $uri->getPort() === null
|
||||
|| (isset(self::$defaultPorts[$uri->getScheme()]) && $uri->getPort() === self::$defaultPorts[$uri->getScheme()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the URI is absolute, i.e. it has a scheme.
|
||||
*
|
||||
* An instance of UriInterface can either be an absolute URI or a relative reference. This method returns true
|
||||
* if it is the former. An absolute URI has a scheme. A relative reference is used to express a URI relative
|
||||
* to another URI, the base URI. Relative references can be divided into several forms:
|
||||
* - network-path references, e.g. '//example.com/path'
|
||||
* - absolute-path references, e.g. '/path'
|
||||
* - relative-path references, e.g. 'subpath'
|
||||
*
|
||||
* @param UriInterface $uri
|
||||
*
|
||||
* @return bool
|
||||
* @see Uri::isNetworkPathReference
|
||||
* @see Uri::isAbsolutePathReference
|
||||
* @see Uri::isRelativePathReference
|
||||
* @link https://tools.ietf.org/html/rfc3986#section-4
|
||||
*/
|
||||
public static function isAbsolute(UriInterface $uri)
|
||||
{
|
||||
return $uri->getScheme() !== '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the URI is a network-path reference.
|
||||
*
|
||||
* A relative reference that begins with two slash characters is termed an network-path reference.
|
||||
*
|
||||
* @param UriInterface $uri
|
||||
*
|
||||
* @return bool
|
||||
* @link https://tools.ietf.org/html/rfc3986#section-4.2
|
||||
*/
|
||||
public static function isNetworkPathReference(UriInterface $uri)
|
||||
{
|
||||
return $uri->getScheme() === '' && $uri->getAuthority() !== '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the URI is a absolute-path reference.
|
||||
*
|
||||
* A relative reference that begins with a single slash character is termed an absolute-path reference.
|
||||
*
|
||||
* @param UriInterface $uri
|
||||
*
|
||||
* @return bool
|
||||
* @link https://tools.ietf.org/html/rfc3986#section-4.2
|
||||
*/
|
||||
public static function isAbsolutePathReference(UriInterface $uri)
|
||||
{
|
||||
return $uri->getScheme() === ''
|
||||
&& $uri->getAuthority() === ''
|
||||
&& isset($uri->getPath()[0])
|
||||
&& $uri->getPath()[0] === '/';
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the URI is a relative-path reference.
|
||||
*
|
||||
* A relative reference that does not begin with a slash character is termed a relative-path reference.
|
||||
*
|
||||
* @param UriInterface $uri
|
||||
*
|
||||
* @return bool
|
||||
* @link https://tools.ietf.org/html/rfc3986#section-4.2
|
||||
*/
|
||||
public static function isRelativePathReference(UriInterface $uri)
|
||||
{
|
||||
return $uri->getScheme() === ''
|
||||
&& $uri->getAuthority() === ''
|
||||
&& (!isset($uri->getPath()[0]) || $uri->getPath()[0] !== '/');
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the URI is a same-document reference.
|
||||
*
|
||||
* A same-document reference refers to a URI that is, aside from its fragment
|
||||
* component, identical to the base URI. When no base URI is given, only an empty
|
||||
* URI reference (apart from its fragment) is considered a same-document reference.
|
||||
*
|
||||
* @param UriInterface $uri The URI to check
|
||||
* @param UriInterface|null $base An optional base URI to compare against
|
||||
*
|
||||
* @return bool
|
||||
* @link https://tools.ietf.org/html/rfc3986#section-4.4
|
||||
*/
|
||||
public static function isSameDocumentReference(UriInterface $uri, UriInterface $base = null)
|
||||
{
|
||||
if ($base !== null) {
|
||||
$uri = UriResolver::resolve($base, $uri);
|
||||
|
||||
return ($uri->getScheme() === $base->getScheme())
|
||||
&& ($uri->getAuthority() === $base->getAuthority())
|
||||
&& ($uri->getPath() === $base->getPath())
|
||||
&& ($uri->getQuery() === $base->getQuery());
|
||||
}
|
||||
|
||||
return $uri->getScheme() === '' && $uri->getAuthority() === '' && $uri->getPath() === '' && $uri->getQuery() === '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes dot segments from a path and returns the new path.
|
||||
*
|
||||
* @param string $path
|
||||
*
|
||||
* @return string
|
||||
* @link http://tools.ietf.org/html/rfc3986#section-5.2.4
|
||||
*
|
||||
* @deprecated since version 1.4. Use UriResolver::removeDotSegments instead.
|
||||
* @see UriResolver::removeDotSegments
|
||||
*/
|
||||
public static function removeDotSegments($path)
|
||||
{
|
||||
static $noopPaths = ['' => true, '/' => true, '*' => true];
|
||||
static $ignoreSegments = ['.' => true, '..' => true];
|
||||
|
||||
if (isset($noopPaths[$path])) {
|
||||
return $path;
|
||||
}
|
||||
|
||||
$results = [];
|
||||
$segments = explode('/', $path);
|
||||
foreach ($segments as $segment) {
|
||||
if ($segment === '..') {
|
||||
array_pop($results);
|
||||
} elseif (!isset($ignoreSegments[$segment])) {
|
||||
$results[] = $segment;
|
||||
}
|
||||
}
|
||||
|
||||
$newPath = implode('/', $results);
|
||||
// Add the leading slash if necessary
|
||||
if (substr($path, 0, 1) === '/' &&
|
||||
substr($newPath, 0, 1) !== '/'
|
||||
) {
|
||||
$newPath = '/' . $newPath;
|
||||
}
|
||||
|
||||
// Add the trailing slash if necessary
|
||||
if ($newPath !== '/' && isset($ignoreSegments[end($segments)])) {
|
||||
$newPath .= '/';
|
||||
}
|
||||
|
||||
return $newPath;
|
||||
return UriResolver::removeDotSegments($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve a base URI with a relative URI and return a new URI.
|
||||
* Converts the relative URI into a new URI that is resolved against the base URI.
|
||||
*
|
||||
* @param UriInterface $base Base URI
|
||||
* @param string|UriInterface $rel Relative URI
|
||||
*
|
||||
* @return UriInterface
|
||||
* @link http://tools.ietf.org/html/rfc3986#section-5.2
|
||||
*
|
||||
* @deprecated since version 1.4. Use UriResolver::resolve instead.
|
||||
* @see UriResolver::resolve
|
||||
*/
|
||||
public static function resolve(UriInterface $base, $rel)
|
||||
{
|
||||
|
@ -125,55 +285,11 @@ class Uri implements UriInterface
|
|||
$rel = new self($rel);
|
||||
}
|
||||
|
||||
if ((string) $rel === '') {
|
||||
// we can simply return the same base URI instance for this same-document reference
|
||||
return $base;
|
||||
}
|
||||
|
||||
if ($rel->getScheme() != '') {
|
||||
return $rel->withPath(self::removeDotSegments($rel->getPath()));
|
||||
}
|
||||
|
||||
if ($rel->getAuthority() != '') {
|
||||
$targetAuthority = $rel->getAuthority();
|
||||
$targetPath = self::removeDotSegments($rel->getPath());
|
||||
$targetQuery = $rel->getQuery();
|
||||
} else {
|
||||
$targetAuthority = $base->getAuthority();
|
||||
if ($rel->getPath() === '') {
|
||||
$targetPath = $base->getPath();
|
||||
$targetQuery = $rel->getQuery() != '' ? $rel->getQuery() : $base->getQuery();
|
||||
} else {
|
||||
if ($rel->getPath()[0] === '/') {
|
||||
$targetPath = $rel->getPath();
|
||||
} else {
|
||||
if ($targetAuthority != '' && $base->getPath() === '') {
|
||||
$targetPath = '/' . $rel->getPath();
|
||||
} else {
|
||||
$lastSlashPos = strrpos($base->getPath(), '/');
|
||||
if ($lastSlashPos === false) {
|
||||
$targetPath = $rel->getPath();
|
||||
} else {
|
||||
$targetPath = substr($base->getPath(), 0, $lastSlashPos + 1) . $rel->getPath();
|
||||
}
|
||||
}
|
||||
}
|
||||
$targetPath = self::removeDotSegments($targetPath);
|
||||
$targetQuery = $rel->getQuery();
|
||||
}
|
||||
}
|
||||
|
||||
return new self(self::createUriString(
|
||||
$base->getScheme(),
|
||||
$targetAuthority,
|
||||
$targetPath,
|
||||
$targetQuery,
|
||||
$rel->getFragment()
|
||||
));
|
||||
return UriResolver::resolve($base, $rel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new URI with a specific query string value removed.
|
||||
* Creates a new URI with a specific query string value removed.
|
||||
*
|
||||
* Any existing query string values that exactly match the provided key are
|
||||
* removed.
|
||||
|
@ -185,21 +301,13 @@ class Uri implements UriInterface
|
|||
*/
|
||||
public static function withoutQueryValue(UriInterface $uri, $key)
|
||||
{
|
||||
$current = $uri->getQuery();
|
||||
if ($current == '') {
|
||||
return $uri;
|
||||
}
|
||||
|
||||
$decodedKey = rawurldecode($key);
|
||||
$result = array_filter(explode('&', $current), function ($part) use ($decodedKey) {
|
||||
return rawurldecode(explode('=', $part)[0]) !== $decodedKey;
|
||||
});
|
||||
$result = self::getFilteredQueryString($uri, [$key]);
|
||||
|
||||
return $uri->withQuery(implode('&', $result));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new URI with a specific query string value.
|
||||
* Creates a new URI with a specific query string value.
|
||||
*
|
||||
* Any existing query string values that exactly match the provided key are
|
||||
* removed and replaced with the given key value pair.
|
||||
|
@ -215,42 +323,50 @@ class Uri implements UriInterface
|
|||
*/
|
||||
public static function withQueryValue(UriInterface $uri, $key, $value)
|
||||
{
|
||||
$current = $uri->getQuery();
|
||||
$result = self::getFilteredQueryString($uri, [$key]);
|
||||
|
||||
if ($current == '') {
|
||||
$result = [];
|
||||
} else {
|
||||
$decodedKey = rawurldecode($key);
|
||||
$result = array_filter(explode('&', $current), function ($part) use ($decodedKey) {
|
||||
return rawurldecode(explode('=', $part)[0]) !== $decodedKey;
|
||||
});
|
||||
}
|
||||
$result[] = self::generateQueryString($key, $value);
|
||||
|
||||
// Query string separators ("=", "&") within the key or value need to be encoded
|
||||
// (while preventing double-encoding) before setting the query string. All other
|
||||
// chars that need percent-encoding will be encoded by withQuery().
|
||||
$key = strtr($key, self::$replaceQuery);
|
||||
return $uri->withQuery(implode('&', $result));
|
||||
}
|
||||
|
||||
if ($value !== null) {
|
||||
$result[] = $key . '=' . strtr($value, self::$replaceQuery);
|
||||
} else {
|
||||
$result[] = $key;
|
||||
/**
|
||||
* Creates a new URI with multiple specific query string values.
|
||||
*
|
||||
* It has the same behavior as withQueryValue() but for an associative array of key => value.
|
||||
*
|
||||
* @param UriInterface $uri URI to use as a base.
|
||||
* @param array $keyValueArray Associative array of key and values
|
||||
*
|
||||
* @return UriInterface
|
||||
*/
|
||||
public static function withQueryValues(UriInterface $uri, array $keyValueArray)
|
||||
{
|
||||
$result = self::getFilteredQueryString($uri, array_keys($keyValueArray));
|
||||
|
||||
foreach ($keyValueArray as $key => $value) {
|
||||
$result[] = self::generateQueryString($key, $value);
|
||||
}
|
||||
|
||||
return $uri->withQuery(implode('&', $result));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a URI from a hash of parse_url parts.
|
||||
* Creates a URI from a hash of `parse_url` components.
|
||||
*
|
||||
* @param array $parts
|
||||
*
|
||||
* @return self
|
||||
* @return UriInterface
|
||||
* @link http://php.net/manual/en/function.parse-url.php
|
||||
*
|
||||
* @throws \InvalidArgumentException If the components do not form a valid URI.
|
||||
*/
|
||||
public static function fromParts(array $parts)
|
||||
{
|
||||
$uri = new self();
|
||||
$uri->applyParts($parts);
|
||||
$uri->validateState();
|
||||
|
||||
return $uri;
|
||||
}
|
||||
|
||||
|
@ -261,12 +377,8 @@ class Uri implements UriInterface
|
|||
|
||||
public function getAuthority()
|
||||
{
|
||||
if ($this->host == '') {
|
||||
return '';
|
||||
}
|
||||
|
||||
$authority = $this->host;
|
||||
if ($this->userInfo != '') {
|
||||
if ($this->userInfo !== '') {
|
||||
$authority = $this->userInfo . '@' . $authority;
|
||||
}
|
||||
|
||||
|
@ -317,7 +429,9 @@ class Uri implements UriInterface
|
|||
|
||||
$new = clone $this;
|
||||
$new->scheme = $scheme;
|
||||
$new->port = $new->filterPort($new->port);
|
||||
$new->removeDefaultPort();
|
||||
$new->validateState();
|
||||
|
||||
return $new;
|
||||
}
|
||||
|
||||
|
@ -334,6 +448,8 @@ class Uri implements UriInterface
|
|||
|
||||
$new = clone $this;
|
||||
$new->userInfo = $info;
|
||||
$new->validateState();
|
||||
|
||||
return $new;
|
||||
}
|
||||
|
||||
|
@ -347,6 +463,8 @@ class Uri implements UriInterface
|
|||
|
||||
$new = clone $this;
|
||||
$new->host = $host;
|
||||
$new->validateState();
|
||||
|
||||
return $new;
|
||||
}
|
||||
|
||||
|
@ -360,6 +478,9 @@ class Uri implements UriInterface
|
|||
|
||||
$new = clone $this;
|
||||
$new->port = $port;
|
||||
$new->removeDefaultPort();
|
||||
$new->validateState();
|
||||
|
||||
return $new;
|
||||
}
|
||||
|
||||
|
@ -373,6 +494,8 @@ class Uri implements UriInterface
|
|||
|
||||
$new = clone $this;
|
||||
$new->path = $path;
|
||||
$new->validateState();
|
||||
|
||||
return $new;
|
||||
}
|
||||
|
||||
|
@ -386,6 +509,7 @@ class Uri implements UriInterface
|
|||
|
||||
$new = clone $this;
|
||||
$new->query = $query;
|
||||
|
||||
return $new;
|
||||
}
|
||||
|
||||
|
@ -399,6 +523,7 @@ class Uri implements UriInterface
|
|||
|
||||
$new = clone $this;
|
||||
$new->fragment = $fragment;
|
||||
|
||||
return $new;
|
||||
}
|
||||
|
||||
|
@ -431,69 +556,8 @@ class Uri implements UriInterface
|
|||
if (isset($parts['pass'])) {
|
||||
$this->userInfo .= ':' . $parts['pass'];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a URI string from its various parts
|
||||
*
|
||||
* @param string $scheme
|
||||
* @param string $authority
|
||||
* @param string $path
|
||||
* @param string $query
|
||||
* @param string $fragment
|
||||
* @return string
|
||||
*/
|
||||
private static function createUriString($scheme, $authority, $path, $query, $fragment)
|
||||
{
|
||||
$uri = '';
|
||||
|
||||
if ($scheme != '') {
|
||||
$uri .= $scheme . ':';
|
||||
}
|
||||
|
||||
if ($authority != '') {
|
||||
$uri .= '//' . $authority;
|
||||
}
|
||||
|
||||
if ($path != '') {
|
||||
if ($path[0] !== '/') {
|
||||
if ($authority != '') {
|
||||
// If the path is rootless and an authority is present, the path MUST be prefixed by "/"
|
||||
$path = '/' . $path;
|
||||
}
|
||||
} elseif (isset($path[1]) && $path[1] === '/') {
|
||||
if ($authority == '') {
|
||||
// If the path is starting with more than one "/" and no authority is present, the
|
||||
// starting slashes MUST be reduced to one.
|
||||
$path = '/' . ltrim($path, '/');
|
||||
}
|
||||
}
|
||||
|
||||
$uri .= $path;
|
||||
}
|
||||
|
||||
if ($query != '') {
|
||||
$uri .= '?' . $query;
|
||||
}
|
||||
|
||||
if ($fragment != '') {
|
||||
$uri .= '#' . $fragment;
|
||||
}
|
||||
|
||||
return $uri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is a given port non-standard for the current scheme?
|
||||
*
|
||||
* @param string $scheme
|
||||
* @param int $port
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private static function isNonStandardPort($scheme, $port)
|
||||
{
|
||||
return !isset(self::$schemes[$scheme]) || $port !== self::$schemes[$scheme];
|
||||
$this->removeDefaultPort();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -548,7 +612,55 @@ class Uri implements UriInterface
|
|||
);
|
||||
}
|
||||
|
||||
return self::isNonStandardPort($this->scheme, $port) ? $port : null;
|
||||
return $port;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param UriInterface $uri
|
||||
* @param array $keys
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private static function getFilteredQueryString(UriInterface $uri, array $keys)
|
||||
{
|
||||
$current = $uri->getQuery();
|
||||
|
||||
if ($current === '') {
|
||||
return [];
|
||||
}
|
||||
|
||||
$decodedKeys = array_map('rawurldecode', $keys);
|
||||
|
||||
return array_filter(explode('&', $current), function ($part) use ($decodedKeys) {
|
||||
return !in_array(rawurldecode(explode('=', $part)[0]), $decodedKeys, true);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @param string|null $value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private static function generateQueryString($key, $value)
|
||||
{
|
||||
// Query string separators ("=", "&") within the key or value need to be encoded
|
||||
// (while preventing double-encoding) before setting the query string. All other
|
||||
// chars that need percent-encoding will be encoded by withQuery().
|
||||
$queryString = strtr($key, self::$replaceQuery);
|
||||
|
||||
if ($value !== null) {
|
||||
$queryString .= '=' . strtr($value, self::$replaceQuery);
|
||||
}
|
||||
|
||||
return $queryString;
|
||||
}
|
||||
|
||||
private function removeDefaultPort()
|
||||
{
|
||||
if ($this->port !== null && self::isDefaultPort($this)) {
|
||||
$this->port = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -599,4 +711,28 @@ class Uri implements UriInterface
|
|||
{
|
||||
return rawurlencode($match[0]);
|
||||
}
|
||||
|
||||
private function validateState()
|
||||
{
|
||||
if ($this->host === '' && ($this->scheme === 'http' || $this->scheme === 'https')) {
|
||||
$this->host = self::HTTP_DEFAULT_HOST;
|
||||
}
|
||||
|
||||
if ($this->getAuthority() === '') {
|
||||
if (0 === strpos($this->path, '//')) {
|
||||
throw new \InvalidArgumentException('The path of a URI without an authority must not start with two slashes "//"');
|
||||
}
|
||||
if ($this->scheme === '' && false !== strpos(explode('/', $this->path, 2)[0], ':')) {
|
||||
throw new \InvalidArgumentException('A relative URI must not have a path beginning with a segment containing a colon');
|
||||
}
|
||||
} elseif (isset($this->path[0]) && $this->path[0] !== '/') {
|
||||
@trigger_error(
|
||||
'The path of a URI with an authority must start with a slash "/" or be empty. Automagically fixing the URI ' .
|
||||
'by adding a leading slash to the path is deprecated since version 1.4 and will throw an exception instead.',
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
$this->path = '/'. $this->path;
|
||||
//throw new \InvalidArgumentException('The path of a URI with an authority must start with a slash "/" or be empty');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
216
tests/integration/vendor/guzzlehttp/psr7/src/UriNormalizer.php
vendored
Normal file
216
tests/integration/vendor/guzzlehttp/psr7/src/UriNormalizer.php
vendored
Normal file
|
@ -0,0 +1,216 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Psr7;
|
||||
|
||||
use Psr\Http\Message\UriInterface;
|
||||
|
||||
/**
|
||||
* Provides methods to normalize and compare URIs.
|
||||
*
|
||||
* @author Tobias Schultze
|
||||
*
|
||||
* @link https://tools.ietf.org/html/rfc3986#section-6
|
||||
*/
|
||||
final class UriNormalizer
|
||||
{
|
||||
/**
|
||||
* Default normalizations which only include the ones that preserve semantics.
|
||||
*
|
||||
* self::CAPITALIZE_PERCENT_ENCODING | self::DECODE_UNRESERVED_CHARACTERS | self::CONVERT_EMPTY_PATH |
|
||||
* self::REMOVE_DEFAULT_HOST | self::REMOVE_DEFAULT_PORT | self::REMOVE_DOT_SEGMENTS
|
||||
*/
|
||||
const PRESERVING_NORMALIZATIONS = 63;
|
||||
|
||||
/**
|
||||
* All letters within a percent-encoding triplet (e.g., "%3A") are case-insensitive, and should be capitalized.
|
||||
*
|
||||
* Example: http://example.org/a%c2%b1b → http://example.org/a%C2%B1b
|
||||
*/
|
||||
const CAPITALIZE_PERCENT_ENCODING = 1;
|
||||
|
||||
/**
|
||||
* Decodes percent-encoded octets of unreserved characters.
|
||||
*
|
||||
* For consistency, percent-encoded octets in the ranges of ALPHA (%41–%5A and %61–%7A), DIGIT (%30–%39),
|
||||
* hyphen (%2D), period (%2E), underscore (%5F), or tilde (%7E) should not be created by URI producers and,
|
||||
* when found in a URI, should be decoded to their corresponding unreserved characters by URI normalizers.
|
||||
*
|
||||
* Example: http://example.org/%7Eusern%61me/ → http://example.org/~username/
|
||||
*/
|
||||
const DECODE_UNRESERVED_CHARACTERS = 2;
|
||||
|
||||
/**
|
||||
* Converts the empty path to "/" for http and https URIs.
|
||||
*
|
||||
* Example: http://example.org → http://example.org/
|
||||
*/
|
||||
const CONVERT_EMPTY_PATH = 4;
|
||||
|
||||
/**
|
||||
* Removes the default host of the given URI scheme from the URI.
|
||||
*
|
||||
* Only the "file" scheme defines the default host "localhost".
|
||||
* All of `file:/myfile`, `file:///myfile`, and `file://localhost/myfile`
|
||||
* are equivalent according to RFC 3986. The first format is not accepted
|
||||
* by PHPs stream functions and thus already normalized implicitly to the
|
||||
* second format in the Uri class. See `GuzzleHttp\Psr7\Uri::composeComponents`.
|
||||
*
|
||||
* Example: file://localhost/myfile → file:///myfile
|
||||
*/
|
||||
const REMOVE_DEFAULT_HOST = 8;
|
||||
|
||||
/**
|
||||
* Removes the default port of the given URI scheme from the URI.
|
||||
*
|
||||
* Example: http://example.org:80/ → http://example.org/
|
||||
*/
|
||||
const REMOVE_DEFAULT_PORT = 16;
|
||||
|
||||
/**
|
||||
* Removes unnecessary dot-segments.
|
||||
*
|
||||
* Dot-segments in relative-path references are not removed as it would
|
||||
* change the semantics of the URI reference.
|
||||
*
|
||||
* Example: http://example.org/../a/b/../c/./d.html → http://example.org/a/c/d.html
|
||||
*/
|
||||
const REMOVE_DOT_SEGMENTS = 32;
|
||||
|
||||
/**
|
||||
* Paths which include two or more adjacent slashes are converted to one.
|
||||
*
|
||||
* Webservers usually ignore duplicate slashes and treat those URIs equivalent.
|
||||
* But in theory those URIs do not need to be equivalent. So this normalization
|
||||
* may change the semantics. Encoded slashes (%2F) are not removed.
|
||||
*
|
||||
* Example: http://example.org//foo///bar.html → http://example.org/foo/bar.html
|
||||
*/
|
||||
const REMOVE_DUPLICATE_SLASHES = 64;
|
||||
|
||||
/**
|
||||
* Sort query parameters with their values in alphabetical order.
|
||||
*
|
||||
* However, the order of parameters in a URI may be significant (this is not defined by the standard).
|
||||
* So this normalization is not safe and may change the semantics of the URI.
|
||||
*
|
||||
* Example: ?lang=en&article=fred → ?article=fred&lang=en
|
||||
*
|
||||
* Note: The sorting is neither locale nor Unicode aware (the URI query does not get decoded at all) as the
|
||||
* purpose is to be able to compare URIs in a reproducible way, not to have the params sorted perfectly.
|
||||
*/
|
||||
const SORT_QUERY_PARAMETERS = 128;
|
||||
|
||||
/**
|
||||
* Returns a normalized URI.
|
||||
*
|
||||
* The scheme and host component are already normalized to lowercase per PSR-7 UriInterface.
|
||||
* This methods adds additional normalizations that can be configured with the $flags parameter.
|
||||
*
|
||||
* PSR-7 UriInterface cannot distinguish between an empty component and a missing component as
|
||||
* getQuery(), getFragment() etc. always return a string. This means the URIs "/?#" and "/" are
|
||||
* treated equivalent which is not necessarily true according to RFC 3986. But that difference
|
||||
* is highly uncommon in reality. So this potential normalization is implied in PSR-7 as well.
|
||||
*
|
||||
* @param UriInterface $uri The URI to normalize
|
||||
* @param int $flags A bitmask of normalizations to apply, see constants
|
||||
*
|
||||
* @return UriInterface The normalized URI
|
||||
* @link https://tools.ietf.org/html/rfc3986#section-6.2
|
||||
*/
|
||||
public static function normalize(UriInterface $uri, $flags = self::PRESERVING_NORMALIZATIONS)
|
||||
{
|
||||
if ($flags & self::CAPITALIZE_PERCENT_ENCODING) {
|
||||
$uri = self::capitalizePercentEncoding($uri);
|
||||
}
|
||||
|
||||
if ($flags & self::DECODE_UNRESERVED_CHARACTERS) {
|
||||
$uri = self::decodeUnreservedCharacters($uri);
|
||||
}
|
||||
|
||||
if ($flags & self::CONVERT_EMPTY_PATH && $uri->getPath() === '' &&
|
||||
($uri->getScheme() === 'http' || $uri->getScheme() === 'https')
|
||||
) {
|
||||
$uri = $uri->withPath('/');
|
||||
}
|
||||
|
||||
if ($flags & self::REMOVE_DEFAULT_HOST && $uri->getScheme() === 'file' && $uri->getHost() === 'localhost') {
|
||||
$uri = $uri->withHost('');
|
||||
}
|
||||
|
||||
if ($flags & self::REMOVE_DEFAULT_PORT && $uri->getPort() !== null && Uri::isDefaultPort($uri)) {
|
||||
$uri = $uri->withPort(null);
|
||||
}
|
||||
|
||||
if ($flags & self::REMOVE_DOT_SEGMENTS && !Uri::isRelativePathReference($uri)) {
|
||||
$uri = $uri->withPath(UriResolver::removeDotSegments($uri->getPath()));
|
||||
}
|
||||
|
||||
if ($flags & self::REMOVE_DUPLICATE_SLASHES) {
|
||||
$uri = $uri->withPath(preg_replace('#//++#', '/', $uri->getPath()));
|
||||
}
|
||||
|
||||
if ($flags & self::SORT_QUERY_PARAMETERS && $uri->getQuery() !== '') {
|
||||
$queryKeyValues = explode('&', $uri->getQuery());
|
||||
sort($queryKeyValues);
|
||||
$uri = $uri->withQuery(implode('&', $queryKeyValues));
|
||||
}
|
||||
|
||||
return $uri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether two URIs can be considered equivalent.
|
||||
*
|
||||
* Both URIs are normalized automatically before comparison with the given $normalizations bitmask. The method also
|
||||
* accepts relative URI references and returns true when they are equivalent. This of course assumes they will be
|
||||
* resolved against the same base URI. If this is not the case, determination of equivalence or difference of
|
||||
* relative references does not mean anything.
|
||||
*
|
||||
* @param UriInterface $uri1 An URI to compare
|
||||
* @param UriInterface $uri2 An URI to compare
|
||||
* @param int $normalizations A bitmask of normalizations to apply, see constants
|
||||
*
|
||||
* @return bool
|
||||
* @link https://tools.ietf.org/html/rfc3986#section-6.1
|
||||
*/
|
||||
public static function isEquivalent(UriInterface $uri1, UriInterface $uri2, $normalizations = self::PRESERVING_NORMALIZATIONS)
|
||||
{
|
||||
return (string) self::normalize($uri1, $normalizations) === (string) self::normalize($uri2, $normalizations);
|
||||
}
|
||||
|
||||
private static function capitalizePercentEncoding(UriInterface $uri)
|
||||
{
|
||||
$regex = '/(?:%[A-Fa-f0-9]{2})++/';
|
||||
|
||||
$callback = function (array $match) {
|
||||
return strtoupper($match[0]);
|
||||
};
|
||||
|
||||
return
|
||||
$uri->withPath(
|
||||
preg_replace_callback($regex, $callback, $uri->getPath())
|
||||
)->withQuery(
|
||||
preg_replace_callback($regex, $callback, $uri->getQuery())
|
||||
);
|
||||
}
|
||||
|
||||
private static function decodeUnreservedCharacters(UriInterface $uri)
|
||||
{
|
||||
$regex = '/%(?:2D|2E|5F|7E|3[0-9]|[46][1-9A-F]|[57][0-9A])/i';
|
||||
|
||||
$callback = function (array $match) {
|
||||
return rawurldecode($match[0]);
|
||||
};
|
||||
|
||||
return
|
||||
$uri->withPath(
|
||||
preg_replace_callback($regex, $callback, $uri->getPath())
|
||||
)->withQuery(
|
||||
preg_replace_callback($regex, $callback, $uri->getQuery())
|
||||
);
|
||||
}
|
||||
|
||||
private function __construct()
|
||||
{
|
||||
// cannot be instantiated
|
||||
}
|
||||
}
|
219
tests/integration/vendor/guzzlehttp/psr7/src/UriResolver.php
vendored
Normal file
219
tests/integration/vendor/guzzlehttp/psr7/src/UriResolver.php
vendored
Normal file
|
@ -0,0 +1,219 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Psr7;
|
||||
|
||||
use Psr\Http\Message\UriInterface;
|
||||
|
||||
/**
|
||||
* Resolves a URI reference in the context of a base URI and the opposite way.
|
||||
*
|
||||
* @author Tobias Schultze
|
||||
*
|
||||
* @link https://tools.ietf.org/html/rfc3986#section-5
|
||||
*/
|
||||
final class UriResolver
|
||||
{
|
||||
/**
|
||||
* Removes dot segments from a path and returns the new path.
|
||||
*
|
||||
* @param string $path
|
||||
*
|
||||
* @return string
|
||||
* @link http://tools.ietf.org/html/rfc3986#section-5.2.4
|
||||
*/
|
||||
public static function removeDotSegments($path)
|
||||
{
|
||||
if ($path === '' || $path === '/') {
|
||||
return $path;
|
||||
}
|
||||
|
||||
$results = [];
|
||||
$segments = explode('/', $path);
|
||||
foreach ($segments as $segment) {
|
||||
if ($segment === '..') {
|
||||
array_pop($results);
|
||||
} elseif ($segment !== '.') {
|
||||
$results[] = $segment;
|
||||
}
|
||||
}
|
||||
|
||||
$newPath = implode('/', $results);
|
||||
|
||||
if ($path[0] === '/' && (!isset($newPath[0]) || $newPath[0] !== '/')) {
|
||||
// Re-add the leading slash if necessary for cases like "/.."
|
||||
$newPath = '/' . $newPath;
|
||||
} elseif ($newPath !== '' && ($segment === '.' || $segment === '..')) {
|
||||
// Add the trailing slash if necessary
|
||||
// If newPath is not empty, then $segment must be set and is the last segment from the foreach
|
||||
$newPath .= '/';
|
||||
}
|
||||
|
||||
return $newPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the relative URI into a new URI that is resolved against the base URI.
|
||||
*
|
||||
* @param UriInterface $base Base URI
|
||||
* @param UriInterface $rel Relative URI
|
||||
*
|
||||
* @return UriInterface
|
||||
* @link http://tools.ietf.org/html/rfc3986#section-5.2
|
||||
*/
|
||||
public static function resolve(UriInterface $base, UriInterface $rel)
|
||||
{
|
||||
if ((string) $rel === '') {
|
||||
// we can simply return the same base URI instance for this same-document reference
|
||||
return $base;
|
||||
}
|
||||
|
||||
if ($rel->getScheme() != '') {
|
||||
return $rel->withPath(self::removeDotSegments($rel->getPath()));
|
||||
}
|
||||
|
||||
if ($rel->getAuthority() != '') {
|
||||
$targetAuthority = $rel->getAuthority();
|
||||
$targetPath = self::removeDotSegments($rel->getPath());
|
||||
$targetQuery = $rel->getQuery();
|
||||
} else {
|
||||
$targetAuthority = $base->getAuthority();
|
||||
if ($rel->getPath() === '') {
|
||||
$targetPath = $base->getPath();
|
||||
$targetQuery = $rel->getQuery() != '' ? $rel->getQuery() : $base->getQuery();
|
||||
} else {
|
||||
if ($rel->getPath()[0] === '/') {
|
||||
$targetPath = $rel->getPath();
|
||||
} else {
|
||||
if ($targetAuthority != '' && $base->getPath() === '') {
|
||||
$targetPath = '/' . $rel->getPath();
|
||||
} else {
|
||||
$lastSlashPos = strrpos($base->getPath(), '/');
|
||||
if ($lastSlashPos === false) {
|
||||
$targetPath = $rel->getPath();
|
||||
} else {
|
||||
$targetPath = substr($base->getPath(), 0, $lastSlashPos + 1) . $rel->getPath();
|
||||
}
|
||||
}
|
||||
}
|
||||
$targetPath = self::removeDotSegments($targetPath);
|
||||
$targetQuery = $rel->getQuery();
|
||||
}
|
||||
}
|
||||
|
||||
return new Uri(Uri::composeComponents(
|
||||
$base->getScheme(),
|
||||
$targetAuthority,
|
||||
$targetPath,
|
||||
$targetQuery,
|
||||
$rel->getFragment()
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the target URI as a relative reference from the base URI.
|
||||
*
|
||||
* This method is the counterpart to resolve():
|
||||
*
|
||||
* (string) $target === (string) UriResolver::resolve($base, UriResolver::relativize($base, $target))
|
||||
*
|
||||
* One use-case is to use the current request URI as base URI and then generate relative links in your documents
|
||||
* to reduce the document size or offer self-contained downloadable document archives.
|
||||
*
|
||||
* $base = new Uri('http://example.com/a/b/');
|
||||
* echo UriResolver::relativize($base, new Uri('http://example.com/a/b/c')); // prints 'c'.
|
||||
* echo UriResolver::relativize($base, new Uri('http://example.com/a/x/y')); // prints '../x/y'.
|
||||
* echo UriResolver::relativize($base, new Uri('http://example.com/a/b/?q')); // prints '?q'.
|
||||
* echo UriResolver::relativize($base, new Uri('http://example.org/a/b/')); // prints '//example.org/a/b/'.
|
||||
*
|
||||
* This method also accepts a target that is already relative and will try to relativize it further. Only a
|
||||
* relative-path reference will be returned as-is.
|
||||
*
|
||||
* echo UriResolver::relativize($base, new Uri('/a/b/c')); // prints 'c' as well
|
||||
*
|
||||
* @param UriInterface $base Base URI
|
||||
* @param UriInterface $target Target URI
|
||||
*
|
||||
* @return UriInterface The relative URI reference
|
||||
*/
|
||||
public static function relativize(UriInterface $base, UriInterface $target)
|
||||
{
|
||||
if ($target->getScheme() !== '' &&
|
||||
($base->getScheme() !== $target->getScheme() || $target->getAuthority() === '' && $base->getAuthority() !== '')
|
||||
) {
|
||||
return $target;
|
||||
}
|
||||
|
||||
if (Uri::isRelativePathReference($target)) {
|
||||
// As the target is already highly relative we return it as-is. It would be possible to resolve
|
||||
// the target with `$target = self::resolve($base, $target);` and then try make it more relative
|
||||
// by removing a duplicate query. But let's not do that automatically.
|
||||
return $target;
|
||||
}
|
||||
|
||||
if ($target->getAuthority() !== '' && $base->getAuthority() !== $target->getAuthority()) {
|
||||
return $target->withScheme('');
|
||||
}
|
||||
|
||||
// We must remove the path before removing the authority because if the path starts with two slashes, the URI
|
||||
// would turn invalid. And we also cannot set a relative path before removing the authority, as that is also
|
||||
// invalid.
|
||||
$emptyPathUri = $target->withScheme('')->withPath('')->withUserInfo('')->withPort(null)->withHost('');
|
||||
|
||||
if ($base->getPath() !== $target->getPath()) {
|
||||
return $emptyPathUri->withPath(self::getRelativePath($base, $target));
|
||||
}
|
||||
|
||||
if ($base->getQuery() === $target->getQuery()) {
|
||||
// Only the target fragment is left. And it must be returned even if base and target fragment are the same.
|
||||
return $emptyPathUri->withQuery('');
|
||||
}
|
||||
|
||||
// If the base URI has a query but the target has none, we cannot return an empty path reference as it would
|
||||
// inherit the base query component when resolving.
|
||||
if ($target->getQuery() === '') {
|
||||
$segments = explode('/', $target->getPath());
|
||||
$lastSegment = end($segments);
|
||||
|
||||
return $emptyPathUri->withPath($lastSegment === '' ? './' : $lastSegment);
|
||||
}
|
||||
|
||||
return $emptyPathUri;
|
||||
}
|
||||
|
||||
private static function getRelativePath(UriInterface $base, UriInterface $target)
|
||||
{
|
||||
$sourceSegments = explode('/', $base->getPath());
|
||||
$targetSegments = explode('/', $target->getPath());
|
||||
array_pop($sourceSegments);
|
||||
$targetLastSegment = array_pop($targetSegments);
|
||||
foreach ($sourceSegments as $i => $segment) {
|
||||
if (isset($targetSegments[$i]) && $segment === $targetSegments[$i]) {
|
||||
unset($sourceSegments[$i], $targetSegments[$i]);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
$targetSegments[] = $targetLastSegment;
|
||||
$relativePath = str_repeat('../', count($sourceSegments)) . implode('/', $targetSegments);
|
||||
|
||||
// A reference to am empty last segment or an empty first sub-segment must be prefixed with "./".
|
||||
// This also applies to a segment with a colon character (e.g., "file:colon") that cannot be used
|
||||
// as the first segment of a relative-path reference, as it would be mistaken for a scheme name.
|
||||
if ('' === $relativePath || false !== strpos(explode('/', $relativePath, 2)[0], ':')) {
|
||||
$relativePath = "./$relativePath";
|
||||
} elseif ('/' === $relativePath[0]) {
|
||||
if ($base->getAuthority() != '' && $base->getPath() === '') {
|
||||
// In this case an extra slash is added by resolve() automatically. So we must not add one here.
|
||||
$relativePath = ".$relativePath";
|
||||
} else {
|
||||
$relativePath = "./$relativePath";
|
||||
}
|
||||
}
|
||||
|
||||
return $relativePath;
|
||||
}
|
||||
|
||||
private function __construct()
|
||||
{
|
||||
// cannot be instantiated
|
||||
}
|
||||
}
|
|
@ -69,10 +69,10 @@ function uri_for($uri)
|
|||
* - metadata: Array of custom metadata.
|
||||
* - size: Size of the stream.
|
||||
*
|
||||
* @param resource|string|null|int|float|bool|StreamInterface|callable $resource Entity body data
|
||||
* @param array $options Additional options
|
||||
* @param resource|string|null|int|float|bool|StreamInterface|callable|\Iterator $resource Entity body data
|
||||
* @param array $options Additional options
|
||||
*
|
||||
* @return Stream
|
||||
* @return StreamInterface
|
||||
* @throws \InvalidArgumentException if the $resource arg is not valid.
|
||||
*/
|
||||
function stream_for($resource = '', array $options = [])
|
||||
|
@ -238,7 +238,7 @@ function modify_request(RequestInterface $request, array $changes)
|
|||
}
|
||||
|
||||
if ($request instanceof ServerRequestInterface) {
|
||||
return new ServerRequest(
|
||||
return (new ServerRequest(
|
||||
isset($changes['method']) ? $changes['method'] : $request->getMethod(),
|
||||
$uri,
|
||||
$headers,
|
||||
|
@ -247,7 +247,11 @@ function modify_request(RequestInterface $request, array $changes)
|
|||
? $changes['version']
|
||||
: $request->getProtocolVersion(),
|
||||
$request->getServerParams()
|
||||
);
|
||||
))
|
||||
->withParsedBody($request->getParsedBody())
|
||||
->withQueryParams($request->getQueryParams())
|
||||
->withCookieParams($request->getCookieParams())
|
||||
->withUploadedFiles($request->getUploadedFiles());
|
||||
}
|
||||
|
||||
return new Request(
|
||||
|
@ -371,25 +375,24 @@ function copy_to_stream(
|
|||
StreamInterface $dest,
|
||||
$maxLen = -1
|
||||
) {
|
||||
$bufferSize = 8192;
|
||||
|
||||
if ($maxLen === -1) {
|
||||
while (!$source->eof()) {
|
||||
if (!$dest->write($source->read(1048576))) {
|
||||
if (!$dest->write($source->read($bufferSize))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
$bytes = 0;
|
||||
while (!$source->eof()) {
|
||||
$buf = $source->read($maxLen - $bytes);
|
||||
if (!($len = strlen($buf))) {
|
||||
break;
|
||||
}
|
||||
$bytes += $len;
|
||||
$dest->write($buf);
|
||||
if ($bytes == $maxLen) {
|
||||
break;
|
||||
} else {
|
||||
$remaining = $maxLen;
|
||||
while ($remaining > 0 && !$source->eof()) {
|
||||
$buf = $source->read(min($bufferSize, $remaining));
|
||||
$len = strlen($buf);
|
||||
if (!$len) {
|
||||
break;
|
||||
}
|
||||
$remaining -= $len;
|
||||
$dest->write($buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -432,7 +435,7 @@ function hash(
|
|||
* @param StreamInterface $stream Stream to read from
|
||||
* @param int $maxLength Maximum buffer length
|
||||
*
|
||||
* @return string|bool
|
||||
* @return string
|
||||
*/
|
||||
function readline(StreamInterface $stream, $maxLength = null)
|
||||
{
|
||||
|
@ -492,8 +495,11 @@ function parse_request($message)
|
|||
function parse_response($message)
|
||||
{
|
||||
$data = _parse_message($message);
|
||||
if (!preg_match('/^HTTP\/.* [0-9]{3} .*/', $data['start-line'])) {
|
||||
throw new \InvalidArgumentException('Invalid response string');
|
||||
// According to https://tools.ietf.org/html/rfc7230#section-3.1.2 the space
|
||||
// between status-code and reason-phrase is required. But browsers accept
|
||||
// responses without space and reason as well.
|
||||
if (!preg_match('/^HTTP\/.* [0-9]{3}( .*|$)/', $data['start-line'])) {
|
||||
throw new \InvalidArgumentException('Invalid response string: ' . $data['start-line']);
|
||||
}
|
||||
$parts = explode(' ', $data['start-line'], 3);
|
||||
|
||||
|
@ -514,8 +520,8 @@ function parse_response($message)
|
|||
* PHP style arrays into an associative array (e.g., foo[a]=1&foo[b]=2 will
|
||||
* be parsed into ['foo[a]' => '1', 'foo[b]' => '2']).
|
||||
*
|
||||
* @param string $str Query string to parse
|
||||
* @param bool|string $urlEncoding How the query string is encoded
|
||||
* @param string $str Query string to parse
|
||||
* @param int|bool $urlEncoding How the query string is encoded
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
|
@ -531,9 +537,9 @@ function parse_query($str, $urlEncoding = true)
|
|||
$decoder = function ($value) {
|
||||
return rawurldecode(str_replace('+', ' ', $value));
|
||||
};
|
||||
} elseif ($urlEncoding == PHP_QUERY_RFC3986) {
|
||||
} elseif ($urlEncoding === PHP_QUERY_RFC3986) {
|
||||
$decoder = 'rawurldecode';
|
||||
} elseif ($urlEncoding == PHP_QUERY_RFC1738) {
|
||||
} elseif ($urlEncoding === PHP_QUERY_RFC1738) {
|
||||
$decoder = 'urldecode';
|
||||
} else {
|
||||
$decoder = function ($str) { return $str; };
|
||||
|
@ -631,6 +637,7 @@ function mimetype_from_filename($filename)
|
|||
function mimetype_from_extension($extension)
|
||||
{
|
||||
static $mimetypes = [
|
||||
'3gp' => 'video/3gpp',
|
||||
'7z' => 'application/x-7z-compressed',
|
||||
'aac' => 'audio/x-aac',
|
||||
'ai' => 'application/postscript',
|
||||
|
@ -678,6 +685,7 @@ function mimetype_from_extension($extension)
|
|||
'mid' => 'audio/midi',
|
||||
'midi' => 'audio/midi',
|
||||
'mov' => 'video/quicktime',
|
||||
'mkv' => 'video/x-matroska',
|
||||
'mp3' => 'audio/mpeg',
|
||||
'mp4' => 'video/mp4',
|
||||
'mp4a' => 'audio/mp4',
|
||||
|
@ -756,29 +764,53 @@ function _parse_message($message)
|
|||
throw new \InvalidArgumentException('Invalid message');
|
||||
}
|
||||
|
||||
// Iterate over each line in the message, accounting for line endings
|
||||
$lines = preg_split('/(\\r?\\n)/', $message, -1, PREG_SPLIT_DELIM_CAPTURE);
|
||||
$result = ['start-line' => array_shift($lines), 'headers' => [], 'body' => ''];
|
||||
array_shift($lines);
|
||||
$message = ltrim($message, "\r\n");
|
||||
|
||||
for ($i = 0, $totalLines = count($lines); $i < $totalLines; $i += 2) {
|
||||
$line = $lines[$i];
|
||||
// If two line breaks were encountered, then this is the end of body
|
||||
if (empty($line)) {
|
||||
if ($i < $totalLines - 1) {
|
||||
$result['body'] = implode('', array_slice($lines, $i + 2));
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (strpos($line, ':')) {
|
||||
$parts = explode(':', $line, 2);
|
||||
$key = trim($parts[0]);
|
||||
$value = isset($parts[1]) ? trim($parts[1]) : '';
|
||||
$result['headers'][$key][] = $value;
|
||||
}
|
||||
$messageParts = preg_split("/\r?\n\r?\n/", $message, 2);
|
||||
|
||||
if ($messageParts === false || count($messageParts) !== 2) {
|
||||
throw new \InvalidArgumentException('Invalid message: Missing header delimiter');
|
||||
}
|
||||
|
||||
return $result;
|
||||
list($rawHeaders, $body) = $messageParts;
|
||||
$rawHeaders .= "\r\n"; // Put back the delimiter we split previously
|
||||
$headerParts = preg_split("/\r?\n/", $rawHeaders, 2);
|
||||
|
||||
if ($headerParts === false || count($headerParts) !== 2) {
|
||||
throw new \InvalidArgumentException('Invalid message: Missing status line');
|
||||
}
|
||||
|
||||
list($startLine, $rawHeaders) = $headerParts;
|
||||
|
||||
if (preg_match("/(?:^HTTP\/|^[A-Z]+ \S+ HTTP\/)(\d+(?:\.\d+)?)/i", $startLine, $matches) && $matches[1] === '1.0') {
|
||||
// Header folding is deprecated for HTTP/1.1, but allowed in HTTP/1.0
|
||||
$rawHeaders = preg_replace(Rfc7230::HEADER_FOLD_REGEX, ' ', $rawHeaders);
|
||||
}
|
||||
|
||||
/** @var array[] $headerLines */
|
||||
$count = preg_match_all(Rfc7230::HEADER_REGEX, $rawHeaders, $headerLines, PREG_SET_ORDER);
|
||||
|
||||
// If these aren't the same, then one line didn't match and there's an invalid header.
|
||||
if ($count !== substr_count($rawHeaders, "\n")) {
|
||||
// Folding is deprecated, see https://tools.ietf.org/html/rfc7230#section-3.2.4
|
||||
if (preg_match(Rfc7230::HEADER_FOLD_REGEX, $rawHeaders)) {
|
||||
throw new \InvalidArgumentException('Invalid header syntax: Obsolete line folding');
|
||||
}
|
||||
|
||||
throw new \InvalidArgumentException('Invalid header syntax');
|
||||
}
|
||||
|
||||
$headers = [];
|
||||
|
||||
foreach ($headerLines as $headerLine) {
|
||||
$headers[$headerLine[1]][] = $headerLine[2];
|
||||
}
|
||||
|
||||
return [
|
||||
'start-line' => $startLine,
|
||||
'headers' => $headers,
|
||||
'body' => $body,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -807,6 +839,46 @@ function _parse_request_uri($path, array $headers)
|
|||
return $scheme . '://' . $host . '/' . ltrim($path, '/');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a short summary of the message body
|
||||
*
|
||||
* Will return `null` if the response is not printable.
|
||||
*
|
||||
* @param MessageInterface $message The message to get the body summary
|
||||
* @param int $truncateAt The maximum allowed size of the summary
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
function get_message_body_summary(MessageInterface $message, $truncateAt = 120)
|
||||
{
|
||||
$body = $message->getBody();
|
||||
|
||||
if (!$body->isSeekable() || !$body->isReadable()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$size = $body->getSize();
|
||||
|
||||
if ($size === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$summary = $body->read($truncateAt);
|
||||
$body->rewind();
|
||||
|
||||
if ($size > $truncateAt) {
|
||||
$summary .= ' (truncated...)';
|
||||
}
|
||||
|
||||
// Matches any printable character, including unicode characters:
|
||||
// letters, marks, numbers, punctuation, spacing, and separators.
|
||||
if (preg_match('/[^\pL\pM\pN\pP\pS\pZ\n\r\t]/', $summary)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $summary;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
function _caseless_remove($keys, array $data)
|
||||
{
|
||||
|
|
|
@ -1,186 +0,0 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Tests\Psr7;
|
||||
|
||||
use GuzzleHttp\Psr7\AppendStream;
|
||||
use GuzzleHttp\Psr7;
|
||||
|
||||
class AppendStreamTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* @expectedException \InvalidArgumentException
|
||||
* @expectedExceptionMessage Each stream must be readable
|
||||
*/
|
||||
public function testValidatesStreamsAreReadable()
|
||||
{
|
||||
$a = new AppendStream();
|
||||
$s = $this->getMockBuilder('Psr\Http\Message\StreamInterface')
|
||||
->setMethods(['isReadable'])
|
||||
->getMockForAbstractClass();
|
||||
$s->expects($this->once())
|
||||
->method('isReadable')
|
||||
->will($this->returnValue(false));
|
||||
$a->addStream($s);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \RuntimeException
|
||||
* @expectedExceptionMessage The AppendStream can only seek with SEEK_SET
|
||||
*/
|
||||
public function testValidatesSeekType()
|
||||
{
|
||||
$a = new AppendStream();
|
||||
$a->seek(100, SEEK_CUR);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \RuntimeException
|
||||
* @expectedExceptionMessage Unable to seek stream 0 of the AppendStream
|
||||
*/
|
||||
public function testTriesToRewindOnSeek()
|
||||
{
|
||||
$a = new AppendStream();
|
||||
$s = $this->getMockBuilder('Psr\Http\Message\StreamInterface')
|
||||
->setMethods(['isReadable', 'rewind', 'isSeekable'])
|
||||
->getMockForAbstractClass();
|
||||
$s->expects($this->once())
|
||||
->method('isReadable')
|
||||
->will($this->returnValue(true));
|
||||
$s->expects($this->once())
|
||||
->method('isSeekable')
|
||||
->will($this->returnValue(true));
|
||||
$s->expects($this->once())
|
||||
->method('rewind')
|
||||
->will($this->throwException(new \RuntimeException()));
|
||||
$a->addStream($s);
|
||||
$a->seek(10);
|
||||
}
|
||||
|
||||
public function testSeeksToPositionByReading()
|
||||
{
|
||||
$a = new AppendStream([
|
||||
Psr7\stream_for('foo'),
|
||||
Psr7\stream_for('bar'),
|
||||
Psr7\stream_for('baz'),
|
||||
]);
|
||||
|
||||
$a->seek(3);
|
||||
$this->assertEquals(3, $a->tell());
|
||||
$this->assertEquals('bar', $a->read(3));
|
||||
|
||||
$a->seek(6);
|
||||
$this->assertEquals(6, $a->tell());
|
||||
$this->assertEquals('baz', $a->read(3));
|
||||
}
|
||||
|
||||
public function testDetachesEachStream()
|
||||
{
|
||||
$s1 = Psr7\stream_for('foo');
|
||||
$s2 = Psr7\stream_for('bar');
|
||||
$a = new AppendStream([$s1, $s2]);
|
||||
$this->assertSame('foobar', (string) $a);
|
||||
$a->detach();
|
||||
$this->assertSame('', (string) $a);
|
||||
$this->assertSame(0, $a->getSize());
|
||||
}
|
||||
|
||||
public function testClosesEachStream()
|
||||
{
|
||||
$s1 = Psr7\stream_for('foo');
|
||||
$a = new AppendStream([$s1]);
|
||||
$a->close();
|
||||
$this->assertSame('', (string) $a);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedExceptionMessage Cannot write to an AppendStream
|
||||
* @expectedException \RuntimeException
|
||||
*/
|
||||
public function testIsNotWritable()
|
||||
{
|
||||
$a = new AppendStream([Psr7\stream_for('foo')]);
|
||||
$this->assertFalse($a->isWritable());
|
||||
$this->assertTrue($a->isSeekable());
|
||||
$this->assertTrue($a->isReadable());
|
||||
$a->write('foo');
|
||||
}
|
||||
|
||||
public function testDoesNotNeedStreams()
|
||||
{
|
||||
$a = new AppendStream();
|
||||
$this->assertEquals('', (string) $a);
|
||||
}
|
||||
|
||||
public function testCanReadFromMultipleStreams()
|
||||
{
|
||||
$a = new AppendStream([
|
||||
Psr7\stream_for('foo'),
|
||||
Psr7\stream_for('bar'),
|
||||
Psr7\stream_for('baz'),
|
||||
]);
|
||||
$this->assertFalse($a->eof());
|
||||
$this->assertSame(0, $a->tell());
|
||||
$this->assertEquals('foo', $a->read(3));
|
||||
$this->assertEquals('bar', $a->read(3));
|
||||
$this->assertEquals('baz', $a->read(3));
|
||||
$this->assertSame('', $a->read(1));
|
||||
$this->assertTrue($a->eof());
|
||||
$this->assertSame(9, $a->tell());
|
||||
$this->assertEquals('foobarbaz', (string) $a);
|
||||
}
|
||||
|
||||
public function testCanDetermineSizeFromMultipleStreams()
|
||||
{
|
||||
$a = new AppendStream([
|
||||
Psr7\stream_for('foo'),
|
||||
Psr7\stream_for('bar')
|
||||
]);
|
||||
$this->assertEquals(6, $a->getSize());
|
||||
|
||||
$s = $this->getMockBuilder('Psr\Http\Message\StreamInterface')
|
||||
->setMethods(['isSeekable', 'isReadable'])
|
||||
->getMockForAbstractClass();
|
||||
$s->expects($this->once())
|
||||
->method('isSeekable')
|
||||
->will($this->returnValue(null));
|
||||
$s->expects($this->once())
|
||||
->method('isReadable')
|
||||
->will($this->returnValue(true));
|
||||
$a->addStream($s);
|
||||
$this->assertNull($a->getSize());
|
||||
}
|
||||
|
||||
public function testCatchesExceptionsWhenCastingToString()
|
||||
{
|
||||
$s = $this->getMockBuilder('Psr\Http\Message\StreamInterface')
|
||||
->setMethods(['isSeekable', 'read', 'isReadable', 'eof'])
|
||||
->getMockForAbstractClass();
|
||||
$s->expects($this->once())
|
||||
->method('isSeekable')
|
||||
->will($this->returnValue(true));
|
||||
$s->expects($this->once())
|
||||
->method('read')
|
||||
->will($this->throwException(new \RuntimeException('foo')));
|
||||
$s->expects($this->once())
|
||||
->method('isReadable')
|
||||
->will($this->returnValue(true));
|
||||
$s->expects($this->any())
|
||||
->method('eof')
|
||||
->will($this->returnValue(false));
|
||||
$a = new AppendStream([$s]);
|
||||
$this->assertFalse($a->eof());
|
||||
$this->assertSame('', (string) $a);
|
||||
}
|
||||
|
||||
public function testCanDetach()
|
||||
{
|
||||
$s = new AppendStream();
|
||||
$s->detach();
|
||||
}
|
||||
|
||||
public function testReturnsEmptyMetadata()
|
||||
{
|
||||
$s = new AppendStream();
|
||||
$this->assertEquals([], $s->getMetadata());
|
||||
$this->assertNull($s->getMetadata('foo'));
|
||||
}
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Tests\Psr7;
|
||||
|
||||
use GuzzleHttp\Psr7\BufferStream;
|
||||
|
||||
class BufferStreamTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testHasMetadata()
|
||||
{
|
||||
$b = new BufferStream(10);
|
||||
$this->assertTrue($b->isReadable());
|
||||
$this->assertTrue($b->isWritable());
|
||||
$this->assertFalse($b->isSeekable());
|
||||
$this->assertEquals(null, $b->getMetadata('foo'));
|
||||
$this->assertEquals(10, $b->getMetadata('hwm'));
|
||||
$this->assertEquals([], $b->getMetadata());
|
||||
}
|
||||
|
||||
public function testRemovesReadDataFromBuffer()
|
||||
{
|
||||
$b = new BufferStream();
|
||||
$this->assertEquals(3, $b->write('foo'));
|
||||
$this->assertEquals(3, $b->getSize());
|
||||
$this->assertFalse($b->eof());
|
||||
$this->assertEquals('foo', $b->read(10));
|
||||
$this->assertTrue($b->eof());
|
||||
$this->assertEquals('', $b->read(10));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \RuntimeException
|
||||
* @expectedExceptionMessage Cannot determine the position of a BufferStream
|
||||
*/
|
||||
public function testCanCastToStringOrGetContents()
|
||||
{
|
||||
$b = new BufferStream();
|
||||
$b->write('foo');
|
||||
$b->write('baz');
|
||||
$this->assertEquals('foo', $b->read(3));
|
||||
$b->write('bar');
|
||||
$this->assertEquals('bazbar', (string) $b);
|
||||
$b->tell();
|
||||
}
|
||||
|
||||
public function testDetachClearsBuffer()
|
||||
{
|
||||
$b = new BufferStream();
|
||||
$b->write('foo');
|
||||
$b->detach();
|
||||
$this->assertTrue($b->eof());
|
||||
$this->assertEquals(3, $b->write('abc'));
|
||||
$this->assertEquals('abc', $b->read(10));
|
||||
}
|
||||
|
||||
public function testExceedingHighwaterMarkReturnsFalseButStillBuffers()
|
||||
{
|
||||
$b = new BufferStream(5);
|
||||
$this->assertEquals(3, $b->write('hi '));
|
||||
$this->assertFalse($b->write('hello'));
|
||||
$this->assertEquals('hi hello', (string) $b);
|
||||
$this->assertEquals(4, $b->write('test'));
|
||||
}
|
||||
}
|
|
@ -1,193 +0,0 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Tests\Psr7;
|
||||
|
||||
use GuzzleHttp\Psr7;
|
||||
use GuzzleHttp\Psr7\CachingStream;
|
||||
|
||||
/**
|
||||
* @covers GuzzleHttp\Psr7\CachingStream
|
||||
*/
|
||||
class CachingStreamTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/** @var CachingStream */
|
||||
protected $body;
|
||||
protected $decorated;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
$this->decorated = Psr7\stream_for('testing');
|
||||
$this->body = new CachingStream($this->decorated);
|
||||
}
|
||||
|
||||
public function tearDown()
|
||||
{
|
||||
$this->decorated->close();
|
||||
$this->body->close();
|
||||
}
|
||||
|
||||
public function testUsesRemoteSizeIfPossible()
|
||||
{
|
||||
$body = Psr7\stream_for('test');
|
||||
$caching = new CachingStream($body);
|
||||
$this->assertEquals(4, $caching->getSize());
|
||||
}
|
||||
|
||||
public function testReadsUntilCachedToByte()
|
||||
{
|
||||
$this->body->seek(5);
|
||||
$this->assertEquals('n', $this->body->read(1));
|
||||
$this->body->seek(0);
|
||||
$this->assertEquals('t', $this->body->read(1));
|
||||
}
|
||||
|
||||
public function testCanSeekNearEndWithSeekEnd()
|
||||
{
|
||||
$baseStream = Psr7\stream_for(implode('', range('a', 'z')));
|
||||
$cached = new CachingStream($baseStream);
|
||||
$cached->seek(-1, SEEK_END);
|
||||
$this->assertEquals(25, $baseStream->tell());
|
||||
$this->assertEquals('z', $cached->read(1));
|
||||
$this->assertEquals(26, $cached->getSize());
|
||||
}
|
||||
|
||||
public function testCanSeekToEndWithSeekEnd()
|
||||
{
|
||||
$baseStream = Psr7\stream_for(implode('', range('a', 'z')));
|
||||
$cached = new CachingStream($baseStream);
|
||||
$cached->seek(0, SEEK_END);
|
||||
$this->assertEquals(26, $baseStream->tell());
|
||||
$this->assertEquals('', $cached->read(1));
|
||||
$this->assertEquals(26, $cached->getSize());
|
||||
}
|
||||
|
||||
public function testCanUseSeekEndWithUnknownSize()
|
||||
{
|
||||
$baseStream = Psr7\stream_for('testing');
|
||||
$decorated = Psr7\FnStream::decorate($baseStream, [
|
||||
'getSize' => function () { return null; }
|
||||
]);
|
||||
$cached = new CachingStream($decorated);
|
||||
$cached->seek(-1, SEEK_END);
|
||||
$this->assertEquals('g', $cached->read(1));
|
||||
}
|
||||
|
||||
public function testRewindUsesSeek()
|
||||
{
|
||||
$a = Psr7\stream_for('foo');
|
||||
$d = $this->getMockBuilder('GuzzleHttp\Psr7\CachingStream')
|
||||
->setMethods(array('seek'))
|
||||
->setConstructorArgs(array($a))
|
||||
->getMock();
|
||||
$d->expects($this->once())
|
||||
->method('seek')
|
||||
->with(0)
|
||||
->will($this->returnValue(true));
|
||||
$d->seek(0);
|
||||
}
|
||||
|
||||
public function testCanSeekToReadBytes()
|
||||
{
|
||||
$this->assertEquals('te', $this->body->read(2));
|
||||
$this->body->seek(0);
|
||||
$this->assertEquals('test', $this->body->read(4));
|
||||
$this->assertEquals(4, $this->body->tell());
|
||||
$this->body->seek(2);
|
||||
$this->assertEquals(2, $this->body->tell());
|
||||
$this->body->seek(2, SEEK_CUR);
|
||||
$this->assertEquals(4, $this->body->tell());
|
||||
$this->assertEquals('ing', $this->body->read(3));
|
||||
}
|
||||
|
||||
public function testCanSeekToReadBytesWithPartialBodyReturned()
|
||||
{
|
||||
$stream = fopen('php://temp', 'r+');
|
||||
fwrite($stream, 'testing');
|
||||
fseek($stream, 0);
|
||||
|
||||
$this->decorated = $this->getMockBuilder('\GuzzleHttp\Psr7\Stream')
|
||||
->setConstructorArgs([$stream])
|
||||
->setMethods(['read'])
|
||||
->getMock();
|
||||
|
||||
$this->decorated->expects($this->exactly(2))
|
||||
->method('read')
|
||||
->willReturnCallback(function($length) use ($stream){
|
||||
return fread($stream, 2);
|
||||
});
|
||||
|
||||
$this->body = new CachingStream($this->decorated);
|
||||
|
||||
$this->assertEquals(0, $this->body->tell());
|
||||
$this->body->seek(4, SEEK_SET);
|
||||
$this->assertEquals(4, $this->body->tell());
|
||||
|
||||
$this->body->seek(0);
|
||||
$this->assertEquals('test', $this->body->read(4));
|
||||
}
|
||||
|
||||
public function testWritesToBufferStream()
|
||||
{
|
||||
$this->body->read(2);
|
||||
$this->body->write('hi');
|
||||
$this->body->seek(0);
|
||||
$this->assertEquals('tehiing', (string) $this->body);
|
||||
}
|
||||
|
||||
public function testSkipsOverwrittenBytes()
|
||||
{
|
||||
$decorated = Psr7\stream_for(
|
||||
implode("\n", array_map(function ($n) {
|
||||
return str_pad($n, 4, '0', STR_PAD_LEFT);
|
||||
}, range(0, 25)))
|
||||
);
|
||||
|
||||
$body = new CachingStream($decorated);
|
||||
|
||||
$this->assertEquals("0000\n", Psr7\readline($body));
|
||||
$this->assertEquals("0001\n", Psr7\readline($body));
|
||||
// Write over part of the body yet to be read, so skip some bytes
|
||||
$this->assertEquals(5, $body->write("TEST\n"));
|
||||
$this->assertEquals(5, $this->readAttribute($body, 'skipReadBytes'));
|
||||
// Read, which skips bytes, then reads
|
||||
$this->assertEquals("0003\n", Psr7\readline($body));
|
||||
$this->assertEquals(0, $this->readAttribute($body, 'skipReadBytes'));
|
||||
$this->assertEquals("0004\n", Psr7\readline($body));
|
||||
$this->assertEquals("0005\n", Psr7\readline($body));
|
||||
|
||||
// Overwrite part of the cached body (so don't skip any bytes)
|
||||
$body->seek(5);
|
||||
$this->assertEquals(5, $body->write("ABCD\n"));
|
||||
$this->assertEquals(0, $this->readAttribute($body, 'skipReadBytes'));
|
||||
$this->assertEquals("TEST\n", Psr7\readline($body));
|
||||
$this->assertEquals("0003\n", Psr7\readline($body));
|
||||
$this->assertEquals("0004\n", Psr7\readline($body));
|
||||
$this->assertEquals("0005\n", Psr7\readline($body));
|
||||
$this->assertEquals("0006\n", Psr7\readline($body));
|
||||
$this->assertEquals(5, $body->write("1234\n"));
|
||||
$this->assertEquals(5, $this->readAttribute($body, 'skipReadBytes'));
|
||||
|
||||
// Seek to 0 and ensure the overwritten bit is replaced
|
||||
$body->seek(0);
|
||||
$this->assertEquals("0000\nABCD\nTEST\n0003\n0004\n0005\n0006\n1234\n0008\n0009\n", $body->read(50));
|
||||
|
||||
// Ensure that casting it to a string does not include the bit that was overwritten
|
||||
$this->assertContains("0000\nABCD\nTEST\n0003\n0004\n0005\n0006\n1234\n0008\n0009\n", (string) $body);
|
||||
}
|
||||
|
||||
public function testClosesBothStreams()
|
||||
{
|
||||
$s = fopen('php://temp', 'r');
|
||||
$a = Psr7\stream_for($s);
|
||||
$d = new CachingStream($a);
|
||||
$d->close();
|
||||
$this->assertFalse(is_resource($s));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \InvalidArgumentException
|
||||
*/
|
||||
public function testEnsuresValidWhence()
|
||||
{
|
||||
$this->body->seek(10, -123456);
|
||||
}
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Tests\Psr7;
|
||||
|
||||
use GuzzleHttp\Psr7\BufferStream;
|
||||
use GuzzleHttp\Psr7\DroppingStream;
|
||||
|
||||
class DroppingStreamTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testBeginsDroppingWhenSizeExceeded()
|
||||
{
|
||||
$stream = new BufferStream();
|
||||
$drop = new DroppingStream($stream, 5);
|
||||
$this->assertEquals(3, $drop->write('hel'));
|
||||
$this->assertEquals(2, $drop->write('lo'));
|
||||
$this->assertEquals(5, $drop->getSize());
|
||||
$this->assertEquals('hello', $drop->read(5));
|
||||
$this->assertEquals(0, $drop->getSize());
|
||||
$drop->write('12345678910');
|
||||
$this->assertEquals(5, $stream->getSize());
|
||||
$this->assertEquals(5, $drop->getSize());
|
||||
$this->assertEquals('12345', (string) $drop);
|
||||
$this->assertEquals(0, $drop->getSize());
|
||||
$drop->write('hello');
|
||||
$this->assertSame(0, $drop->write('test'));
|
||||
}
|
||||
}
|
|
@ -1,90 +0,0 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Tests\Psr7;
|
||||
|
||||
use GuzzleHttp\Psr7;
|
||||
use GuzzleHttp\Psr7\FnStream;
|
||||
|
||||
/**
|
||||
* @covers GuzzleHttp\Psr7\FnStream
|
||||
*/
|
||||
class FnStreamTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* @expectedException \BadMethodCallException
|
||||
* @expectedExceptionMessage seek() is not implemented in the FnStream
|
||||
*/
|
||||
public function testThrowsWhenNotImplemented()
|
||||
{
|
||||
(new FnStream([]))->seek(1);
|
||||
}
|
||||
|
||||
public function testProxiesToFunction()
|
||||
{
|
||||
$s = new FnStream([
|
||||
'read' => function ($len) {
|
||||
$this->assertEquals(3, $len);
|
||||
return 'foo';
|
||||
}
|
||||
]);
|
||||
|
||||
$this->assertEquals('foo', $s->read(3));
|
||||
}
|
||||
|
||||
public function testCanCloseOnDestruct()
|
||||
{
|
||||
$called = false;
|
||||
$s = new FnStream([
|
||||
'close' => function () use (&$called) {
|
||||
$called = true;
|
||||
}
|
||||
]);
|
||||
unset($s);
|
||||
$this->assertTrue($called);
|
||||
}
|
||||
|
||||
public function testDoesNotRequireClose()
|
||||
{
|
||||
$s = new FnStream([]);
|
||||
unset($s);
|
||||
}
|
||||
|
||||
public function testDecoratesStream()
|
||||
{
|
||||
$a = Psr7\stream_for('foo');
|
||||
$b = FnStream::decorate($a, []);
|
||||
$this->assertEquals(3, $b->getSize());
|
||||
$this->assertEquals($b->isWritable(), true);
|
||||
$this->assertEquals($b->isReadable(), true);
|
||||
$this->assertEquals($b->isSeekable(), true);
|
||||
$this->assertEquals($b->read(3), 'foo');
|
||||
$this->assertEquals($b->tell(), 3);
|
||||
$this->assertEquals($a->tell(), 3);
|
||||
$this->assertSame('', $a->read(1));
|
||||
$this->assertEquals($b->eof(), true);
|
||||
$this->assertEquals($a->eof(), true);
|
||||
$b->seek(0);
|
||||
$this->assertEquals('foo', (string) $b);
|
||||
$b->seek(0);
|
||||
$this->assertEquals('foo', $b->getContents());
|
||||
$this->assertEquals($a->getMetadata(), $b->getMetadata());
|
||||
$b->seek(0, SEEK_END);
|
||||
$b->write('bar');
|
||||
$this->assertEquals('foobar', (string) $b);
|
||||
$this->assertInternalType('resource', $b->detach());
|
||||
$b->close();
|
||||
}
|
||||
|
||||
public function testDecoratesWithCustomizations()
|
||||
{
|
||||
$called = false;
|
||||
$a = Psr7\stream_for('foo');
|
||||
$b = FnStream::decorate($a, [
|
||||
'read' => function ($len) use (&$called, $a) {
|
||||
$called = true;
|
||||
return $a->read($len);
|
||||
}
|
||||
]);
|
||||
$this->assertEquals('foo', $b->read(3));
|
||||
$this->assertTrue($called);
|
||||
}
|
||||
}
|
|
@ -1,619 +0,0 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Tests\Psr7;
|
||||
|
||||
use GuzzleHttp\Psr7;
|
||||
use GuzzleHttp\Psr7\FnStream;
|
||||
use GuzzleHttp\Psr7\NoSeekStream;
|
||||
|
||||
class FunctionsTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testCopiesToString()
|
||||
{
|
||||
$s = Psr7\stream_for('foobaz');
|
||||
$this->assertEquals('foobaz', Psr7\copy_to_string($s));
|
||||
$s->seek(0);
|
||||
$this->assertEquals('foo', Psr7\copy_to_string($s, 3));
|
||||
$this->assertEquals('baz', Psr7\copy_to_string($s, 3));
|
||||
$this->assertEquals('', Psr7\copy_to_string($s));
|
||||
}
|
||||
|
||||
public function testCopiesToStringStopsWhenReadFails()
|
||||
{
|
||||
$s1 = Psr7\stream_for('foobaz');
|
||||
$s1 = FnStream::decorate($s1, [
|
||||
'read' => function () { return ''; }
|
||||
]);
|
||||
$result = Psr7\copy_to_string($s1);
|
||||
$this->assertEquals('', $result);
|
||||
}
|
||||
|
||||
public function testCopiesToStream()
|
||||
{
|
||||
$s1 = Psr7\stream_for('foobaz');
|
||||
$s2 = Psr7\stream_for('');
|
||||
Psr7\copy_to_stream($s1, $s2);
|
||||
$this->assertEquals('foobaz', (string) $s2);
|
||||
$s2 = Psr7\stream_for('');
|
||||
$s1->seek(0);
|
||||
Psr7\copy_to_stream($s1, $s2, 3);
|
||||
$this->assertEquals('foo', (string) $s2);
|
||||
Psr7\copy_to_stream($s1, $s2, 3);
|
||||
$this->assertEquals('foobaz', (string) $s2);
|
||||
}
|
||||
|
||||
public function testStopsCopyToStreamWhenWriteFails()
|
||||
{
|
||||
$s1 = Psr7\stream_for('foobaz');
|
||||
$s2 = Psr7\stream_for('');
|
||||
$s2 = FnStream::decorate($s2, ['write' => function () { return 0; }]);
|
||||
Psr7\copy_to_stream($s1, $s2);
|
||||
$this->assertEquals('', (string) $s2);
|
||||
}
|
||||
|
||||
public function testStopsCopyToSteamWhenWriteFailsWithMaxLen()
|
||||
{
|
||||
$s1 = Psr7\stream_for('foobaz');
|
||||
$s2 = Psr7\stream_for('');
|
||||
$s2 = FnStream::decorate($s2, ['write' => function () { return 0; }]);
|
||||
Psr7\copy_to_stream($s1, $s2, 10);
|
||||
$this->assertEquals('', (string) $s2);
|
||||
}
|
||||
|
||||
public function testStopsCopyToSteamWhenReadFailsWithMaxLen()
|
||||
{
|
||||
$s1 = Psr7\stream_for('foobaz');
|
||||
$s1 = FnStream::decorate($s1, ['read' => function () { return ''; }]);
|
||||
$s2 = Psr7\stream_for('');
|
||||
Psr7\copy_to_stream($s1, $s2, 10);
|
||||
$this->assertEquals('', (string) $s2);
|
||||
}
|
||||
|
||||
public function testReadsLines()
|
||||
{
|
||||
$s = Psr7\stream_for("foo\nbaz\nbar");
|
||||
$this->assertEquals("foo\n", Psr7\readline($s));
|
||||
$this->assertEquals("baz\n", Psr7\readline($s));
|
||||
$this->assertEquals("bar", Psr7\readline($s));
|
||||
}
|
||||
|
||||
public function testReadsLinesUpToMaxLength()
|
||||
{
|
||||
$s = Psr7\stream_for("12345\n");
|
||||
$this->assertEquals("123", Psr7\readline($s, 4));
|
||||
$this->assertEquals("45\n", Psr7\readline($s));
|
||||
}
|
||||
|
||||
public function testReadsLineUntilFalseReturnedFromRead()
|
||||
{
|
||||
$s = $this->getMockBuilder('GuzzleHttp\Psr7\Stream')
|
||||
->setMethods(['read', 'eof'])
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$s->expects($this->exactly(2))
|
||||
->method('read')
|
||||
->will($this->returnCallback(function () {
|
||||
static $c = false;
|
||||
if ($c) {
|
||||
return false;
|
||||
}
|
||||
$c = true;
|
||||
return 'h';
|
||||
}));
|
||||
$s->expects($this->exactly(2))
|
||||
->method('eof')
|
||||
->will($this->returnValue(false));
|
||||
$this->assertEquals("h", Psr7\readline($s));
|
||||
}
|
||||
|
||||
public function testCalculatesHash()
|
||||
{
|
||||
$s = Psr7\stream_for('foobazbar');
|
||||
$this->assertEquals(md5('foobazbar'), Psr7\hash($s, 'md5'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \RuntimeException
|
||||
*/
|
||||
public function testCalculatesHashThrowsWhenSeekFails()
|
||||
{
|
||||
$s = new NoSeekStream(Psr7\stream_for('foobazbar'));
|
||||
$s->read(2);
|
||||
Psr7\hash($s, 'md5');
|
||||
}
|
||||
|
||||
public function testCalculatesHashSeeksToOriginalPosition()
|
||||
{
|
||||
$s = Psr7\stream_for('foobazbar');
|
||||
$s->seek(4);
|
||||
$this->assertEquals(md5('foobazbar'), Psr7\hash($s, 'md5'));
|
||||
$this->assertEquals(4, $s->tell());
|
||||
}
|
||||
|
||||
public function testOpensFilesSuccessfully()
|
||||
{
|
||||
$r = Psr7\try_fopen(__FILE__, 'r');
|
||||
$this->assertInternalType('resource', $r);
|
||||
fclose($r);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \RuntimeException
|
||||
* @expectedExceptionMessage Unable to open /path/to/does/not/exist using mode r
|
||||
*/
|
||||
public function testThrowsExceptionNotWarning()
|
||||
{
|
||||
Psr7\try_fopen('/path/to/does/not/exist', 'r');
|
||||
}
|
||||
|
||||
public function parseQueryProvider()
|
||||
{
|
||||
return [
|
||||
// Does not need to parse when the string is empty
|
||||
['', []],
|
||||
// Can parse mult-values items
|
||||
['q=a&q=b', ['q' => ['a', 'b']]],
|
||||
// Can parse multi-valued items that use numeric indices
|
||||
['q[0]=a&q[1]=b', ['q[0]' => 'a', 'q[1]' => 'b']],
|
||||
// Can parse duplicates and does not include numeric indices
|
||||
['q[]=a&q[]=b', ['q[]' => ['a', 'b']]],
|
||||
// Ensures that the value of "q" is an array even though one value
|
||||
['q[]=a', ['q[]' => 'a']],
|
||||
// Does not modify "." to "_" like PHP's parse_str()
|
||||
['q.a=a&q.b=b', ['q.a' => 'a', 'q.b' => 'b']],
|
||||
// Can decode %20 to " "
|
||||
['q%20a=a%20b', ['q a' => 'a b']],
|
||||
// Can parse funky strings with no values by assigning each to null
|
||||
['q&a', ['q' => null, 'a' => null]],
|
||||
// Does not strip trailing equal signs
|
||||
['data=abc=', ['data' => 'abc=']],
|
||||
// Can store duplicates without affecting other values
|
||||
['foo=a&foo=b&?µ=c', ['foo' => ['a', 'b'], '?µ' => 'c']],
|
||||
// Sets value to null when no "=" is present
|
||||
['foo', ['foo' => null]],
|
||||
// Preserves "0" keys.
|
||||
['0', ['0' => null]],
|
||||
// Sets the value to an empty string when "=" is present
|
||||
['0=', ['0' => '']],
|
||||
// Preserves falsey keys
|
||||
['var=0', ['var' => '0']],
|
||||
['a[b][c]=1&a[b][c]=2', ['a[b][c]' => ['1', '2']]],
|
||||
['a[b]=c&a[d]=e', ['a[b]' => 'c', 'a[d]' => 'e']],
|
||||
// Ensure it doesn't leave things behind with repeated values
|
||||
// Can parse mult-values items
|
||||
['q=a&q=b&q=c', ['q' => ['a', 'b', 'c']]],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider parseQueryProvider
|
||||
*/
|
||||
public function testParsesQueries($input, $output)
|
||||
{
|
||||
$result = Psr7\parse_query($input);
|
||||
$this->assertSame($output, $result);
|
||||
}
|
||||
|
||||
public function testDoesNotDecode()
|
||||
{
|
||||
$str = 'foo%20=bar';
|
||||
$data = Psr7\parse_query($str, false);
|
||||
$this->assertEquals(['foo%20' => 'bar'], $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider parseQueryProvider
|
||||
*/
|
||||
public function testParsesAndBuildsQueries($input, $output)
|
||||
{
|
||||
$result = Psr7\parse_query($input, false);
|
||||
$this->assertSame($input, Psr7\build_query($result, false));
|
||||
}
|
||||
|
||||
public function testEncodesWithRfc1738()
|
||||
{
|
||||
$str = Psr7\build_query(['foo bar' => 'baz+'], PHP_QUERY_RFC1738);
|
||||
$this->assertEquals('foo+bar=baz%2B', $str);
|
||||
}
|
||||
|
||||
public function testEncodesWithRfc3986()
|
||||
{
|
||||
$str = Psr7\build_query(['foo bar' => 'baz+'], PHP_QUERY_RFC3986);
|
||||
$this->assertEquals('foo%20bar=baz%2B', $str);
|
||||
}
|
||||
|
||||
public function testDoesNotEncode()
|
||||
{
|
||||
$str = Psr7\build_query(['foo bar' => 'baz+'], false);
|
||||
$this->assertEquals('foo bar=baz+', $str);
|
||||
}
|
||||
|
||||
public function testCanControlDecodingType()
|
||||
{
|
||||
$result = Psr7\parse_query('var=foo+bar', PHP_QUERY_RFC3986);
|
||||
$this->assertEquals('foo+bar', $result['var']);
|
||||
$result = Psr7\parse_query('var=foo+bar', PHP_QUERY_RFC1738);
|
||||
$this->assertEquals('foo bar', $result['var']);
|
||||
}
|
||||
|
||||
public function testParsesRequestMessages()
|
||||
{
|
||||
$req = "GET /abc HTTP/1.0\r\nHost: foo.com\r\nFoo: Bar\r\nBaz: Bam\r\nBaz: Qux\r\n\r\nTest";
|
||||
$request = Psr7\parse_request($req);
|
||||
$this->assertEquals('GET', $request->getMethod());
|
||||
$this->assertEquals('/abc', $request->getRequestTarget());
|
||||
$this->assertEquals('1.0', $request->getProtocolVersion());
|
||||
$this->assertEquals('foo.com', $request->getHeaderLine('Host'));
|
||||
$this->assertEquals('Bar', $request->getHeaderLine('Foo'));
|
||||
$this->assertEquals('Bam, Qux', $request->getHeaderLine('Baz'));
|
||||
$this->assertEquals('Test', (string) $request->getBody());
|
||||
$this->assertEquals('http://foo.com/abc', (string) $request->getUri());
|
||||
}
|
||||
|
||||
public function testParsesRequestMessagesWithHttpsScheme()
|
||||
{
|
||||
$req = "PUT /abc?baz=bar HTTP/1.1\r\nHost: foo.com:443\r\n\r\n";
|
||||
$request = Psr7\parse_request($req);
|
||||
$this->assertEquals('PUT', $request->getMethod());
|
||||
$this->assertEquals('/abc?baz=bar', $request->getRequestTarget());
|
||||
$this->assertEquals('1.1', $request->getProtocolVersion());
|
||||
$this->assertEquals('foo.com:443', $request->getHeaderLine('Host'));
|
||||
$this->assertEquals('', (string) $request->getBody());
|
||||
$this->assertEquals('https://foo.com/abc?baz=bar', (string) $request->getUri());
|
||||
}
|
||||
|
||||
public function testParsesRequestMessagesWithUriWhenHostIsNotFirst()
|
||||
{
|
||||
$req = "PUT / HTTP/1.1\r\nFoo: Bar\r\nHost: foo.com\r\n\r\n";
|
||||
$request = Psr7\parse_request($req);
|
||||
$this->assertEquals('PUT', $request->getMethod());
|
||||
$this->assertEquals('/', $request->getRequestTarget());
|
||||
$this->assertEquals('http://foo.com/', (string) $request->getUri());
|
||||
}
|
||||
|
||||
public function testParsesRequestMessagesWithFullUri()
|
||||
{
|
||||
$req = "GET https://www.google.com:443/search?q=foobar HTTP/1.1\r\nHost: www.google.com\r\n\r\n";
|
||||
$request = Psr7\parse_request($req);
|
||||
$this->assertEquals('GET', $request->getMethod());
|
||||
$this->assertEquals('https://www.google.com:443/search?q=foobar', $request->getRequestTarget());
|
||||
$this->assertEquals('1.1', $request->getProtocolVersion());
|
||||
$this->assertEquals('www.google.com', $request->getHeaderLine('Host'));
|
||||
$this->assertEquals('', (string) $request->getBody());
|
||||
$this->assertEquals('https://www.google.com/search?q=foobar', (string) $request->getUri());
|
||||
}
|
||||
|
||||
public function testParsesRequestMessagesWithCustomMethod()
|
||||
{
|
||||
$req = "GET_DATA / HTTP/1.1\r\nFoo: Bar\r\nHost: foo.com\r\n\r\n";
|
||||
$request = Psr7\parse_request($req);
|
||||
$this->assertEquals('GET_DATA', $request->getMethod());
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \InvalidArgumentException
|
||||
*/
|
||||
public function testValidatesRequestMessages()
|
||||
{
|
||||
Psr7\parse_request("HTTP/1.1 200 OK\r\n\r\n");
|
||||
}
|
||||
|
||||
public function testParsesResponseMessages()
|
||||
{
|
||||
$res = "HTTP/1.0 200 OK\r\nFoo: Bar\r\nBaz: Bam\r\nBaz: Qux\r\n\r\nTest";
|
||||
$response = Psr7\parse_response($res);
|
||||
$this->assertEquals(200, $response->getStatusCode());
|
||||
$this->assertEquals('OK', $response->getReasonPhrase());
|
||||
$this->assertEquals('1.0', $response->getProtocolVersion());
|
||||
$this->assertEquals('Bar', $response->getHeaderLine('Foo'));
|
||||
$this->assertEquals('Bam, Qux', $response->getHeaderLine('Baz'));
|
||||
$this->assertEquals('Test', (string) $response->getBody());
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \InvalidArgumentException
|
||||
*/
|
||||
public function testValidatesResponseMessages()
|
||||
{
|
||||
Psr7\parse_response("GET / HTTP/1.1\r\n\r\n");
|
||||
}
|
||||
|
||||
public function testDetermineMimetype()
|
||||
{
|
||||
$this->assertNull(Psr7\mimetype_from_extension('not-a-real-extension'));
|
||||
$this->assertEquals(
|
||||
'application/json',
|
||||
Psr7\mimetype_from_extension('json')
|
||||
);
|
||||
$this->assertEquals(
|
||||
'image/jpeg',
|
||||
Psr7\mimetype_from_filename('/tmp/images/IMG034821.JPEG')
|
||||
);
|
||||
}
|
||||
|
||||
public function testCreatesUriForValue()
|
||||
{
|
||||
$this->assertInstanceOf('GuzzleHttp\Psr7\Uri', Psr7\uri_for('/foo'));
|
||||
$this->assertInstanceOf(
|
||||
'GuzzleHttp\Psr7\Uri',
|
||||
Psr7\uri_for(new Psr7\Uri('/foo'))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \InvalidArgumentException
|
||||
*/
|
||||
public function testValidatesUri()
|
||||
{
|
||||
Psr7\uri_for([]);
|
||||
}
|
||||
|
||||
public function testKeepsPositionOfResource()
|
||||
{
|
||||
$h = fopen(__FILE__, 'r');
|
||||
fseek($h, 10);
|
||||
$stream = Psr7\stream_for($h);
|
||||
$this->assertEquals(10, $stream->tell());
|
||||
$stream->close();
|
||||
}
|
||||
|
||||
public function testCreatesWithFactory()
|
||||
{
|
||||
$stream = Psr7\stream_for('foo');
|
||||
$this->assertInstanceOf('GuzzleHttp\Psr7\Stream', $stream);
|
||||
$this->assertEquals('foo', $stream->getContents());
|
||||
$stream->close();
|
||||
}
|
||||
|
||||
public function testFactoryCreatesFromEmptyString()
|
||||
{
|
||||
$s = Psr7\stream_for();
|
||||
$this->assertInstanceOf('GuzzleHttp\Psr7\Stream', $s);
|
||||
}
|
||||
|
||||
public function testFactoryCreatesFromNull()
|
||||
{
|
||||
$s = Psr7\stream_for(null);
|
||||
$this->assertInstanceOf('GuzzleHttp\Psr7\Stream', $s);
|
||||
}
|
||||
|
||||
public function testFactoryCreatesFromResource()
|
||||
{
|
||||
$r = fopen(__FILE__, 'r');
|
||||
$s = Psr7\stream_for($r);
|
||||
$this->assertInstanceOf('GuzzleHttp\Psr7\Stream', $s);
|
||||
$this->assertSame(file_get_contents(__FILE__), (string) $s);
|
||||
}
|
||||
|
||||
public function testFactoryCreatesFromObjectWithToString()
|
||||
{
|
||||
$r = new HasToString();
|
||||
$s = Psr7\stream_for($r);
|
||||
$this->assertInstanceOf('GuzzleHttp\Psr7\Stream', $s);
|
||||
$this->assertEquals('foo', (string) $s);
|
||||
}
|
||||
|
||||
public function testCreatePassesThrough()
|
||||
{
|
||||
$s = Psr7\stream_for('foo');
|
||||
$this->assertSame($s, Psr7\stream_for($s));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \InvalidArgumentException
|
||||
*/
|
||||
public function testThrowsExceptionForUnknown()
|
||||
{
|
||||
Psr7\stream_for(new \stdClass());
|
||||
}
|
||||
|
||||
public function testReturnsCustomMetadata()
|
||||
{
|
||||
$s = Psr7\stream_for('foo', ['metadata' => ['hwm' => 3]]);
|
||||
$this->assertEquals(3, $s->getMetadata('hwm'));
|
||||
$this->assertArrayHasKey('hwm', $s->getMetadata());
|
||||
}
|
||||
|
||||
public function testCanSetSize()
|
||||
{
|
||||
$s = Psr7\stream_for('', ['size' => 10]);
|
||||
$this->assertEquals(10, $s->getSize());
|
||||
}
|
||||
|
||||
public function testCanCreateIteratorBasedStream()
|
||||
{
|
||||
$a = new \ArrayIterator(['foo', 'bar', '123']);
|
||||
$p = Psr7\stream_for($a);
|
||||
$this->assertInstanceOf('GuzzleHttp\Psr7\PumpStream', $p);
|
||||
$this->assertEquals('foo', $p->read(3));
|
||||
$this->assertFalse($p->eof());
|
||||
$this->assertEquals('b', $p->read(1));
|
||||
$this->assertEquals('a', $p->read(1));
|
||||
$this->assertEquals('r12', $p->read(3));
|
||||
$this->assertFalse($p->eof());
|
||||
$this->assertEquals('3', $p->getContents());
|
||||
$this->assertTrue($p->eof());
|
||||
$this->assertEquals(9, $p->tell());
|
||||
}
|
||||
|
||||
public function testConvertsRequestsToStrings()
|
||||
{
|
||||
$request = new Psr7\Request('PUT', 'http://foo.com/hi?123', [
|
||||
'Baz' => 'bar',
|
||||
'Qux' => 'ipsum'
|
||||
], 'hello', '1.0');
|
||||
$this->assertEquals(
|
||||
"PUT /hi?123 HTTP/1.0\r\nHost: foo.com\r\nBaz: bar\r\nQux: ipsum\r\n\r\nhello",
|
||||
Psr7\str($request)
|
||||
);
|
||||
}
|
||||
|
||||
public function testConvertsResponsesToStrings()
|
||||
{
|
||||
$response = new Psr7\Response(200, [
|
||||
'Baz' => 'bar',
|
||||
'Qux' => 'ipsum'
|
||||
], 'hello', '1.0', 'FOO');
|
||||
$this->assertEquals(
|
||||
"HTTP/1.0 200 FOO\r\nBaz: bar\r\nQux: ipsum\r\n\r\nhello",
|
||||
Psr7\str($response)
|
||||
);
|
||||
}
|
||||
|
||||
public function parseParamsProvider()
|
||||
{
|
||||
$res1 = array(
|
||||
array(
|
||||
'<http:/.../front.jpeg>',
|
||||
'rel' => 'front',
|
||||
'type' => 'image/jpeg',
|
||||
),
|
||||
array(
|
||||
'<http://.../back.jpeg>',
|
||||
'rel' => 'back',
|
||||
'type' => 'image/jpeg',
|
||||
),
|
||||
);
|
||||
return array(
|
||||
array(
|
||||
'<http:/.../front.jpeg>; rel="front"; type="image/jpeg", <http://.../back.jpeg>; rel=back; type="image/jpeg"',
|
||||
$res1
|
||||
),
|
||||
array(
|
||||
'<http:/.../front.jpeg>; rel="front"; type="image/jpeg",<http://.../back.jpeg>; rel=back; type="image/jpeg"',
|
||||
$res1
|
||||
),
|
||||
array(
|
||||
'foo="baz"; bar=123, boo, test="123", foobar="foo;bar"',
|
||||
array(
|
||||
array('foo' => 'baz', 'bar' => '123'),
|
||||
array('boo'),
|
||||
array('test' => '123'),
|
||||
array('foobar' => 'foo;bar')
|
||||
)
|
||||
),
|
||||
array(
|
||||
'<http://.../side.jpeg?test=1>; rel="side"; type="image/jpeg",<http://.../side.jpeg?test=2>; rel=side; type="image/jpeg"',
|
||||
array(
|
||||
array('<http://.../side.jpeg?test=1>', 'rel' => 'side', 'type' => 'image/jpeg'),
|
||||
array('<http://.../side.jpeg?test=2>', 'rel' => 'side', 'type' => 'image/jpeg')
|
||||
)
|
||||
),
|
||||
array(
|
||||
'',
|
||||
array()
|
||||
)
|
||||
);
|
||||
}
|
||||
/**
|
||||
* @dataProvider parseParamsProvider
|
||||
*/
|
||||
public function testParseParams($header, $result)
|
||||
{
|
||||
$this->assertEquals($result, Psr7\parse_header($header));
|
||||
}
|
||||
|
||||
public function testParsesArrayHeaders()
|
||||
{
|
||||
$header = ['a, b', 'c', 'd, e'];
|
||||
$this->assertEquals(['a', 'b', 'c', 'd', 'e'], Psr7\normalize_header($header));
|
||||
}
|
||||
|
||||
public function testRewindsBody()
|
||||
{
|
||||
$body = Psr7\stream_for('abc');
|
||||
$res = new Psr7\Response(200, [], $body);
|
||||
Psr7\rewind_body($res);
|
||||
$this->assertEquals(0, $body->tell());
|
||||
$body->rewind(1);
|
||||
Psr7\rewind_body($res);
|
||||
$this->assertEquals(0, $body->tell());
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \RuntimeException
|
||||
*/
|
||||
public function testThrowsWhenBodyCannotBeRewound()
|
||||
{
|
||||
$body = Psr7\stream_for('abc');
|
||||
$body->read(1);
|
||||
$body = FnStream::decorate($body, [
|
||||
'rewind' => function () { throw new \RuntimeException('a'); }
|
||||
]);
|
||||
$res = new Psr7\Response(200, [], $body);
|
||||
Psr7\rewind_body($res);
|
||||
}
|
||||
|
||||
public function testCanModifyRequestWithUri()
|
||||
{
|
||||
$r1 = new Psr7\Request('GET', 'http://foo.com');
|
||||
$r2 = Psr7\modify_request($r1, [
|
||||
'uri' => new Psr7\Uri('http://www.foo.com')
|
||||
]);
|
||||
$this->assertEquals('http://www.foo.com', (string) $r2->getUri());
|
||||
$this->assertEquals('www.foo.com', (string) $r2->getHeaderLine('host'));
|
||||
}
|
||||
|
||||
public function testCanModifyRequestWithUriAndPort()
|
||||
{
|
||||
$r1 = new Psr7\Request('GET', 'http://foo.com:8000');
|
||||
$r2 = Psr7\modify_request($r1, [
|
||||
'uri' => new Psr7\Uri('http://www.foo.com:8000')
|
||||
]);
|
||||
$this->assertEquals('http://www.foo.com:8000', (string) $r2->getUri());
|
||||
$this->assertEquals('www.foo.com:8000', (string) $r2->getHeaderLine('host'));
|
||||
}
|
||||
|
||||
public function testCanModifyRequestWithCaseInsensitiveHeader()
|
||||
{
|
||||
$r1 = new Psr7\Request('GET', 'http://foo.com', ['User-Agent' => 'foo']);
|
||||
$r2 = Psr7\modify_request($r1, ['set_headers' => ['User-agent' => 'bar']]);
|
||||
$this->assertEquals('bar', $r2->getHeaderLine('User-Agent'));
|
||||
$this->assertEquals('bar', $r2->getHeaderLine('User-agent'));
|
||||
}
|
||||
|
||||
public function testReturnsAsIsWhenNoChanges()
|
||||
{
|
||||
$r1 = new Psr7\Request('GET', 'http://foo.com');
|
||||
$r2 = Psr7\modify_request($r1, []);
|
||||
$this->assertTrue($r2 instanceof Psr7\Request);
|
||||
|
||||
$r1 = new Psr7\ServerRequest('GET', 'http://foo.com');
|
||||
$r2 = Psr7\modify_request($r1, []);
|
||||
$this->assertTrue($r2 instanceof \Psr\Http\Message\ServerRequestInterface);
|
||||
}
|
||||
|
||||
public function testReturnsUriAsIsWhenNoChanges()
|
||||
{
|
||||
$r1 = new Psr7\Request('GET', 'http://foo.com');
|
||||
$r2 = Psr7\modify_request($r1, ['set_headers' => ['foo' => 'bar']]);
|
||||
$this->assertNotSame($r1, $r2);
|
||||
$this->assertEquals('bar', $r2->getHeaderLine('foo'));
|
||||
}
|
||||
|
||||
public function testRemovesHeadersFromMessage()
|
||||
{
|
||||
$r1 = new Psr7\Request('GET', 'http://foo.com', ['foo' => 'bar']);
|
||||
$r2 = Psr7\modify_request($r1, ['remove_headers' => ['foo']]);
|
||||
$this->assertNotSame($r1, $r2);
|
||||
$this->assertFalse($r2->hasHeader('foo'));
|
||||
}
|
||||
|
||||
public function testAddsQueryToUri()
|
||||
{
|
||||
$r1 = new Psr7\Request('GET', 'http://foo.com');
|
||||
$r2 = Psr7\modify_request($r1, ['query' => 'foo=bar']);
|
||||
$this->assertNotSame($r1, $r2);
|
||||
$this->assertEquals('foo=bar', $r2->getUri()->getQuery());
|
||||
}
|
||||
|
||||
public function testModifyRequestKeepInstanceOfRequest()
|
||||
{
|
||||
$r1 = new Psr7\Request('GET', 'http://foo.com');
|
||||
$r2 = Psr7\modify_request($r1, ['remove_headers' => ['non-existent']]);
|
||||
$this->assertTrue($r2 instanceof Psr7\Request);
|
||||
|
||||
$r1 = new Psr7\ServerRequest('GET', 'http://foo.com');
|
||||
$r2 = Psr7\modify_request($r1, ['remove_headers' => ['non-existent']]);
|
||||
$this->assertTrue($r2 instanceof \Psr\Http\Message\ServerRequestInterface);
|
||||
}
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Tests\Psr7;
|
||||
|
||||
use GuzzleHttp\Psr7;
|
||||
use GuzzleHttp\Psr7\InflateStream;
|
||||
|
||||
class InflateStreamtest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testInflatesStreams()
|
||||
{
|
||||
$content = gzencode('test');
|
||||
$a = Psr7\stream_for($content);
|
||||
$b = new InflateStream($a);
|
||||
$this->assertEquals('test', (string) $b);
|
||||
}
|
||||
|
||||
public function testInflatesStreamsWithFilename()
|
||||
{
|
||||
$content = $this->getGzipStringWithFilename('test');
|
||||
$a = Psr7\stream_for($content);
|
||||
$b = new InflateStream($a);
|
||||
$this->assertEquals('test', (string) $b);
|
||||
}
|
||||
|
||||
private function getGzipStringWithFilename($original_string)
|
||||
{
|
||||
$gzipped = bin2hex(gzencode($original_string));
|
||||
|
||||
$header = substr($gzipped, 0, 20);
|
||||
// set FNAME flag
|
||||
$header[6]=0;
|
||||
$header[7]=8;
|
||||
// make a dummy filename
|
||||
$filename = "64756d6d7900";
|
||||
$rest = substr($gzipped, 20);
|
||||
|
||||
return hex2bin($header . $filename . $rest);
|
||||
}
|
||||
}
|
|
@ -1,64 +0,0 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Tests\Psr7;
|
||||
|
||||
use GuzzleHttp\Psr7\LazyOpenStream;
|
||||
|
||||
class LazyOpenStreamTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
private $fname;
|
||||
|
||||
public function setup()
|
||||
{
|
||||
$this->fname = tempnam('/tmp', 'tfile');
|
||||
|
||||
if (file_exists($this->fname)) {
|
||||
unlink($this->fname);
|
||||
}
|
||||
}
|
||||
|
||||
public function tearDown()
|
||||
{
|
||||
if (file_exists($this->fname)) {
|
||||
unlink($this->fname);
|
||||
}
|
||||
}
|
||||
|
||||
public function testOpensLazily()
|
||||
{
|
||||
$l = new LazyOpenStream($this->fname, 'w+');
|
||||
$l->write('foo');
|
||||
$this->assertInternalType('array', $l->getMetadata());
|
||||
$this->assertFileExists($this->fname);
|
||||
$this->assertEquals('foo', file_get_contents($this->fname));
|
||||
$this->assertEquals('foo', (string) $l);
|
||||
}
|
||||
|
||||
public function testProxiesToFile()
|
||||
{
|
||||
file_put_contents($this->fname, 'foo');
|
||||
$l = new LazyOpenStream($this->fname, 'r');
|
||||
$this->assertEquals('foo', $l->read(4));
|
||||
$this->assertTrue($l->eof());
|
||||
$this->assertEquals(3, $l->tell());
|
||||
$this->assertTrue($l->isReadable());
|
||||
$this->assertTrue($l->isSeekable());
|
||||
$this->assertFalse($l->isWritable());
|
||||
$l->seek(1);
|
||||
$this->assertEquals('oo', $l->getContents());
|
||||
$this->assertEquals('foo', (string) $l);
|
||||
$this->assertEquals(3, $l->getSize());
|
||||
$this->assertInternalType('array', $l->getMetadata());
|
||||
$l->close();
|
||||
}
|
||||
|
||||
public function testDetachesUnderlyingStream()
|
||||
{
|
||||
file_put_contents($this->fname, 'foo');
|
||||
$l = new LazyOpenStream($this->fname, 'r');
|
||||
$r = $l->detach();
|
||||
$this->assertInternalType('resource', $r);
|
||||
fseek($r, 0);
|
||||
$this->assertEquals('foo', stream_get_contents($r));
|
||||
fclose($r);
|
||||
}
|
||||
}
|
|
@ -1,166 +0,0 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Tests\Psr7;
|
||||
|
||||
use GuzzleHttp\Psr7;
|
||||
use GuzzleHttp\Psr7\FnStream;
|
||||
use GuzzleHttp\Psr7\Stream;
|
||||
use GuzzleHttp\Psr7\LimitStream;
|
||||
use GuzzleHttp\Psr7\NoSeekStream;
|
||||
|
||||
/**
|
||||
* @covers GuzzleHttp\Psr7\LimitStream
|
||||
*/
|
||||
class LimitStreamTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/** @var LimitStream */
|
||||
protected $body;
|
||||
|
||||
/** @var Stream */
|
||||
protected $decorated;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
$this->decorated = Psr7\stream_for(fopen(__FILE__, 'r'));
|
||||
$this->body = new LimitStream($this->decorated, 10, 3);
|
||||
}
|
||||
|
||||
public function testReturnsSubset()
|
||||
{
|
||||
$body = new LimitStream(Psr7\stream_for('foo'), -1, 1);
|
||||
$this->assertEquals('oo', (string) $body);
|
||||
$this->assertTrue($body->eof());
|
||||
$body->seek(0);
|
||||
$this->assertFalse($body->eof());
|
||||
$this->assertEquals('oo', $body->read(100));
|
||||
$this->assertSame('', $body->read(1));
|
||||
$this->assertTrue($body->eof());
|
||||
}
|
||||
|
||||
public function testReturnsSubsetWhenCastToString()
|
||||
{
|
||||
$body = Psr7\stream_for('foo_baz_bar');
|
||||
$limited = new LimitStream($body, 3, 4);
|
||||
$this->assertEquals('baz', (string) $limited);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \RuntimeException
|
||||
* @expectedExceptionMessage Unable to seek to stream position 10 with whence 0
|
||||
*/
|
||||
public function testEnsuresPositionCanBeekSeekedTo()
|
||||
{
|
||||
new LimitStream(Psr7\stream_for(''), 0, 10);
|
||||
}
|
||||
|
||||
public function testReturnsSubsetOfEmptyBodyWhenCastToString()
|
||||
{
|
||||
$body = Psr7\stream_for('01234567891234');
|
||||
$limited = new LimitStream($body, 0, 10);
|
||||
$this->assertEquals('', (string) $limited);
|
||||
}
|
||||
|
||||
public function testReturnsSpecificSubsetOBodyWhenCastToString()
|
||||
{
|
||||
$body = Psr7\stream_for('0123456789abcdef');
|
||||
$limited = new LimitStream($body, 3, 10);
|
||||
$this->assertEquals('abc', (string) $limited);
|
||||
}
|
||||
|
||||
public function testSeeksWhenConstructed()
|
||||
{
|
||||
$this->assertEquals(0, $this->body->tell());
|
||||
$this->assertEquals(3, $this->decorated->tell());
|
||||
}
|
||||
|
||||
public function testAllowsBoundedSeek()
|
||||
{
|
||||
$this->body->seek(100);
|
||||
$this->assertEquals(10, $this->body->tell());
|
||||
$this->assertEquals(13, $this->decorated->tell());
|
||||
$this->body->seek(0);
|
||||
$this->assertEquals(0, $this->body->tell());
|
||||
$this->assertEquals(3, $this->decorated->tell());
|
||||
try {
|
||||
$this->body->seek(-10);
|
||||
$this->fail();
|
||||
} catch (\RuntimeException $e) {}
|
||||
$this->assertEquals(0, $this->body->tell());
|
||||
$this->assertEquals(3, $this->decorated->tell());
|
||||
$this->body->seek(5);
|
||||
$this->assertEquals(5, $this->body->tell());
|
||||
$this->assertEquals(8, $this->decorated->tell());
|
||||
// Fail
|
||||
try {
|
||||
$this->body->seek(1000, SEEK_END);
|
||||
$this->fail();
|
||||
} catch (\RuntimeException $e) {}
|
||||
}
|
||||
|
||||
public function testReadsOnlySubsetOfData()
|
||||
{
|
||||
$data = $this->body->read(100);
|
||||
$this->assertEquals(10, strlen($data));
|
||||
$this->assertSame('', $this->body->read(1000));
|
||||
|
||||
$this->body->setOffset(10);
|
||||
$newData = $this->body->read(100);
|
||||
$this->assertEquals(10, strlen($newData));
|
||||
$this->assertNotSame($data, $newData);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \RuntimeException
|
||||
* @expectedExceptionMessage Could not seek to stream offset 2
|
||||
*/
|
||||
public function testThrowsWhenCurrentGreaterThanOffsetSeek()
|
||||
{
|
||||
$a = Psr7\stream_for('foo_bar');
|
||||
$b = new NoSeekStream($a);
|
||||
$c = new LimitStream($b);
|
||||
$a->getContents();
|
||||
$c->setOffset(2);
|
||||
}
|
||||
|
||||
public function testCanGetContentsWithoutSeeking()
|
||||
{
|
||||
$a = Psr7\stream_for('foo_bar');
|
||||
$b = new NoSeekStream($a);
|
||||
$c = new LimitStream($b);
|
||||
$this->assertEquals('foo_bar', $c->getContents());
|
||||
}
|
||||
|
||||
public function testClaimsConsumedWhenReadLimitIsReached()
|
||||
{
|
||||
$this->assertFalse($this->body->eof());
|
||||
$this->body->read(1000);
|
||||
$this->assertTrue($this->body->eof());
|
||||
}
|
||||
|
||||
public function testContentLengthIsBounded()
|
||||
{
|
||||
$this->assertEquals(10, $this->body->getSize());
|
||||
}
|
||||
|
||||
public function testGetContentsIsBasedOnSubset()
|
||||
{
|
||||
$body = new LimitStream(Psr7\stream_for('foobazbar'), 3, 3);
|
||||
$this->assertEquals('baz', $body->getContents());
|
||||
}
|
||||
|
||||
public function testReturnsNullIfSizeCannotBeDetermined()
|
||||
{
|
||||
$a = new FnStream([
|
||||
'getSize' => function () { return null; },
|
||||
'tell' => function () { return 0; },
|
||||
]);
|
||||
$b = new LimitStream($a);
|
||||
$this->assertNull($b->getSize());
|
||||
}
|
||||
|
||||
public function testLengthLessOffsetWhenNoLimitSize()
|
||||
{
|
||||
$a = Psr7\stream_for('foo_bar');
|
||||
$b = new LimitStream($a, -1, 4);
|
||||
$this->assertEquals(3, $b->getSize());
|
||||
}
|
||||
}
|
|
@ -1,242 +0,0 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Tests;
|
||||
|
||||
use GuzzleHttp\Psr7;
|
||||
use GuzzleHttp\Psr7\MultipartStream;
|
||||
|
||||
class MultipartStreamTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testCreatesDefaultBoundary()
|
||||
{
|
||||
$b = new MultipartStream();
|
||||
$this->assertNotEmpty($b->getBoundary());
|
||||
}
|
||||
|
||||
public function testCanProvideBoundary()
|
||||
{
|
||||
$b = new MultipartStream([], 'foo');
|
||||
$this->assertEquals('foo', $b->getBoundary());
|
||||
}
|
||||
|
||||
public function testIsNotWritable()
|
||||
{
|
||||
$b = new MultipartStream();
|
||||
$this->assertFalse($b->isWritable());
|
||||
}
|
||||
|
||||
public function testCanCreateEmptyStream()
|
||||
{
|
||||
$b = new MultipartStream();
|
||||
$boundary = $b->getBoundary();
|
||||
$this->assertSame("--{$boundary}--\r\n", $b->getContents());
|
||||
$this->assertSame(strlen($boundary) + 6, $b->getSize());
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \InvalidArgumentException
|
||||
*/
|
||||
public function testValidatesFilesArrayElement()
|
||||
{
|
||||
new MultipartStream([['foo' => 'bar']]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \InvalidArgumentException
|
||||
*/
|
||||
public function testEnsuresFileHasName()
|
||||
{
|
||||
new MultipartStream([['contents' => 'bar']]);
|
||||
}
|
||||
|
||||
public function testSerializesFields()
|
||||
{
|
||||
$b = new MultipartStream([
|
||||
[
|
||||
'name' => 'foo',
|
||||
'contents' => 'bar'
|
||||
],
|
||||
[
|
||||
'name' => 'baz',
|
||||
'contents' => 'bam'
|
||||
]
|
||||
], 'boundary');
|
||||
$this->assertEquals(
|
||||
"--boundary\r\nContent-Disposition: form-data; name=\"foo\"\r\nContent-Length: 3\r\n\r\n"
|
||||
. "bar\r\n--boundary\r\nContent-Disposition: form-data; name=\"baz\"\r\nContent-Length: 3"
|
||||
. "\r\n\r\nbam\r\n--boundary--\r\n", (string) $b);
|
||||
}
|
||||
|
||||
public function testSerializesNonStringFields()
|
||||
{
|
||||
$b = new MultipartStream([
|
||||
[
|
||||
'name' => 'int',
|
||||
'contents' => (int) 1
|
||||
],
|
||||
[
|
||||
'name' => 'bool',
|
||||
'contents' => (boolean) false
|
||||
],
|
||||
[
|
||||
'name' => 'bool2',
|
||||
'contents' => (boolean) true
|
||||
],
|
||||
[
|
||||
'name' => 'float',
|
||||
'contents' => (float) 1.1
|
||||
]
|
||||
], 'boundary');
|
||||
$this->assertEquals(
|
||||
"--boundary\r\nContent-Disposition: form-data; name=\"int\"\r\nContent-Length: 1\r\n\r\n"
|
||||
. "1\r\n--boundary\r\nContent-Disposition: form-data; name=\"bool\"\r\n\r\n\r\n--boundary"
|
||||
. "\r\nContent-Disposition: form-data; name=\"bool2\"\r\nContent-Length: 1\r\n\r\n"
|
||||
. "1\r\n--boundary\r\nContent-Disposition: form-data; name=\"float\"\r\nContent-Length: 3"
|
||||
. "\r\n\r\n1.1\r\n--boundary--\r\n", (string) $b);
|
||||
}
|
||||
|
||||
public function testSerializesFiles()
|
||||
{
|
||||
$f1 = Psr7\FnStream::decorate(Psr7\stream_for('foo'), [
|
||||
'getMetadata' => function () {
|
||||
return '/foo/bar.txt';
|
||||
}
|
||||
]);
|
||||
|
||||
$f2 = Psr7\FnStream::decorate(Psr7\stream_for('baz'), [
|
||||
'getMetadata' => function () {
|
||||
return '/foo/baz.jpg';
|
||||
}
|
||||
]);
|
||||
|
||||
$f3 = Psr7\FnStream::decorate(Psr7\stream_for('bar'), [
|
||||
'getMetadata' => function () {
|
||||
return '/foo/bar.gif';
|
||||
}
|
||||
]);
|
||||
|
||||
$b = new MultipartStream([
|
||||
[
|
||||
'name' => 'foo',
|
||||
'contents' => $f1
|
||||
],
|
||||
[
|
||||
'name' => 'qux',
|
||||
'contents' => $f2
|
||||
],
|
||||
[
|
||||
'name' => 'qux',
|
||||
'contents' => $f3
|
||||
],
|
||||
], 'boundary');
|
||||
|
||||
$expected = <<<EOT
|
||||
--boundary
|
||||
Content-Disposition: form-data; name="foo"; filename="bar.txt"
|
||||
Content-Length: 3
|
||||
Content-Type: text/plain
|
||||
|
||||
foo
|
||||
--boundary
|
||||
Content-Disposition: form-data; name="qux"; filename="baz.jpg"
|
||||
Content-Length: 3
|
||||
Content-Type: image/jpeg
|
||||
|
||||
baz
|
||||
--boundary
|
||||
Content-Disposition: form-data; name="qux"; filename="bar.gif"
|
||||
Content-Length: 3
|
||||
Content-Type: image/gif
|
||||
|
||||
bar
|
||||
--boundary--
|
||||
|
||||
EOT;
|
||||
|
||||
$this->assertEquals($expected, str_replace("\r", '', $b));
|
||||
}
|
||||
|
||||
public function testSerializesFilesWithCustomHeaders()
|
||||
{
|
||||
$f1 = Psr7\FnStream::decorate(Psr7\stream_for('foo'), [
|
||||
'getMetadata' => function () {
|
||||
return '/foo/bar.txt';
|
||||
}
|
||||
]);
|
||||
|
||||
$b = new MultipartStream([
|
||||
[
|
||||
'name' => 'foo',
|
||||
'contents' => $f1,
|
||||
'headers' => [
|
||||
'x-foo' => 'bar',
|
||||
'content-disposition' => 'custom'
|
||||
]
|
||||
]
|
||||
], 'boundary');
|
||||
|
||||
$expected = <<<EOT
|
||||
--boundary
|
||||
x-foo: bar
|
||||
content-disposition: custom
|
||||
Content-Length: 3
|
||||
Content-Type: text/plain
|
||||
|
||||
foo
|
||||
--boundary--
|
||||
|
||||
EOT;
|
||||
|
||||
$this->assertEquals($expected, str_replace("\r", '', $b));
|
||||
}
|
||||
|
||||
public function testSerializesFilesWithCustomHeadersAndMultipleValues()
|
||||
{
|
||||
$f1 = Psr7\FnStream::decorate(Psr7\stream_for('foo'), [
|
||||
'getMetadata' => function () {
|
||||
return '/foo/bar.txt';
|
||||
}
|
||||
]);
|
||||
|
||||
$f2 = Psr7\FnStream::decorate(Psr7\stream_for('baz'), [
|
||||
'getMetadata' => function () {
|
||||
return '/foo/baz.jpg';
|
||||
}
|
||||
]);
|
||||
|
||||
$b = new MultipartStream([
|
||||
[
|
||||
'name' => 'foo',
|
||||
'contents' => $f1,
|
||||
'headers' => [
|
||||
'x-foo' => 'bar',
|
||||
'content-disposition' => 'custom'
|
||||
]
|
||||
],
|
||||
[
|
||||
'name' => 'foo',
|
||||
'contents' => $f2,
|
||||
'headers' => ['cOntenT-Type' => 'custom'],
|
||||
]
|
||||
], 'boundary');
|
||||
|
||||
$expected = <<<EOT
|
||||
--boundary
|
||||
x-foo: bar
|
||||
content-disposition: custom
|
||||
Content-Length: 3
|
||||
Content-Type: text/plain
|
||||
|
||||
foo
|
||||
--boundary
|
||||
cOntenT-Type: custom
|
||||
Content-Disposition: form-data; name="foo"; filename="baz.jpg"
|
||||
Content-Length: 3
|
||||
|
||||
baz
|
||||
--boundary--
|
||||
|
||||
EOT;
|
||||
|
||||
$this->assertEquals($expected, str_replace("\r", '', $b));
|
||||
}
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Tests\Psr7;
|
||||
|
||||
use GuzzleHttp\Psr7;
|
||||
use GuzzleHttp\Psr7\NoSeekStream;
|
||||
|
||||
/**
|
||||
* @covers GuzzleHttp\Psr7\NoSeekStream
|
||||
* @covers GuzzleHttp\Psr7\StreamDecoratorTrait
|
||||
*/
|
||||
class NoSeekStreamTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* @expectedException \RuntimeException
|
||||
* @expectedExceptionMessage Cannot seek a NoSeekStream
|
||||
*/
|
||||
public function testCannotSeek()
|
||||
{
|
||||
$s = $this->getMockBuilder('Psr\Http\Message\StreamInterface')
|
||||
->setMethods(['isSeekable', 'seek'])
|
||||
->getMockForAbstractClass();
|
||||
$s->expects($this->never())->method('seek');
|
||||
$s->expects($this->never())->method('isSeekable');
|
||||
$wrapped = new NoSeekStream($s);
|
||||
$this->assertFalse($wrapped->isSeekable());
|
||||
$wrapped->seek(2);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \RuntimeException
|
||||
* @expectedExceptionMessage Cannot write to a non-writable stream
|
||||
*/
|
||||
public function testHandlesClose()
|
||||
{
|
||||
$s = Psr7\stream_for('foo');
|
||||
$wrapped = new NoSeekStream($s);
|
||||
$wrapped->close();
|
||||
$wrapped->write('foo');
|
||||
}
|
||||
}
|
|
@ -1,72 +0,0 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Tests\Psr7;
|
||||
|
||||
use GuzzleHttp\Psr7\LimitStream;
|
||||
use GuzzleHttp\Psr7\PumpStream;
|
||||
use GuzzleHttp\Psr7;
|
||||
|
||||
class PumpStreamTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testHasMetadataAndSize()
|
||||
{
|
||||
$p = new PumpStream(function () {}, [
|
||||
'metadata' => ['foo' => 'bar'],
|
||||
'size' => 100
|
||||
]);
|
||||
|
||||
$this->assertEquals('bar', $p->getMetadata('foo'));
|
||||
$this->assertEquals(['foo' => 'bar'], $p->getMetadata());
|
||||
$this->assertEquals(100, $p->getSize());
|
||||
}
|
||||
|
||||
public function testCanReadFromCallable()
|
||||
{
|
||||
$p = Psr7\stream_for(function ($size) {
|
||||
return 'a';
|
||||
});
|
||||
$this->assertEquals('a', $p->read(1));
|
||||
$this->assertEquals(1, $p->tell());
|
||||
$this->assertEquals('aaaaa', $p->read(5));
|
||||
$this->assertEquals(6, $p->tell());
|
||||
}
|
||||
|
||||
public function testStoresExcessDataInBuffer()
|
||||
{
|
||||
$called = [];
|
||||
$p = Psr7\stream_for(function ($size) use (&$called) {
|
||||
$called[] = $size;
|
||||
return 'abcdef';
|
||||
});
|
||||
$this->assertEquals('a', $p->read(1));
|
||||
$this->assertEquals('b', $p->read(1));
|
||||
$this->assertEquals('cdef', $p->read(4));
|
||||
$this->assertEquals('abcdefabc', $p->read(9));
|
||||
$this->assertEquals([1, 9, 3], $called);
|
||||
}
|
||||
|
||||
public function testInifiniteStreamWrappedInLimitStream()
|
||||
{
|
||||
$p = Psr7\stream_for(function () { return 'a'; });
|
||||
$s = new LimitStream($p, 5);
|
||||
$this->assertEquals('aaaaa', (string) $s);
|
||||
}
|
||||
|
||||
public function testDescribesCapabilities()
|
||||
{
|
||||
$p = Psr7\stream_for(function () {});
|
||||
$this->assertTrue($p->isReadable());
|
||||
$this->assertFalse($p->isSeekable());
|
||||
$this->assertFalse($p->isWritable());
|
||||
$this->assertNull($p->getSize());
|
||||
$this->assertEquals('', $p->getContents());
|
||||
$this->assertEquals('', (string) $p);
|
||||
$p->close();
|
||||
$this->assertEquals('', $p->read(10));
|
||||
$this->assertTrue($p->eof());
|
||||
|
||||
try {
|
||||
$this->assertFalse($p->write('aa'));
|
||||
$this->fail();
|
||||
} catch (\RuntimeException $e) {}
|
||||
}
|
||||
}
|
|
@ -1,195 +0,0 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Tests\Psr7;
|
||||
|
||||
use GuzzleHttp\Psr7;
|
||||
use GuzzleHttp\Psr7\Request;
|
||||
use GuzzleHttp\Psr7\Uri;
|
||||
|
||||
/**
|
||||
* @covers GuzzleHttp\Psr7\Request
|
||||
*/
|
||||
class RequestTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testRequestUriMayBeString()
|
||||
{
|
||||
$r = new Request('GET', '/');
|
||||
$this->assertEquals('/', (string) $r->getUri());
|
||||
}
|
||||
|
||||
public function testRequestUriMayBeUri()
|
||||
{
|
||||
$uri = new Uri('/');
|
||||
$r = new Request('GET', $uri);
|
||||
$this->assertSame($uri, $r->getUri());
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \InvalidArgumentException
|
||||
*/
|
||||
public function testValidateRequestUri()
|
||||
{
|
||||
new Request('GET', '///');
|
||||
}
|
||||
|
||||
public function testCanConstructWithBody()
|
||||
{
|
||||
$r = new Request('GET', '/', [], 'baz');
|
||||
$this->assertInstanceOf('Psr\Http\Message\StreamInterface', $r->getBody());
|
||||
$this->assertEquals('baz', (string) $r->getBody());
|
||||
}
|
||||
|
||||
public function testNullBody()
|
||||
{
|
||||
$r = new Request('GET', '/', [], null);
|
||||
$this->assertInstanceOf('Psr\Http\Message\StreamInterface', $r->getBody());
|
||||
$this->assertSame('', (string) $r->getBody());
|
||||
}
|
||||
|
||||
public function testFalseyBody()
|
||||
{
|
||||
$r = new Request('GET', '/', [], '0');
|
||||
$this->assertInstanceOf('Psr\Http\Message\StreamInterface', $r->getBody());
|
||||
$this->assertSame('0', (string) $r->getBody());
|
||||
}
|
||||
|
||||
public function testConstructorDoesNotReadStreamBody()
|
||||
{
|
||||
$streamIsRead = false;
|
||||
$body = Psr7\FnStream::decorate(Psr7\stream_for(''), [
|
||||
'__toString' => function () use (&$streamIsRead) {
|
||||
$streamIsRead = true;
|
||||
return '';
|
||||
}
|
||||
]);
|
||||
|
||||
$r = new Request('GET', '/', [], $body);
|
||||
$this->assertFalse($streamIsRead);
|
||||
$this->assertSame($body, $r->getBody());
|
||||
}
|
||||
|
||||
public function testCapitalizesMethod()
|
||||
{
|
||||
$r = new Request('get', '/');
|
||||
$this->assertEquals('GET', $r->getMethod());
|
||||
}
|
||||
|
||||
public function testCapitalizesWithMethod()
|
||||
{
|
||||
$r = new Request('GET', '/');
|
||||
$this->assertEquals('PUT', $r->withMethod('put')->getMethod());
|
||||
}
|
||||
|
||||
public function testWithUri()
|
||||
{
|
||||
$r1 = new Request('GET', '/');
|
||||
$u1 = $r1->getUri();
|
||||
$u2 = new Uri('http://www.example.com');
|
||||
$r2 = $r1->withUri($u2);
|
||||
$this->assertNotSame($r1, $r2);
|
||||
$this->assertSame($u2, $r2->getUri());
|
||||
$this->assertSame($u1, $r1->getUri());
|
||||
}
|
||||
|
||||
public function testSameInstanceWhenSameUri()
|
||||
{
|
||||
$r1 = new Request('GET', 'http://foo.com');
|
||||
$r2 = $r1->withUri($r1->getUri());
|
||||
$this->assertSame($r1, $r2);
|
||||
}
|
||||
|
||||
public function testWithRequestTarget()
|
||||
{
|
||||
$r1 = new Request('GET', '/');
|
||||
$r2 = $r1->withRequestTarget('*');
|
||||
$this->assertEquals('*', $r2->getRequestTarget());
|
||||
$this->assertEquals('/', $r1->getRequestTarget());
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \InvalidArgumentException
|
||||
*/
|
||||
public function testRequestTargetDoesNotAllowSpaces()
|
||||
{
|
||||
$r1 = new Request('GET', '/');
|
||||
$r1->withRequestTarget('/foo bar');
|
||||
}
|
||||
|
||||
public function testRequestTargetDefaultsToSlash()
|
||||
{
|
||||
$r1 = new Request('GET', '');
|
||||
$this->assertEquals('/', $r1->getRequestTarget());
|
||||
$r2 = new Request('GET', '*');
|
||||
$this->assertEquals('*', $r2->getRequestTarget());
|
||||
$r3 = new Request('GET', 'http://foo.com/bar baz/');
|
||||
$this->assertEquals('/bar%20baz/', $r3->getRequestTarget());
|
||||
}
|
||||
|
||||
public function testBuildsRequestTarget()
|
||||
{
|
||||
$r1 = new Request('GET', 'http://foo.com/baz?bar=bam');
|
||||
$this->assertEquals('/baz?bar=bam', $r1->getRequestTarget());
|
||||
}
|
||||
|
||||
public function testBuildsRequestTargetWithFalseyQuery()
|
||||
{
|
||||
$r1 = new Request('GET', 'http://foo.com/baz?0');
|
||||
$this->assertEquals('/baz?0', $r1->getRequestTarget());
|
||||
}
|
||||
|
||||
public function testHostIsAddedFirst()
|
||||
{
|
||||
$r = new Request('GET', 'http://foo.com/baz?bar=bam', ['Foo' => 'Bar']);
|
||||
$this->assertEquals([
|
||||
'Host' => ['foo.com'],
|
||||
'Foo' => ['Bar']
|
||||
], $r->getHeaders());
|
||||
}
|
||||
|
||||
public function testCanGetHeaderAsCsv()
|
||||
{
|
||||
$r = new Request('GET', 'http://foo.com/baz?bar=bam', [
|
||||
'Foo' => ['a', 'b', 'c']
|
||||
]);
|
||||
$this->assertEquals('a, b, c', $r->getHeaderLine('Foo'));
|
||||
$this->assertEquals('', $r->getHeaderLine('Bar'));
|
||||
}
|
||||
|
||||
public function testHostIsNotOverwrittenWhenPreservingHost()
|
||||
{
|
||||
$r = new Request('GET', 'http://foo.com/baz?bar=bam', ['Host' => 'a.com']);
|
||||
$this->assertEquals(['Host' => ['a.com']], $r->getHeaders());
|
||||
$r2 = $r->withUri(new Uri('http://www.foo.com/bar'), true);
|
||||
$this->assertEquals('a.com', $r2->getHeaderLine('Host'));
|
||||
}
|
||||
|
||||
public function testOverridesHostWithUri()
|
||||
{
|
||||
$r = new Request('GET', 'http://foo.com/baz?bar=bam');
|
||||
$this->assertEquals(['Host' => ['foo.com']], $r->getHeaders());
|
||||
$r2 = $r->withUri(new Uri('http://www.baz.com/bar'));
|
||||
$this->assertEquals('www.baz.com', $r2->getHeaderLine('Host'));
|
||||
}
|
||||
|
||||
public function testAggregatesHeaders()
|
||||
{
|
||||
$r = new Request('GET', '', [
|
||||
'ZOO' => 'zoobar',
|
||||
'zoo' => ['foobar', 'zoobar']
|
||||
]);
|
||||
$this->assertEquals(['ZOO' => ['zoobar', 'foobar', 'zoobar']], $r->getHeaders());
|
||||
$this->assertEquals('zoobar, foobar, zoobar', $r->getHeaderLine('zoo'));
|
||||
}
|
||||
|
||||
public function testAddsPortToHeader()
|
||||
{
|
||||
$r = new Request('GET', 'http://foo.com:8124/bar');
|
||||
$this->assertEquals('foo.com:8124', $r->getHeaderLine('host'));
|
||||
}
|
||||
|
||||
public function testAddsPortToHeaderAndReplacePreviousPort()
|
||||
{
|
||||
$r = new Request('GET', 'http://foo.com:8124/bar');
|
||||
$r = $r->withUri(new Uri('http://foo.com:8125/bar'));
|
||||
$this->assertEquals('foo.com:8125', $r->getHeaderLine('host'));
|
||||
}
|
||||
}
|
|
@ -1,252 +0,0 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Tests\Psr7;
|
||||
|
||||
use GuzzleHttp\Psr7;
|
||||
use GuzzleHttp\Psr7\Response;
|
||||
|
||||
/**
|
||||
* @covers GuzzleHttp\Psr7\MessageTrait
|
||||
* @covers GuzzleHttp\Psr7\Response
|
||||
*/
|
||||
class ResponseTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testDefaultConstructor()
|
||||
{
|
||||
$r = new Response();
|
||||
$this->assertSame(200, $r->getStatusCode());
|
||||
$this->assertSame('1.1', $r->getProtocolVersion());
|
||||
$this->assertSame('OK', $r->getReasonPhrase());
|
||||
$this->assertSame([], $r->getHeaders());
|
||||
$this->assertInstanceOf('Psr\Http\Message\StreamInterface', $r->getBody());
|
||||
$this->assertSame('', (string) $r->getBody());
|
||||
}
|
||||
|
||||
public function testCanConstructWithStatusCode()
|
||||
{
|
||||
$r = new Response(404);
|
||||
$this->assertSame(404, $r->getStatusCode());
|
||||
$this->assertSame('Not Found', $r->getReasonPhrase());
|
||||
}
|
||||
|
||||
public function testConstructorDoesNotReadStreamBody()
|
||||
{
|
||||
$streamIsRead = false;
|
||||
$body = Psr7\FnStream::decorate(Psr7\stream_for(''), [
|
||||
'__toString' => function () use (&$streamIsRead) {
|
||||
$streamIsRead = true;
|
||||
return '';
|
||||
}
|
||||
]);
|
||||
|
||||
$r = new Response(200, [], $body);
|
||||
$this->assertFalse($streamIsRead);
|
||||
$this->assertSame($body, $r->getBody());
|
||||
}
|
||||
|
||||
public function testStatusCanBeNumericString()
|
||||
{
|
||||
$r = new Response('404');
|
||||
$r2 = $r->withStatus('201');
|
||||
$this->assertSame(404, $r->getStatusCode());
|
||||
$this->assertSame('Not Found', $r->getReasonPhrase());
|
||||
$this->assertSame(201, $r2->getStatusCode());
|
||||
$this->assertSame('Created', $r2->getReasonPhrase());
|
||||
}
|
||||
|
||||
public function testCanConstructWithHeaders()
|
||||
{
|
||||
$r = new Response(200, ['Foo' => 'Bar']);
|
||||
$this->assertSame(['Foo' => ['Bar']], $r->getHeaders());
|
||||
$this->assertSame('Bar', $r->getHeaderLine('Foo'));
|
||||
$this->assertSame(['Bar'], $r->getHeader('Foo'));
|
||||
}
|
||||
|
||||
public function testCanConstructWithHeadersAsArray()
|
||||
{
|
||||
$r = new Response(200, [
|
||||
'Foo' => ['baz', 'bar']
|
||||
]);
|
||||
$this->assertSame(['Foo' => ['baz', 'bar']], $r->getHeaders());
|
||||
$this->assertSame('baz, bar', $r->getHeaderLine('Foo'));
|
||||
$this->assertSame(['baz', 'bar'], $r->getHeader('Foo'));
|
||||
}
|
||||
|
||||
public function testCanConstructWithBody()
|
||||
{
|
||||
$r = new Response(200, [], 'baz');
|
||||
$this->assertInstanceOf('Psr\Http\Message\StreamInterface', $r->getBody());
|
||||
$this->assertSame('baz', (string) $r->getBody());
|
||||
}
|
||||
|
||||
public function testNullBody()
|
||||
{
|
||||
$r = new Response(200, [], null);
|
||||
$this->assertInstanceOf('Psr\Http\Message\StreamInterface', $r->getBody());
|
||||
$this->assertSame('', (string) $r->getBody());
|
||||
}
|
||||
|
||||
public function testFalseyBody()
|
||||
{
|
||||
$r = new Response(200, [], '0');
|
||||
$this->assertInstanceOf('Psr\Http\Message\StreamInterface', $r->getBody());
|
||||
$this->assertSame('0', (string) $r->getBody());
|
||||
}
|
||||
|
||||
public function testCanConstructWithReason()
|
||||
{
|
||||
$r = new Response(200, [], null, '1.1', 'bar');
|
||||
$this->assertSame('bar', $r->getReasonPhrase());
|
||||
|
||||
$r = new Response(200, [], null, '1.1', '0');
|
||||
$this->assertSame('0', $r->getReasonPhrase(), 'Falsey reason works');
|
||||
}
|
||||
|
||||
public function testCanConstructWithProtocolVersion()
|
||||
{
|
||||
$r = new Response(200, [], null, '1000');
|
||||
$this->assertSame('1000', $r->getProtocolVersion());
|
||||
}
|
||||
|
||||
public function testWithStatusCodeAndNoReason()
|
||||
{
|
||||
$r = (new Response())->withStatus(201);
|
||||
$this->assertSame(201, $r->getStatusCode());
|
||||
$this->assertSame('Created', $r->getReasonPhrase());
|
||||
}
|
||||
|
||||
public function testWithStatusCodeAndReason()
|
||||
{
|
||||
$r = (new Response())->withStatus(201, 'Foo');
|
||||
$this->assertSame(201, $r->getStatusCode());
|
||||
$this->assertSame('Foo', $r->getReasonPhrase());
|
||||
|
||||
$r = (new Response())->withStatus(201, '0');
|
||||
$this->assertSame(201, $r->getStatusCode());
|
||||
$this->assertSame('0', $r->getReasonPhrase(), 'Falsey reason works');
|
||||
}
|
||||
|
||||
public function testWithProtocolVersion()
|
||||
{
|
||||
$r = (new Response())->withProtocolVersion('1000');
|
||||
$this->assertSame('1000', $r->getProtocolVersion());
|
||||
}
|
||||
|
||||
public function testSameInstanceWhenSameProtocol()
|
||||
{
|
||||
$r = new Response();
|
||||
$this->assertSame($r, $r->withProtocolVersion('1.1'));
|
||||
}
|
||||
|
||||
public function testWithBody()
|
||||
{
|
||||
$b = Psr7\stream_for('0');
|
||||
$r = (new Response())->withBody($b);
|
||||
$this->assertInstanceOf('Psr\Http\Message\StreamInterface', $r->getBody());
|
||||
$this->assertSame('0', (string) $r->getBody());
|
||||
}
|
||||
|
||||
public function testSameInstanceWhenSameBody()
|
||||
{
|
||||
$r = new Response();
|
||||
$b = $r->getBody();
|
||||
$this->assertSame($r, $r->withBody($b));
|
||||
}
|
||||
|
||||
public function testWithHeader()
|
||||
{
|
||||
$r = new Response(200, ['Foo' => 'Bar']);
|
||||
$r2 = $r->withHeader('baZ', 'Bam');
|
||||
$this->assertSame(['Foo' => ['Bar']], $r->getHeaders());
|
||||
$this->assertSame(['Foo' => ['Bar'], 'baZ' => ['Bam']], $r2->getHeaders());
|
||||
$this->assertSame('Bam', $r2->getHeaderLine('baz'));
|
||||
$this->assertSame(['Bam'], $r2->getHeader('baz'));
|
||||
}
|
||||
|
||||
public function testWithHeaderAsArray()
|
||||
{
|
||||
$r = new Response(200, ['Foo' => 'Bar']);
|
||||
$r2 = $r->withHeader('baZ', ['Bam', 'Bar']);
|
||||
$this->assertSame(['Foo' => ['Bar']], $r->getHeaders());
|
||||
$this->assertSame(['Foo' => ['Bar'], 'baZ' => ['Bam', 'Bar']], $r2->getHeaders());
|
||||
$this->assertSame('Bam, Bar', $r2->getHeaderLine('baz'));
|
||||
$this->assertSame(['Bam', 'Bar'], $r2->getHeader('baz'));
|
||||
}
|
||||
|
||||
public function testWithHeaderReplacesDifferentCase()
|
||||
{
|
||||
$r = new Response(200, ['Foo' => 'Bar']);
|
||||
$r2 = $r->withHeader('foO', 'Bam');
|
||||
$this->assertSame(['Foo' => ['Bar']], $r->getHeaders());
|
||||
$this->assertSame(['foO' => ['Bam']], $r2->getHeaders());
|
||||
$this->assertSame('Bam', $r2->getHeaderLine('foo'));
|
||||
$this->assertSame(['Bam'], $r2->getHeader('foo'));
|
||||
}
|
||||
|
||||
public function testWithAddedHeader()
|
||||
{
|
||||
$r = new Response(200, ['Foo' => 'Bar']);
|
||||
$r2 = $r->withAddedHeader('foO', 'Baz');
|
||||
$this->assertSame(['Foo' => ['Bar']], $r->getHeaders());
|
||||
$this->assertSame(['Foo' => ['Bar', 'Baz']], $r2->getHeaders());
|
||||
$this->assertSame('Bar, Baz', $r2->getHeaderLine('foo'));
|
||||
$this->assertSame(['Bar', 'Baz'], $r2->getHeader('foo'));
|
||||
}
|
||||
|
||||
public function testWithAddedHeaderAsArray()
|
||||
{
|
||||
$r = new Response(200, ['Foo' => 'Bar']);
|
||||
$r2 = $r->withAddedHeader('foO', ['Baz', 'Bam']);
|
||||
$this->assertSame(['Foo' => ['Bar']], $r->getHeaders());
|
||||
$this->assertSame(['Foo' => ['Bar', 'Baz', 'Bam']], $r2->getHeaders());
|
||||
$this->assertSame('Bar, Baz, Bam', $r2->getHeaderLine('foo'));
|
||||
$this->assertSame(['Bar', 'Baz', 'Bam'], $r2->getHeader('foo'));
|
||||
}
|
||||
|
||||
public function testWithAddedHeaderThatDoesNotExist()
|
||||
{
|
||||
$r = new Response(200, ['Foo' => 'Bar']);
|
||||
$r2 = $r->withAddedHeader('nEw', 'Baz');
|
||||
$this->assertSame(['Foo' => ['Bar']], $r->getHeaders());
|
||||
$this->assertSame(['Foo' => ['Bar'], 'nEw' => ['Baz']], $r2->getHeaders());
|
||||
$this->assertSame('Baz', $r2->getHeaderLine('new'));
|
||||
$this->assertSame(['Baz'], $r2->getHeader('new'));
|
||||
}
|
||||
|
||||
public function testWithoutHeaderThatExists()
|
||||
{
|
||||
$r = new Response(200, ['Foo' => 'Bar', 'Baz' => 'Bam']);
|
||||
$r2 = $r->withoutHeader('foO');
|
||||
$this->assertTrue($r->hasHeader('foo'));
|
||||
$this->assertSame(['Foo' => ['Bar'], 'Baz' => ['Bam']], $r->getHeaders());
|
||||
$this->assertFalse($r2->hasHeader('foo'));
|
||||
$this->assertSame(['Baz' => ['Bam']], $r2->getHeaders());
|
||||
}
|
||||
|
||||
public function testWithoutHeaderThatDoesNotExist()
|
||||
{
|
||||
$r = new Response(200, ['Baz' => 'Bam']);
|
||||
$r2 = $r->withoutHeader('foO');
|
||||
$this->assertSame($r, $r2);
|
||||
$this->assertFalse($r2->hasHeader('foo'));
|
||||
$this->assertSame(['Baz' => ['Bam']], $r2->getHeaders());
|
||||
}
|
||||
|
||||
public function testSameInstanceWhenRemovingMissingHeader()
|
||||
{
|
||||
$r = new Response();
|
||||
$this->assertSame($r, $r->withoutHeader('foo'));
|
||||
}
|
||||
|
||||
public function testHeaderValuesAreTrimmed()
|
||||
{
|
||||
$r1 = new Response(200, ['OWS' => " \t \tFoo\t \t "]);
|
||||
$r2 = (new Response())->withHeader('OWS', " \t \tFoo\t \t ");
|
||||
$r3 = (new Response())->withAddedHeader('OWS', " \t \tFoo\t \t ");;
|
||||
|
||||
foreach ([$r1, $r2, $r3] as $r) {
|
||||
$this->assertSame(['OWS' => ['Foo']], $r->getHeaders());
|
||||
$this->assertSame('Foo', $r->getHeaderLine('OWS'));
|
||||
$this->assertSame(['Foo'], $r->getHeader('OWS'));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,532 +0,0 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Tests\Psr7;
|
||||
|
||||
use GuzzleHttp\Psr7\ServerRequest;
|
||||
use GuzzleHttp\Psr7\UploadedFile;
|
||||
use GuzzleHttp\Psr7\Uri;
|
||||
|
||||
/**
|
||||
* @covers GuzzleHttp\Psr7\ServerRequest
|
||||
*/
|
||||
class ServerRequestTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function dataNormalizeFiles()
|
||||
{
|
||||
return [
|
||||
'Single file' => [
|
||||
[
|
||||
'file' => [
|
||||
'name' => 'MyFile.txt',
|
||||
'type' => 'text/plain',
|
||||
'tmp_name' => '/tmp/php/php1h4j1o',
|
||||
'error' => '0',
|
||||
'size' => '123'
|
||||
]
|
||||
],
|
||||
[
|
||||
'file' => new UploadedFile(
|
||||
'/tmp/php/php1h4j1o',
|
||||
123,
|
||||
UPLOAD_ERR_OK,
|
||||
'MyFile.txt',
|
||||
'text/plain'
|
||||
)
|
||||
]
|
||||
],
|
||||
'Empty file' => [
|
||||
[
|
||||
'image_file' => [
|
||||
'name' => '',
|
||||
'type' => '',
|
||||
'tmp_name' => '',
|
||||
'error' => '4',
|
||||
'size' => '0'
|
||||
]
|
||||
],
|
||||
[
|
||||
'image_file' => new UploadedFile(
|
||||
'',
|
||||
0,
|
||||
UPLOAD_ERR_NO_FILE,
|
||||
'',
|
||||
''
|
||||
)
|
||||
]
|
||||
],
|
||||
'Already Converted' => [
|
||||
[
|
||||
'file' => new UploadedFile(
|
||||
'/tmp/php/php1h4j1o',
|
||||
123,
|
||||
UPLOAD_ERR_OK,
|
||||
'MyFile.txt',
|
||||
'text/plain'
|
||||
)
|
||||
],
|
||||
[
|
||||
'file' => new UploadedFile(
|
||||
'/tmp/php/php1h4j1o',
|
||||
123,
|
||||
UPLOAD_ERR_OK,
|
||||
'MyFile.txt',
|
||||
'text/plain'
|
||||
)
|
||||
]
|
||||
],
|
||||
'Already Converted array' => [
|
||||
[
|
||||
'file' => [
|
||||
new UploadedFile(
|
||||
'/tmp/php/php1h4j1o',
|
||||
123,
|
||||
UPLOAD_ERR_OK,
|
||||
'MyFile.txt',
|
||||
'text/plain'
|
||||
),
|
||||
new UploadedFile(
|
||||
'',
|
||||
0,
|
||||
UPLOAD_ERR_NO_FILE,
|
||||
'',
|
||||
''
|
||||
)
|
||||
],
|
||||
],
|
||||
[
|
||||
'file' => [
|
||||
new UploadedFile(
|
||||
'/tmp/php/php1h4j1o',
|
||||
123,
|
||||
UPLOAD_ERR_OK,
|
||||
'MyFile.txt',
|
||||
'text/plain'
|
||||
),
|
||||
new UploadedFile(
|
||||
'',
|
||||
0,
|
||||
UPLOAD_ERR_NO_FILE,
|
||||
'',
|
||||
''
|
||||
)
|
||||
],
|
||||
]
|
||||
],
|
||||
'Multiple files' => [
|
||||
[
|
||||
'text_file' => [
|
||||
'name' => 'MyFile.txt',
|
||||
'type' => 'text/plain',
|
||||
'tmp_name' => '/tmp/php/php1h4j1o',
|
||||
'error' => '0',
|
||||
'size' => '123'
|
||||
],
|
||||
'image_file' => [
|
||||
'name' => '',
|
||||
'type' => '',
|
||||
'tmp_name' => '',
|
||||
'error' => '4',
|
||||
'size' => '0'
|
||||
]
|
||||
],
|
||||
[
|
||||
'text_file' => new UploadedFile(
|
||||
'/tmp/php/php1h4j1o',
|
||||
123,
|
||||
UPLOAD_ERR_OK,
|
||||
'MyFile.txt',
|
||||
'text/plain'
|
||||
),
|
||||
'image_file' => new UploadedFile(
|
||||
'',
|
||||
0,
|
||||
UPLOAD_ERR_NO_FILE,
|
||||
'',
|
||||
''
|
||||
)
|
||||
]
|
||||
],
|
||||
'Nested files' => [
|
||||
[
|
||||
'file' => [
|
||||
'name' => [
|
||||
0 => 'MyFile.txt',
|
||||
1 => 'Image.png',
|
||||
],
|
||||
'type' => [
|
||||
0 => 'text/plain',
|
||||
1 => 'image/png',
|
||||
],
|
||||
'tmp_name' => [
|
||||
0 => '/tmp/php/hp9hskjhf',
|
||||
1 => '/tmp/php/php1h4j1o',
|
||||
],
|
||||
'error' => [
|
||||
0 => '0',
|
||||
1 => '0',
|
||||
],
|
||||
'size' => [
|
||||
0 => '123',
|
||||
1 => '7349',
|
||||
],
|
||||
],
|
||||
'nested' => [
|
||||
'name' => [
|
||||
'other' => 'Flag.txt',
|
||||
'test' => [
|
||||
0 => 'Stuff.txt',
|
||||
1 => '',
|
||||
],
|
||||
],
|
||||
'type' => [
|
||||
'other' => 'text/plain',
|
||||
'test' => [
|
||||
0 => 'text/plain',
|
||||
1 => '',
|
||||
],
|
||||
],
|
||||
'tmp_name' => [
|
||||
'other' => '/tmp/php/hp9hskjhf',
|
||||
'test' => [
|
||||
0 => '/tmp/php/asifu2gp3',
|
||||
1 => '',
|
||||
],
|
||||
],
|
||||
'error' => [
|
||||
'other' => '0',
|
||||
'test' => [
|
||||
0 => '0',
|
||||
1 => '4',
|
||||
],
|
||||
],
|
||||
'size' => [
|
||||
'other' => '421',
|
||||
'test' => [
|
||||
0 => '32',
|
||||
1 => '0',
|
||||
]
|
||||
]
|
||||
],
|
||||
],
|
||||
[
|
||||
'file' => [
|
||||
0 => new UploadedFile(
|
||||
'/tmp/php/hp9hskjhf',
|
||||
123,
|
||||
UPLOAD_ERR_OK,
|
||||
'MyFile.txt',
|
||||
'text/plain'
|
||||
),
|
||||
1 => new UploadedFile(
|
||||
'/tmp/php/php1h4j1o',
|
||||
7349,
|
||||
UPLOAD_ERR_OK,
|
||||
'Image.png',
|
||||
'image/png'
|
||||
),
|
||||
],
|
||||
'nested' => [
|
||||
'other' => new UploadedFile(
|
||||
'/tmp/php/hp9hskjhf',
|
||||
421,
|
||||
UPLOAD_ERR_OK,
|
||||
'Flag.txt',
|
||||
'text/plain'
|
||||
),
|
||||
'test' => [
|
||||
0 => new UploadedFile(
|
||||
'/tmp/php/asifu2gp3',
|
||||
32,
|
||||
UPLOAD_ERR_OK,
|
||||
'Stuff.txt',
|
||||
'text/plain'
|
||||
),
|
||||
1 => new UploadedFile(
|
||||
'',
|
||||
0,
|
||||
UPLOAD_ERR_NO_FILE,
|
||||
'',
|
||||
''
|
||||
),
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dataNormalizeFiles
|
||||
*/
|
||||
public function testNormalizeFiles($files, $expected)
|
||||
{
|
||||
$result = ServerRequest::normalizeFiles($files);
|
||||
|
||||
$this->assertEquals($expected, $result);
|
||||
}
|
||||
|
||||
public function testNormalizeFilesRaisesException()
|
||||
{
|
||||
$this->setExpectedException('InvalidArgumentException', 'Invalid value in files specification');
|
||||
|
||||
ServerRequest::normalizeFiles(['test' => 'something']);
|
||||
}
|
||||
|
||||
public function dataGetUriFromGlobals()
|
||||
{
|
||||
$server = [
|
||||
'PHP_SELF' => '/blog/article.php',
|
||||
'GATEWAY_INTERFACE' => 'CGI/1.1',
|
||||
'SERVER_ADDR' => 'Server IP: 217.112.82.20',
|
||||
'SERVER_NAME' => 'www.blakesimpson.co.uk',
|
||||
'SERVER_SOFTWARE' => 'Apache/2.2.15 (Win32) JRun/4.0 PHP/5.2.13',
|
||||
'SERVER_PROTOCOL' => 'HTTP/1.0',
|
||||
'REQUEST_METHOD' => 'POST',
|
||||
'REQUEST_TIME' => 'Request start time: 1280149029',
|
||||
'QUERY_STRING' => 'id=10&user=foo',
|
||||
'DOCUMENT_ROOT' => '/path/to/your/server/root/',
|
||||
'HTTP_ACCEPT' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
|
||||
'HTTP_ACCEPT_CHARSET' => 'ISO-8859-1,utf-8;q=0.7,*;q=0.7',
|
||||
'HTTP_ACCEPT_ENCODING' => 'gzip,deflate',
|
||||
'HTTP_ACCEPT_LANGUAGE' => 'en-gb,en;q=0.5',
|
||||
'HTTP_CONNECTION' => 'keep-alive',
|
||||
'HTTP_HOST' => 'www.blakesimpson.co.uk',
|
||||
'HTTP_REFERER' => 'http://previous.url.com',
|
||||
'HTTP_USER_AGENT' => 'Mozilla/5.0 (Windows; U; Windows NT 6.0; en-GB; rv:1.9.2.6) Gecko/20100625 Firefox/3.6.6 ( .NET CLR 3.5.30729)',
|
||||
'HTTPS' => '1',
|
||||
'REMOTE_ADDR' => '193.60.168.69',
|
||||
'REMOTE_HOST' => 'Client server\'s host name',
|
||||
'REMOTE_PORT' => '5390',
|
||||
'SCRIPT_FILENAME' => '/path/to/this/script.php',
|
||||
'SERVER_ADMIN' => 'webmaster@blakesimpson.co.uk',
|
||||
'SERVER_PORT' => '80',
|
||||
'SERVER_SIGNATURE' => 'Version signature: 5.123',
|
||||
'SCRIPT_NAME' => '/blog/article.php',
|
||||
'REQUEST_URI' => '/blog/article.php?id=10&user=foo',
|
||||
];
|
||||
|
||||
return [
|
||||
'Normal request' => [
|
||||
'http://www.blakesimpson.co.uk/blog/article.php?id=10&user=foo',
|
||||
$server,
|
||||
],
|
||||
'Secure request' => [
|
||||
'https://www.blakesimpson.co.uk/blog/article.php?id=10&user=foo',
|
||||
array_merge($server, ['HTTPS' => 'on', 'SERVER_PORT' => '443']),
|
||||
],
|
||||
'HTTP_HOST missing' => [
|
||||
'http://www.blakesimpson.co.uk/blog/article.php?id=10&user=foo',
|
||||
array_merge($server, ['HTTP_HOST' => null]),
|
||||
],
|
||||
'No query String' => [
|
||||
'http://www.blakesimpson.co.uk/blog/article.php',
|
||||
array_merge($server, ['REQUEST_URI' => '/blog/article.php', 'QUERY_STRING' => '']),
|
||||
],
|
||||
'Different port' => [
|
||||
'http://www.blakesimpson.co.uk:8324/blog/article.php?id=10&user=foo',
|
||||
array_merge($server, ['SERVER_PORT' => '8324']),
|
||||
],
|
||||
'Empty server variable' => [
|
||||
'',
|
||||
[],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dataGetUriFromGlobals
|
||||
*/
|
||||
public function testGetUriFromGlobals($expected, $serverParams)
|
||||
{
|
||||
$_SERVER = $serverParams;
|
||||
|
||||
$this->assertEquals(new Uri($expected), ServerRequest::getUriFromGlobals());
|
||||
}
|
||||
|
||||
public function testFromGlobals()
|
||||
{
|
||||
$_SERVER = [
|
||||
'PHP_SELF' => '/blog/article.php',
|
||||
'GATEWAY_INTERFACE' => 'CGI/1.1',
|
||||
'SERVER_ADDR' => 'Server IP: 217.112.82.20',
|
||||
'SERVER_NAME' => 'www.blakesimpson.co.uk',
|
||||
'SERVER_SOFTWARE' => 'Apache/2.2.15 (Win32) JRun/4.0 PHP/5.2.13',
|
||||
'SERVER_PROTOCOL' => 'HTTP/1.0',
|
||||
'REQUEST_METHOD' => 'POST',
|
||||
'REQUEST_TIME' => 'Request start time: 1280149029',
|
||||
'QUERY_STRING' => 'id=10&user=foo',
|
||||
'DOCUMENT_ROOT' => '/path/to/your/server/root/',
|
||||
'HTTP_ACCEPT' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
|
||||
'HTTP_ACCEPT_CHARSET' => 'ISO-8859-1,utf-8;q=0.7,*;q=0.7',
|
||||
'HTTP_ACCEPT_ENCODING' => 'gzip,deflate',
|
||||
'HTTP_ACCEPT_LANGUAGE' => 'en-gb,en;q=0.5',
|
||||
'HTTP_CONNECTION' => 'keep-alive',
|
||||
'HTTP_HOST' => 'www.blakesimpson.co.uk',
|
||||
'HTTP_REFERER' => 'http://previous.url.com',
|
||||
'HTTP_USER_AGENT' => 'Mozilla/5.0 (Windows; U; Windows NT 6.0; en-GB; rv:1.9.2.6) Gecko/20100625 Firefox/3.6.6 ( .NET CLR 3.5.30729)',
|
||||
'HTTPS' => '1',
|
||||
'REMOTE_ADDR' => '193.60.168.69',
|
||||
'REMOTE_HOST' => 'Client server\'s host name',
|
||||
'REMOTE_PORT' => '5390',
|
||||
'SCRIPT_FILENAME' => '/path/to/this/script.php',
|
||||
'SERVER_ADMIN' => 'webmaster@blakesimpson.co.uk',
|
||||
'SERVER_PORT' => '80',
|
||||
'SERVER_SIGNATURE' => 'Version signature: 5.123',
|
||||
'SCRIPT_NAME' => '/blog/article.php',
|
||||
'REQUEST_URI' => '/blog/article.php?id=10&user=foo',
|
||||
];
|
||||
|
||||
$_COOKIE = [
|
||||
'logged-in' => 'yes!'
|
||||
];
|
||||
|
||||
$_POST = [
|
||||
'name' => 'Pesho',
|
||||
'email' => 'pesho@example.com',
|
||||
];
|
||||
|
||||
$_GET = [
|
||||
'id' => 10,
|
||||
'user' => 'foo',
|
||||
];
|
||||
|
||||
$_FILES = [
|
||||
'file' => [
|
||||
'name' => 'MyFile.txt',
|
||||
'type' => 'text/plain',
|
||||
'tmp_name' => '/tmp/php/php1h4j1o',
|
||||
'error' => UPLOAD_ERR_OK,
|
||||
'size' => 123,
|
||||
]
|
||||
];
|
||||
|
||||
$server = ServerRequest::fromGlobals();
|
||||
|
||||
$this->assertEquals('POST', $server->getMethod());
|
||||
$this->assertEquals(['Host' => ['www.blakesimpson.co.uk']], $server->getHeaders());
|
||||
$this->assertEquals('', (string) $server->getBody());
|
||||
$this->assertEquals('1.0', $server->getProtocolVersion());
|
||||
$this->assertEquals($_COOKIE, $server->getCookieParams());
|
||||
$this->assertEquals($_POST, $server->getParsedBody());
|
||||
$this->assertEquals($_GET, $server->getQueryParams());
|
||||
|
||||
$this->assertEquals(
|
||||
new Uri('http://www.blakesimpson.co.uk/blog/article.php?id=10&user=foo'),
|
||||
$server->getUri()
|
||||
);
|
||||
|
||||
$expectedFiles = [
|
||||
'file' => new UploadedFile(
|
||||
'/tmp/php/php1h4j1o',
|
||||
123,
|
||||
UPLOAD_ERR_OK,
|
||||
'MyFile.txt',
|
||||
'text/plain'
|
||||
),
|
||||
];
|
||||
|
||||
$this->assertEquals($expectedFiles, $server->getUploadedFiles());
|
||||
}
|
||||
|
||||
public function testUploadedFiles()
|
||||
{
|
||||
$request1 = new ServerRequest('GET', '/');
|
||||
|
||||
$files = [
|
||||
'file' => new UploadedFile('test', 123, UPLOAD_ERR_OK)
|
||||
];
|
||||
|
||||
$request2 = $request1->withUploadedFiles($files);
|
||||
|
||||
$this->assertNotSame($request2, $request1);
|
||||
$this->assertSame([], $request1->getUploadedFiles());
|
||||
$this->assertSame($files, $request2->getUploadedFiles());
|
||||
}
|
||||
|
||||
public function testServerParams()
|
||||
{
|
||||
$params = ['name' => 'value'];
|
||||
|
||||
$request = new ServerRequest('GET', '/', [], null, '1.1', $params);
|
||||
$this->assertSame($params, $request->getServerParams());
|
||||
}
|
||||
|
||||
public function testCookieParams()
|
||||
{
|
||||
$request1 = new ServerRequest('GET', '/');
|
||||
|
||||
$params = ['name' => 'value'];
|
||||
|
||||
$request2 = $request1->withCookieParams($params);
|
||||
|
||||
$this->assertNotSame($request2, $request1);
|
||||
$this->assertEmpty($request1->getCookieParams());
|
||||
$this->assertSame($params, $request2->getCookieParams());
|
||||
}
|
||||
|
||||
public function testQueryParams()
|
||||
{
|
||||
$request1 = new ServerRequest('GET', '/');
|
||||
|
||||
$params = ['name' => 'value'];
|
||||
|
||||
$request2 = $request1->withQueryParams($params);
|
||||
|
||||
$this->assertNotSame($request2, $request1);
|
||||
$this->assertEmpty($request1->getQueryParams());
|
||||
$this->assertSame($params, $request2->getQueryParams());
|
||||
}
|
||||
|
||||
public function testParsedBody()
|
||||
{
|
||||
$request1 = new ServerRequest('GET', '/');
|
||||
|
||||
$params = ['name' => 'value'];
|
||||
|
||||
$request2 = $request1->withParsedBody($params);
|
||||
|
||||
$this->assertNotSame($request2, $request1);
|
||||
$this->assertEmpty($request1->getParsedBody());
|
||||
$this->assertSame($params, $request2->getParsedBody());
|
||||
}
|
||||
|
||||
public function testAttributes()
|
||||
{
|
||||
$request1 = new ServerRequest('GET', '/');
|
||||
|
||||
$request2 = $request1->withAttribute('name', 'value');
|
||||
$request3 = $request2->withAttribute('other', 'otherValue');
|
||||
$request4 = $request3->withoutAttribute('other');
|
||||
$request5 = $request3->withoutAttribute('unknown');
|
||||
|
||||
$this->assertNotSame($request2, $request1);
|
||||
$this->assertNotSame($request3, $request2);
|
||||
$this->assertNotSame($request4, $request3);
|
||||
$this->assertNotSame($request5, $request4);
|
||||
|
||||
$this->assertEmpty($request1->getAttributes());
|
||||
$this->assertEmpty($request1->getAttribute('name'));
|
||||
$this->assertEquals(
|
||||
'something',
|
||||
$request1->getAttribute('name', 'something'),
|
||||
'Should return the default value'
|
||||
);
|
||||
|
||||
$this->assertEquals('value', $request2->getAttribute('name'));
|
||||
$this->assertEquals(['name' => 'value'], $request2->getAttributes());
|
||||
$this->assertEquals(['name' => 'value', 'other' => 'otherValue'], $request3->getAttributes());
|
||||
$this->assertEquals(['name' => 'value'], $request4->getAttributes());
|
||||
}
|
||||
|
||||
public function testNullAttribute()
|
||||
{
|
||||
$request = (new ServerRequest('GET', '/'))->withAttribute('name', null);
|
||||
|
||||
$this->assertSame(['name' => null], $request->getAttributes());
|
||||
$this->assertNull($request->getAttribute('name', 'different-default'));
|
||||
|
||||
$requestWithoutAttribute = $request->withoutAttribute('name');
|
||||
|
||||
$this->assertSame([], $requestWithoutAttribute->getAttributes());
|
||||
$this->assertSame('different-default', $requestWithoutAttribute->getAttribute('name', 'different-default'));
|
||||
}
|
||||
}
|
|
@ -1,137 +0,0 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Tests\Psr7;
|
||||
|
||||
use Psr\Http\Message\StreamInterface;
|
||||
use GuzzleHttp\Psr7;
|
||||
use GuzzleHttp\Psr7\StreamDecoratorTrait;
|
||||
|
||||
class Str implements StreamInterface
|
||||
{
|
||||
use StreamDecoratorTrait;
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers GuzzleHttp\Psr7\StreamDecoratorTrait
|
||||
*/
|
||||
class StreamDecoratorTraitTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
private $a;
|
||||
private $b;
|
||||
private $c;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
$this->c = fopen('php://temp', 'r+');
|
||||
fwrite($this->c, 'foo');
|
||||
fseek($this->c, 0);
|
||||
$this->a = Psr7\stream_for($this->c);
|
||||
$this->b = new Str($this->a);
|
||||
}
|
||||
|
||||
public function testCatchesExceptionsWhenCastingToString()
|
||||
{
|
||||
$s = $this->getMockBuilder('Psr\Http\Message\StreamInterface')
|
||||
->setMethods(['read'])
|
||||
->getMockForAbstractClass();
|
||||
$s->expects($this->once())
|
||||
->method('read')
|
||||
->will($this->throwException(new \Exception('foo')));
|
||||
$msg = '';
|
||||
set_error_handler(function ($errNo, $str) use (&$msg) { $msg = $str; });
|
||||
echo new Str($s);
|
||||
restore_error_handler();
|
||||
$this->assertContains('foo', $msg);
|
||||
}
|
||||
|
||||
public function testToString()
|
||||
{
|
||||
$this->assertEquals('foo', (string) $this->b);
|
||||
}
|
||||
|
||||
public function testHasSize()
|
||||
{
|
||||
$this->assertEquals(3, $this->b->getSize());
|
||||
}
|
||||
|
||||
public function testReads()
|
||||
{
|
||||
$this->assertEquals('foo', $this->b->read(10));
|
||||
}
|
||||
|
||||
public function testCheckMethods()
|
||||
{
|
||||
$this->assertEquals($this->a->isReadable(), $this->b->isReadable());
|
||||
$this->assertEquals($this->a->isWritable(), $this->b->isWritable());
|
||||
$this->assertEquals($this->a->isSeekable(), $this->b->isSeekable());
|
||||
}
|
||||
|
||||
public function testSeeksAndTells()
|
||||
{
|
||||
$this->b->seek(1);
|
||||
$this->assertEquals(1, $this->a->tell());
|
||||
$this->assertEquals(1, $this->b->tell());
|
||||
$this->b->seek(0);
|
||||
$this->assertEquals(0, $this->a->tell());
|
||||
$this->assertEquals(0, $this->b->tell());
|
||||
$this->b->seek(0, SEEK_END);
|
||||
$this->assertEquals(3, $this->a->tell());
|
||||
$this->assertEquals(3, $this->b->tell());
|
||||
}
|
||||
|
||||
public function testGetsContents()
|
||||
{
|
||||
$this->assertEquals('foo', $this->b->getContents());
|
||||
$this->assertEquals('', $this->b->getContents());
|
||||
$this->b->seek(1);
|
||||
$this->assertEquals('oo', $this->b->getContents(1));
|
||||
}
|
||||
|
||||
public function testCloses()
|
||||
{
|
||||
$this->b->close();
|
||||
$this->assertFalse(is_resource($this->c));
|
||||
}
|
||||
|
||||
public function testDetaches()
|
||||
{
|
||||
$this->b->detach();
|
||||
$this->assertFalse($this->b->isReadable());
|
||||
}
|
||||
|
||||
public function testWrapsMetadata()
|
||||
{
|
||||
$this->assertSame($this->b->getMetadata(), $this->a->getMetadata());
|
||||
$this->assertSame($this->b->getMetadata('uri'), $this->a->getMetadata('uri'));
|
||||
}
|
||||
|
||||
public function testWrapsWrites()
|
||||
{
|
||||
$this->b->seek(0, SEEK_END);
|
||||
$this->b->write('foo');
|
||||
$this->assertEquals('foofoo', (string) $this->a);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \UnexpectedValueException
|
||||
*/
|
||||
public function testThrowsWithInvalidGetter()
|
||||
{
|
||||
$this->b->foo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \BadMethodCallException
|
||||
*/
|
||||
public function testThrowsWhenGetterNotImplemented()
|
||||
{
|
||||
$s = new BadStream();
|
||||
$s->stream;
|
||||
}
|
||||
}
|
||||
|
||||
class BadStream
|
||||
{
|
||||
use StreamDecoratorTrait;
|
||||
|
||||
public function __construct() {}
|
||||
}
|
|
@ -1,161 +0,0 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Tests\Psr7;
|
||||
|
||||
use GuzzleHttp\Psr7\NoSeekStream;
|
||||
use GuzzleHttp\Psr7\Stream;
|
||||
|
||||
/**
|
||||
* @covers GuzzleHttp\Psr7\Stream
|
||||
*/
|
||||
class StreamTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* @expectedException \InvalidArgumentException
|
||||
*/
|
||||
public function testConstructorThrowsExceptionOnInvalidArgument()
|
||||
{
|
||||
new Stream(true);
|
||||
}
|
||||
|
||||
public function testConstructorInitializesProperties()
|
||||
{
|
||||
$handle = fopen('php://temp', 'r+');
|
||||
fwrite($handle, 'data');
|
||||
$stream = new Stream($handle);
|
||||
$this->assertTrue($stream->isReadable());
|
||||
$this->assertTrue($stream->isWritable());
|
||||
$this->assertTrue($stream->isSeekable());
|
||||
$this->assertEquals('php://temp', $stream->getMetadata('uri'));
|
||||
$this->assertInternalType('array', $stream->getMetadata());
|
||||
$this->assertEquals(4, $stream->getSize());
|
||||
$this->assertFalse($stream->eof());
|
||||
$stream->close();
|
||||
}
|
||||
|
||||
public function testStreamClosesHandleOnDestruct()
|
||||
{
|
||||
$handle = fopen('php://temp', 'r');
|
||||
$stream = new Stream($handle);
|
||||
unset($stream);
|
||||
$this->assertFalse(is_resource($handle));
|
||||
}
|
||||
|
||||
public function testConvertsToString()
|
||||
{
|
||||
$handle = fopen('php://temp', 'w+');
|
||||
fwrite($handle, 'data');
|
||||
$stream = new Stream($handle);
|
||||
$this->assertEquals('data', (string) $stream);
|
||||
$this->assertEquals('data', (string) $stream);
|
||||
$stream->close();
|
||||
}
|
||||
|
||||
public function testGetsContents()
|
||||
{
|
||||
$handle = fopen('php://temp', 'w+');
|
||||
fwrite($handle, 'data');
|
||||
$stream = new Stream($handle);
|
||||
$this->assertEquals('', $stream->getContents());
|
||||
$stream->seek(0);
|
||||
$this->assertEquals('data', $stream->getContents());
|
||||
$this->assertEquals('', $stream->getContents());
|
||||
}
|
||||
|
||||
public function testChecksEof()
|
||||
{
|
||||
$handle = fopen('php://temp', 'w+');
|
||||
fwrite($handle, 'data');
|
||||
$stream = new Stream($handle);
|
||||
$this->assertFalse($stream->eof());
|
||||
$stream->read(4);
|
||||
$this->assertTrue($stream->eof());
|
||||
$stream->close();
|
||||
}
|
||||
|
||||
public function testGetSize()
|
||||
{
|
||||
$size = filesize(__FILE__);
|
||||
$handle = fopen(__FILE__, 'r');
|
||||
$stream = new Stream($handle);
|
||||
$this->assertEquals($size, $stream->getSize());
|
||||
// Load from cache
|
||||
$this->assertEquals($size, $stream->getSize());
|
||||
$stream->close();
|
||||
}
|
||||
|
||||
public function testEnsuresSizeIsConsistent()
|
||||
{
|
||||
$h = fopen('php://temp', 'w+');
|
||||
$this->assertEquals(3, fwrite($h, 'foo'));
|
||||
$stream = new Stream($h);
|
||||
$this->assertEquals(3, $stream->getSize());
|
||||
$this->assertEquals(4, $stream->write('test'));
|
||||
$this->assertEquals(7, $stream->getSize());
|
||||
$this->assertEquals(7, $stream->getSize());
|
||||
$stream->close();
|
||||
}
|
||||
|
||||
public function testProvidesStreamPosition()
|
||||
{
|
||||
$handle = fopen('php://temp', 'w+');
|
||||
$stream = new Stream($handle);
|
||||
$this->assertEquals(0, $stream->tell());
|
||||
$stream->write('foo');
|
||||
$this->assertEquals(3, $stream->tell());
|
||||
$stream->seek(1);
|
||||
$this->assertEquals(1, $stream->tell());
|
||||
$this->assertSame(ftell($handle), $stream->tell());
|
||||
$stream->close();
|
||||
}
|
||||
|
||||
public function testCanDetachStream()
|
||||
{
|
||||
$r = fopen('php://temp', 'w+');
|
||||
$stream = new Stream($r);
|
||||
$stream->write('foo');
|
||||
$this->assertTrue($stream->isReadable());
|
||||
$this->assertSame($r, $stream->detach());
|
||||
$stream->detach();
|
||||
|
||||
$this->assertFalse($stream->isReadable());
|
||||
$this->assertFalse($stream->isWritable());
|
||||
$this->assertFalse($stream->isSeekable());
|
||||
|
||||
$throws = function (callable $fn) use ($stream) {
|
||||
try {
|
||||
$fn($stream);
|
||||
$this->fail();
|
||||
} catch (\Exception $e) {}
|
||||
};
|
||||
|
||||
$throws(function ($stream) { $stream->read(10); });
|
||||
$throws(function ($stream) { $stream->write('bar'); });
|
||||
$throws(function ($stream) { $stream->seek(10); });
|
||||
$throws(function ($stream) { $stream->tell(); });
|
||||
$throws(function ($stream) { $stream->eof(); });
|
||||
$throws(function ($stream) { $stream->getSize(); });
|
||||
$throws(function ($stream) { $stream->getContents(); });
|
||||
$this->assertSame('', (string) $stream);
|
||||
$stream->close();
|
||||
}
|
||||
|
||||
public function testCloseClearProperties()
|
||||
{
|
||||
$handle = fopen('php://temp', 'r+');
|
||||
$stream = new Stream($handle);
|
||||
$stream->close();
|
||||
|
||||
$this->assertFalse($stream->isSeekable());
|
||||
$this->assertFalse($stream->isReadable());
|
||||
$this->assertFalse($stream->isWritable());
|
||||
$this->assertNull($stream->getSize());
|
||||
$this->assertEmpty($stream->getMetadata());
|
||||
}
|
||||
|
||||
public function testDoesNotThrowInToString()
|
||||
{
|
||||
$s = \GuzzleHttp\Psr7\stream_for('foo');
|
||||
$s = new NoSeekStream($s);
|
||||
$this->assertEquals('foo', (string) $s);
|
||||
}
|
||||
}
|
|
@ -1,102 +0,0 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Tests\Psr7;
|
||||
|
||||
use GuzzleHttp\Psr7\StreamWrapper;
|
||||
use GuzzleHttp\Psr7;
|
||||
|
||||
/**
|
||||
* @covers GuzzleHttp\Psr7\StreamWrapper
|
||||
*/
|
||||
class StreamWrapperTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testResource()
|
||||
{
|
||||
$stream = Psr7\stream_for('foo');
|
||||
$handle = StreamWrapper::getResource($stream);
|
||||
$this->assertSame('foo', fread($handle, 3));
|
||||
$this->assertSame(3, ftell($handle));
|
||||
$this->assertSame(3, fwrite($handle, 'bar'));
|
||||
$this->assertSame(0, fseek($handle, 0));
|
||||
$this->assertSame('foobar', fread($handle, 6));
|
||||
$this->assertSame('', fread($handle, 1));
|
||||
$this->assertTrue(feof($handle));
|
||||
|
||||
$stBlksize = defined('PHP_WINDOWS_VERSION_BUILD') ? -1 : 0;
|
||||
|
||||
// This fails on HHVM for some reason
|
||||
if (!defined('HHVM_VERSION')) {
|
||||
$this->assertEquals([
|
||||
'dev' => 0,
|
||||
'ino' => 0,
|
||||
'mode' => 33206,
|
||||
'nlink' => 0,
|
||||
'uid' => 0,
|
||||
'gid' => 0,
|
||||
'rdev' => 0,
|
||||
'size' => 6,
|
||||
'atime' => 0,
|
||||
'mtime' => 0,
|
||||
'ctime' => 0,
|
||||
'blksize' => $stBlksize,
|
||||
'blocks' => $stBlksize,
|
||||
0 => 0,
|
||||
1 => 0,
|
||||
2 => 33206,
|
||||
3 => 0,
|
||||
4 => 0,
|
||||
5 => 0,
|
||||
6 => 0,
|
||||
7 => 6,
|
||||
8 => 0,
|
||||
9 => 0,
|
||||
10 => 0,
|
||||
11 => $stBlksize,
|
||||
12 => $stBlksize,
|
||||
], fstat($handle));
|
||||
}
|
||||
|
||||
$this->assertTrue(fclose($handle));
|
||||
$this->assertSame('foobar', (string) $stream);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \InvalidArgumentException
|
||||
*/
|
||||
public function testValidatesStream()
|
||||
{
|
||||
$stream = $this->getMockBuilder('Psr\Http\Message\StreamInterface')
|
||||
->setMethods(['isReadable', 'isWritable'])
|
||||
->getMockForAbstractClass();
|
||||
$stream->expects($this->once())
|
||||
->method('isReadable')
|
||||
->will($this->returnValue(false));
|
||||
$stream->expects($this->once())
|
||||
->method('isWritable')
|
||||
->will($this->returnValue(false));
|
||||
StreamWrapper::getResource($stream);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \PHPUnit_Framework_Error_Warning
|
||||
*/
|
||||
public function testReturnsFalseWhenStreamDoesNotExist()
|
||||
{
|
||||
fopen('guzzle://foo', 'r');
|
||||
}
|
||||
|
||||
public function testCanOpenReadonlyStream()
|
||||
{
|
||||
$stream = $this->getMockBuilder('Psr\Http\Message\StreamInterface')
|
||||
->setMethods(['isReadable', 'isWritable'])
|
||||
->getMockForAbstractClass();
|
||||
$stream->expects($this->once())
|
||||
->method('isReadable')
|
||||
->will($this->returnValue(false));
|
||||
$stream->expects($this->once())
|
||||
->method('isWritable')
|
||||
->will($this->returnValue(true));
|
||||
$r = StreamWrapper::getResource($stream);
|
||||
$this->assertInternalType('resource', $r);
|
||||
fclose($r);
|
||||
}
|
||||
}
|
|
@ -1,280 +0,0 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Tests\Psr7;
|
||||
|
||||
use ReflectionProperty;
|
||||
use GuzzleHttp\Psr7\Stream;
|
||||
use GuzzleHttp\Psr7\UploadedFile;
|
||||
|
||||
/**
|
||||
* @covers GuzzleHttp\Psr7\UploadedFile
|
||||
*/
|
||||
class UploadedFileTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
protected $cleanup;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
$this->cleanup = [];
|
||||
}
|
||||
|
||||
public function tearDown()
|
||||
{
|
||||
foreach ($this->cleanup as $file) {
|
||||
if (is_scalar($file) && file_exists($file)) {
|
||||
unlink($file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function invalidStreams()
|
||||
{
|
||||
return [
|
||||
'null' => [null],
|
||||
'true' => [true],
|
||||
'false' => [false],
|
||||
'int' => [1],
|
||||
'float' => [1.1],
|
||||
'array' => [['filename']],
|
||||
'object' => [(object) ['filename']],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider invalidStreams
|
||||
*/
|
||||
public function testRaisesExceptionOnInvalidStreamOrFile($streamOrFile)
|
||||
{
|
||||
$this->setExpectedException('InvalidArgumentException');
|
||||
|
||||
new UploadedFile($streamOrFile, 0, UPLOAD_ERR_OK);
|
||||
}
|
||||
|
||||
public function invalidSizes()
|
||||
{
|
||||
return [
|
||||
'null' => [null],
|
||||
'float' => [1.1],
|
||||
'array' => [[1]],
|
||||
'object' => [(object) [1]],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider invalidSizes
|
||||
*/
|
||||
public function testRaisesExceptionOnInvalidSize($size)
|
||||
{
|
||||
$this->setExpectedException('InvalidArgumentException', 'size');
|
||||
|
||||
new UploadedFile(fopen('php://temp', 'wb+'), $size, UPLOAD_ERR_OK);
|
||||
}
|
||||
|
||||
public function invalidErrorStatuses()
|
||||
{
|
||||
return [
|
||||
'null' => [null],
|
||||
'true' => [true],
|
||||
'false' => [false],
|
||||
'float' => [1.1],
|
||||
'string' => ['1'],
|
||||
'array' => [[1]],
|
||||
'object' => [(object) [1]],
|
||||
'negative' => [-1],
|
||||
'too-big' => [9],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider invalidErrorStatuses
|
||||
*/
|
||||
public function testRaisesExceptionOnInvalidErrorStatus($status)
|
||||
{
|
||||
$this->setExpectedException('InvalidArgumentException', 'status');
|
||||
|
||||
new UploadedFile(fopen('php://temp', 'wb+'), 0, $status);
|
||||
}
|
||||
|
||||
public function invalidFilenamesAndMediaTypes()
|
||||
{
|
||||
return [
|
||||
'true' => [true],
|
||||
'false' => [false],
|
||||
'int' => [1],
|
||||
'float' => [1.1],
|
||||
'array' => [['string']],
|
||||
'object' => [(object) ['string']],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider invalidFilenamesAndMediaTypes
|
||||
*/
|
||||
public function testRaisesExceptionOnInvalidClientFilename($filename)
|
||||
{
|
||||
$this->setExpectedException('InvalidArgumentException', 'filename');
|
||||
|
||||
new UploadedFile(fopen('php://temp', 'wb+'), 0, UPLOAD_ERR_OK, $filename);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider invalidFilenamesAndMediaTypes
|
||||
*/
|
||||
public function testRaisesExceptionOnInvalidClientMediaType($mediaType)
|
||||
{
|
||||
$this->setExpectedException('InvalidArgumentException', 'media type');
|
||||
|
||||
new UploadedFile(fopen('php://temp', 'wb+'), 0, UPLOAD_ERR_OK, 'foobar.baz', $mediaType);
|
||||
}
|
||||
|
||||
public function testGetStreamReturnsOriginalStreamObject()
|
||||
{
|
||||
$stream = new Stream(fopen('php://temp', 'r'));
|
||||
$upload = new UploadedFile($stream, 0, UPLOAD_ERR_OK);
|
||||
|
||||
$this->assertSame($stream, $upload->getStream());
|
||||
}
|
||||
|
||||
public function testGetStreamReturnsWrappedPhpStream()
|
||||
{
|
||||
$stream = fopen('php://temp', 'wb+');
|
||||
$upload = new UploadedFile($stream, 0, UPLOAD_ERR_OK);
|
||||
$uploadStream = $upload->getStream()->detach();
|
||||
|
||||
$this->assertSame($stream, $uploadStream);
|
||||
}
|
||||
|
||||
public function testGetStreamReturnsStreamForFile()
|
||||
{
|
||||
$this->cleanup[] = $stream = tempnam(sys_get_temp_dir(), 'stream_file');
|
||||
$upload = new UploadedFile($stream, 0, UPLOAD_ERR_OK);
|
||||
$uploadStream = $upload->getStream();
|
||||
$r = new ReflectionProperty($uploadStream, 'filename');
|
||||
$r->setAccessible(true);
|
||||
|
||||
$this->assertSame($stream, $r->getValue($uploadStream));
|
||||
}
|
||||
|
||||
public function testSuccessful()
|
||||
{
|
||||
$stream = \GuzzleHttp\Psr7\stream_for('Foo bar!');
|
||||
$upload = new UploadedFile($stream, $stream->getSize(), UPLOAD_ERR_OK, 'filename.txt', 'text/plain');
|
||||
|
||||
$this->assertEquals($stream->getSize(), $upload->getSize());
|
||||
$this->assertEquals('filename.txt', $upload->getClientFilename());
|
||||
$this->assertEquals('text/plain', $upload->getClientMediaType());
|
||||
|
||||
$this->cleanup[] = $to = tempnam(sys_get_temp_dir(), 'successful');
|
||||
$upload->moveTo($to);
|
||||
$this->assertFileExists($to);
|
||||
$this->assertEquals($stream->__toString(), file_get_contents($to));
|
||||
}
|
||||
|
||||
public function invalidMovePaths()
|
||||
{
|
||||
return [
|
||||
'null' => [null],
|
||||
'true' => [true],
|
||||
'false' => [false],
|
||||
'int' => [1],
|
||||
'float' => [1.1],
|
||||
'empty' => [''],
|
||||
'array' => [['filename']],
|
||||
'object' => [(object) ['filename']],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider invalidMovePaths
|
||||
*/
|
||||
public function testMoveRaisesExceptionForInvalidPath($path)
|
||||
{
|
||||
$stream = \GuzzleHttp\Psr7\stream_for('Foo bar!');
|
||||
$upload = new UploadedFile($stream, 0, UPLOAD_ERR_OK);
|
||||
|
||||
$this->cleanup[] = $path;
|
||||
|
||||
$this->setExpectedException('InvalidArgumentException', 'path');
|
||||
$upload->moveTo($path);
|
||||
}
|
||||
|
||||
public function testMoveCannotBeCalledMoreThanOnce()
|
||||
{
|
||||
$stream = \GuzzleHttp\Psr7\stream_for('Foo bar!');
|
||||
$upload = new UploadedFile($stream, 0, UPLOAD_ERR_OK);
|
||||
|
||||
$this->cleanup[] = $to = tempnam(sys_get_temp_dir(), 'diac');
|
||||
$upload->moveTo($to);
|
||||
$this->assertTrue(file_exists($to));
|
||||
|
||||
$this->setExpectedException('RuntimeException', 'moved');
|
||||
$upload->moveTo($to);
|
||||
}
|
||||
|
||||
public function testCannotRetrieveStreamAfterMove()
|
||||
{
|
||||
$stream = \GuzzleHttp\Psr7\stream_for('Foo bar!');
|
||||
$upload = new UploadedFile($stream, 0, UPLOAD_ERR_OK);
|
||||
|
||||
$this->cleanup[] = $to = tempnam(sys_get_temp_dir(), 'diac');
|
||||
$upload->moveTo($to);
|
||||
$this->assertFileExists($to);
|
||||
|
||||
$this->setExpectedException('RuntimeException', 'moved');
|
||||
$upload->getStream();
|
||||
}
|
||||
|
||||
public function nonOkErrorStatus()
|
||||
{
|
||||
return [
|
||||
'UPLOAD_ERR_INI_SIZE' => [ UPLOAD_ERR_INI_SIZE ],
|
||||
'UPLOAD_ERR_FORM_SIZE' => [ UPLOAD_ERR_FORM_SIZE ],
|
||||
'UPLOAD_ERR_PARTIAL' => [ UPLOAD_ERR_PARTIAL ],
|
||||
'UPLOAD_ERR_NO_FILE' => [ UPLOAD_ERR_NO_FILE ],
|
||||
'UPLOAD_ERR_NO_TMP_DIR' => [ UPLOAD_ERR_NO_TMP_DIR ],
|
||||
'UPLOAD_ERR_CANT_WRITE' => [ UPLOAD_ERR_CANT_WRITE ],
|
||||
'UPLOAD_ERR_EXTENSION' => [ UPLOAD_ERR_EXTENSION ],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider nonOkErrorStatus
|
||||
*/
|
||||
public function testConstructorDoesNotRaiseExceptionForInvalidStreamWhenErrorStatusPresent($status)
|
||||
{
|
||||
$uploadedFile = new UploadedFile('not ok', 0, $status);
|
||||
$this->assertSame($status, $uploadedFile->getError());
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider nonOkErrorStatus
|
||||
*/
|
||||
public function testMoveToRaisesExceptionWhenErrorStatusPresent($status)
|
||||
{
|
||||
$uploadedFile = new UploadedFile('not ok', 0, $status);
|
||||
$this->setExpectedException('RuntimeException', 'upload error');
|
||||
$uploadedFile->moveTo(__DIR__ . '/' . uniqid());
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider nonOkErrorStatus
|
||||
*/
|
||||
public function testGetStreamRaisesExceptionWhenErrorStatusPresent($status)
|
||||
{
|
||||
$uploadedFile = new UploadedFile('not ok', 0, $status);
|
||||
$this->setExpectedException('RuntimeException', 'upload error');
|
||||
$stream = $uploadedFile->getStream();
|
||||
}
|
||||
|
||||
public function testMoveToCreatesStreamIfOnlyAFilenameWasProvided()
|
||||
{
|
||||
$this->cleanup[] = $from = tempnam(sys_get_temp_dir(), 'copy_from');
|
||||
$this->cleanup[] = $to = tempnam(sys_get_temp_dir(), 'copy_to');
|
||||
|
||||
copy(__FILE__, $from);
|
||||
|
||||
$uploadedFile = new UploadedFile($from, 100, UPLOAD_ERR_OK, basename($from), 'text/plain');
|
||||
$uploadedFile->moveTo($to);
|
||||
|
||||
$this->assertFileEquals(__FILE__, $to);
|
||||
}
|
||||
}
|
|
@ -1,573 +0,0 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Tests\Psr7;
|
||||
|
||||
use GuzzleHttp\Psr7\Uri;
|
||||
|
||||
/**
|
||||
* @covers GuzzleHttp\Psr7\Uri
|
||||
*/
|
||||
class UriTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
const RFC3986_BASE = 'http://a/b/c/d;p?q';
|
||||
|
||||
public function testParsesProvidedUri()
|
||||
{
|
||||
$uri = new Uri('https://user:pass@example.com:8080/path/123?q=abc#test');
|
||||
|
||||
$this->assertSame('https', $uri->getScheme());
|
||||
$this->assertSame('user:pass@example.com:8080', $uri->getAuthority());
|
||||
$this->assertSame('user:pass', $uri->getUserInfo());
|
||||
$this->assertSame('example.com', $uri->getHost());
|
||||
$this->assertSame(8080, $uri->getPort());
|
||||
$this->assertSame('/path/123', $uri->getPath());
|
||||
$this->assertSame('q=abc', $uri->getQuery());
|
||||
$this->assertSame('test', $uri->getFragment());
|
||||
$this->assertSame('https://user:pass@example.com:8080/path/123?q=abc#test', (string) $uri);
|
||||
}
|
||||
|
||||
public function testCanTransformAndRetrievePartsIndividually()
|
||||
{
|
||||
$uri = (new Uri())
|
||||
->withScheme('https')
|
||||
->withUserInfo('user', 'pass')
|
||||
->withHost('example.com')
|
||||
->withPort(8080)
|
||||
->withPath('/path/123')
|
||||
->withQuery('q=abc')
|
||||
->withFragment('test');
|
||||
|
||||
$this->assertSame('https', $uri->getScheme());
|
||||
$this->assertSame('user:pass@example.com:8080', $uri->getAuthority());
|
||||
$this->assertSame('user:pass', $uri->getUserInfo());
|
||||
$this->assertSame('example.com', $uri->getHost());
|
||||
$this->assertSame(8080, $uri->getPort());
|
||||
$this->assertSame('/path/123', $uri->getPath());
|
||||
$this->assertSame('q=abc', $uri->getQuery());
|
||||
$this->assertSame('test', $uri->getFragment());
|
||||
$this->assertSame('https://user:pass@example.com:8080/path/123?q=abc#test', (string) $uri);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getValidUris
|
||||
*/
|
||||
public function testValidUrisStayValid($input)
|
||||
{
|
||||
$uri = new Uri($input);
|
||||
|
||||
$this->assertSame($input, (string) $uri);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getValidUris
|
||||
*/
|
||||
public function testFromParts($input)
|
||||
{
|
||||
$uri = Uri::fromParts(parse_url($input));
|
||||
|
||||
$this->assertSame($input, (string) $uri);
|
||||
}
|
||||
|
||||
public function getValidUris()
|
||||
{
|
||||
return [
|
||||
['urn:path-rootless'],
|
||||
['urn:path:with:colon'],
|
||||
['urn:/path-absolute'],
|
||||
['urn:/'],
|
||||
// only scheme with empty path
|
||||
['urn:'],
|
||||
// only path
|
||||
['/'],
|
||||
['relative/'],
|
||||
['0'],
|
||||
// same document reference
|
||||
[''],
|
||||
// network path without scheme
|
||||
['//example.org'],
|
||||
['//example.org/'],
|
||||
['//example.org?q#h'],
|
||||
// only query
|
||||
['?q'],
|
||||
['?q=abc&foo=bar'],
|
||||
// only fragment
|
||||
['#fragment'],
|
||||
// dot segments are not removed automatically
|
||||
['./foo/../bar'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \InvalidArgumentException
|
||||
* @expectedExceptionMessage Unable to parse URI
|
||||
* @dataProvider getInvalidUris
|
||||
*/
|
||||
public function testInvalidUrisThrowException($invalidUri)
|
||||
{
|
||||
new Uri($invalidUri);
|
||||
}
|
||||
|
||||
public function getInvalidUris()
|
||||
{
|
||||
return [
|
||||
// parse_url() requires the host component which makes sense for http(s)
|
||||
// but not when the scheme is not known or different. So '//' or '///' is
|
||||
// currently invalid as well but should not according to RFC 3986.
|
||||
['http://'],
|
||||
['urn://host:with:colon'], // host cannot contain ":"
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \InvalidArgumentException
|
||||
* @expectedExceptionMessage Invalid port: 100000. Must be between 1 and 65535
|
||||
*/
|
||||
public function testPortMustBeValid()
|
||||
{
|
||||
(new Uri())->withPort(100000);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \InvalidArgumentException
|
||||
* @expectedExceptionMessage Invalid port: 0. Must be between 1 and 65535
|
||||
*/
|
||||
public function testWithPortCannotBeZero()
|
||||
{
|
||||
(new Uri())->withPort(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \InvalidArgumentException
|
||||
* @expectedExceptionMessage Unable to parse URI
|
||||
*/
|
||||
public function testParseUriPortCannotBeZero()
|
||||
{
|
||||
new Uri('//example.com:0');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \InvalidArgumentException
|
||||
*/
|
||||
public function testSchemeMustHaveCorrectType()
|
||||
{
|
||||
(new Uri())->withScheme([]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \InvalidArgumentException
|
||||
*/
|
||||
public function testHostMustHaveCorrectType()
|
||||
{
|
||||
(new Uri())->withHost([]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \InvalidArgumentException
|
||||
*/
|
||||
public function testPathMustHaveCorrectType()
|
||||
{
|
||||
(new Uri())->withPath([]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \InvalidArgumentException
|
||||
*/
|
||||
public function testQueryMustHaveCorrectType()
|
||||
{
|
||||
(new Uri())->withQuery([]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \InvalidArgumentException
|
||||
*/
|
||||
public function testFragmentMustHaveCorrectType()
|
||||
{
|
||||
(new Uri())->withFragment([]);
|
||||
}
|
||||
|
||||
public function testCanParseFalseyUriParts()
|
||||
{
|
||||
$uri = new Uri('0://0:0@0/0?0#0');
|
||||
|
||||
$this->assertSame('0', $uri->getScheme());
|
||||
$this->assertSame('0:0@0', $uri->getAuthority());
|
||||
$this->assertSame('0:0', $uri->getUserInfo());
|
||||
$this->assertSame('0', $uri->getHost());
|
||||
$this->assertSame('/0', $uri->getPath());
|
||||
$this->assertSame('0', $uri->getQuery());
|
||||
$this->assertSame('0', $uri->getFragment());
|
||||
$this->assertSame('0://0:0@0/0?0#0', (string) $uri);
|
||||
}
|
||||
|
||||
public function testCanConstructFalseyUriParts()
|
||||
{
|
||||
$uri = (new Uri())
|
||||
->withScheme('0')
|
||||
->withUserInfo('0', '0')
|
||||
->withHost('0')
|
||||
->withPath('/0')
|
||||
->withQuery('0')
|
||||
->withFragment('0');
|
||||
|
||||
$this->assertSame('0', $uri->getScheme());
|
||||
$this->assertSame('0:0@0', $uri->getAuthority());
|
||||
$this->assertSame('0:0', $uri->getUserInfo());
|
||||
$this->assertSame('0', $uri->getHost());
|
||||
$this->assertSame('/0', $uri->getPath());
|
||||
$this->assertSame('0', $uri->getQuery());
|
||||
$this->assertSame('0', $uri->getFragment());
|
||||
$this->assertSame('0://0:0@0/0?0#0', (string) $uri);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getResolveTestCases
|
||||
*/
|
||||
public function testResolvesUris($base, $rel, $expected)
|
||||
{
|
||||
$uri = new Uri($base);
|
||||
$actual = Uri::resolve($uri, $rel);
|
||||
$this->assertSame($expected, (string) $actual);
|
||||
}
|
||||
|
||||
public function getResolveTestCases()
|
||||
{
|
||||
return [
|
||||
[self::RFC3986_BASE, 'g:h', 'g:h'],
|
||||
[self::RFC3986_BASE, 'g', 'http://a/b/c/g'],
|
||||
[self::RFC3986_BASE, './g', 'http://a/b/c/g'],
|
||||
[self::RFC3986_BASE, 'g/', 'http://a/b/c/g/'],
|
||||
[self::RFC3986_BASE, '/g', 'http://a/g'],
|
||||
[self::RFC3986_BASE, '//g', 'http://g'],
|
||||
[self::RFC3986_BASE, '?y', 'http://a/b/c/d;p?y'],
|
||||
[self::RFC3986_BASE, 'g?y', 'http://a/b/c/g?y'],
|
||||
[self::RFC3986_BASE, '#s', 'http://a/b/c/d;p?q#s'],
|
||||
[self::RFC3986_BASE, 'g#s', 'http://a/b/c/g#s'],
|
||||
[self::RFC3986_BASE, 'g?y#s', 'http://a/b/c/g?y#s'],
|
||||
[self::RFC3986_BASE, ';x', 'http://a/b/c/;x'],
|
||||
[self::RFC3986_BASE, 'g;x', 'http://a/b/c/g;x'],
|
||||
[self::RFC3986_BASE, 'g;x?y#s', 'http://a/b/c/g;x?y#s'],
|
||||
[self::RFC3986_BASE, '', self::RFC3986_BASE],
|
||||
[self::RFC3986_BASE, '.', 'http://a/b/c/'],
|
||||
[self::RFC3986_BASE, './', 'http://a/b/c/'],
|
||||
[self::RFC3986_BASE, '..', 'http://a/b/'],
|
||||
[self::RFC3986_BASE, '../', 'http://a/b/'],
|
||||
[self::RFC3986_BASE, '../g', 'http://a/b/g'],
|
||||
[self::RFC3986_BASE, '../..', 'http://a/'],
|
||||
[self::RFC3986_BASE, '../../', 'http://a/'],
|
||||
[self::RFC3986_BASE, '../../g', 'http://a/g'],
|
||||
[self::RFC3986_BASE, '../../../g', 'http://a/g'],
|
||||
[self::RFC3986_BASE, '../../../../g', 'http://a/g'],
|
||||
[self::RFC3986_BASE, '/./g', 'http://a/g'],
|
||||
[self::RFC3986_BASE, '/../g', 'http://a/g'],
|
||||
[self::RFC3986_BASE, 'g.', 'http://a/b/c/g.'],
|
||||
[self::RFC3986_BASE, '.g', 'http://a/b/c/.g'],
|
||||
[self::RFC3986_BASE, 'g..', 'http://a/b/c/g..'],
|
||||
[self::RFC3986_BASE, '..g', 'http://a/b/c/..g'],
|
||||
[self::RFC3986_BASE, './../g', 'http://a/b/g'],
|
||||
[self::RFC3986_BASE, 'foo////g', 'http://a/b/c/foo////g'],
|
||||
[self::RFC3986_BASE, './g/.', 'http://a/b/c/g/'],
|
||||
[self::RFC3986_BASE, 'g/./h', 'http://a/b/c/g/h'],
|
||||
[self::RFC3986_BASE, 'g/../h', 'http://a/b/c/h'],
|
||||
[self::RFC3986_BASE, 'g;x=1/./y', 'http://a/b/c/g;x=1/y'],
|
||||
[self::RFC3986_BASE, 'g;x=1/../y', 'http://a/b/c/y'],
|
||||
// dot-segments in the query or fragment
|
||||
[self::RFC3986_BASE, 'g?y/./x', 'http://a/b/c/g?y/./x'],
|
||||
[self::RFC3986_BASE, 'g?y/../x', 'http://a/b/c/g?y/../x'],
|
||||
[self::RFC3986_BASE, 'g#s/./x', 'http://a/b/c/g#s/./x'],
|
||||
[self::RFC3986_BASE, 'g#s/../x', 'http://a/b/c/g#s/../x'],
|
||||
[self::RFC3986_BASE, 'g#s/../x', 'http://a/b/c/g#s/../x'],
|
||||
[self::RFC3986_BASE, '?y#s', 'http://a/b/c/d;p?y#s'],
|
||||
['http://a/b/c/d;p?q#s', '?y', 'http://a/b/c/d;p?y'],
|
||||
['http://u@a/b/c/d;p?q', '.', 'http://u@a/b/c/'],
|
||||
['http://u:p@a/b/c/d;p?q', '.', 'http://u:p@a/b/c/'],
|
||||
['http://a/b/c/d/', 'e', 'http://a/b/c/d/e'],
|
||||
['urn:no-slash', 'e', 'urn:e'],
|
||||
// falsey relative parts
|
||||
[self::RFC3986_BASE, '//0', 'http://0'],
|
||||
[self::RFC3986_BASE, '0', 'http://a/b/c/0'],
|
||||
[self::RFC3986_BASE, '?0', 'http://a/b/c/d;p?0'],
|
||||
[self::RFC3986_BASE, '#0', 'http://a/b/c/d;p?q#0'],
|
||||
];
|
||||
}
|
||||
|
||||
public function testAddAndRemoveQueryValues()
|
||||
{
|
||||
$uri = new Uri();
|
||||
$uri = Uri::withQueryValue($uri, 'a', 'b');
|
||||
$uri = Uri::withQueryValue($uri, 'c', 'd');
|
||||
$uri = Uri::withQueryValue($uri, 'e', null);
|
||||
$this->assertSame('a=b&c=d&e', $uri->getQuery());
|
||||
|
||||
$uri = Uri::withoutQueryValue($uri, 'c');
|
||||
$this->assertSame('a=b&e', $uri->getQuery());
|
||||
$uri = Uri::withoutQueryValue($uri, 'e');
|
||||
$this->assertSame('a=b', $uri->getQuery());
|
||||
$uri = Uri::withoutQueryValue($uri, 'a');
|
||||
$this->assertSame('', $uri->getQuery());
|
||||
}
|
||||
|
||||
public function testWithQueryValueReplacesSameKeys()
|
||||
{
|
||||
$uri = new Uri();
|
||||
$uri = Uri::withQueryValue($uri, 'a', 'b');
|
||||
$uri = Uri::withQueryValue($uri, 'c', 'd');
|
||||
$uri = Uri::withQueryValue($uri, 'a', 'e');
|
||||
$this->assertSame('c=d&a=e', $uri->getQuery());
|
||||
}
|
||||
|
||||
public function testWithoutQueryValueRemovesAllSameKeys()
|
||||
{
|
||||
$uri = (new Uri())->withQuery('a=b&c=d&a=e');
|
||||
$uri = Uri::withoutQueryValue($uri, 'a');
|
||||
$this->assertSame('c=d', $uri->getQuery());
|
||||
}
|
||||
|
||||
public function testRemoveNonExistingQueryValue()
|
||||
{
|
||||
$uri = new Uri();
|
||||
$uri = Uri::withQueryValue($uri, 'a', 'b');
|
||||
$uri = Uri::withoutQueryValue($uri, 'c');
|
||||
$this->assertSame('a=b', $uri->getQuery());
|
||||
}
|
||||
|
||||
public function testWithQueryValueHandlesEncoding()
|
||||
{
|
||||
$uri = new Uri();
|
||||
$uri = Uri::withQueryValue($uri, 'E=mc^2', 'ein&stein');
|
||||
$this->assertSame('E%3Dmc%5E2=ein%26stein', $uri->getQuery(), 'Decoded key/value get encoded');
|
||||
|
||||
$uri = new Uri();
|
||||
$uri = Uri::withQueryValue($uri, 'E%3Dmc%5e2', 'ein%26stein');
|
||||
$this->assertSame('E%3Dmc%5e2=ein%26stein', $uri->getQuery(), 'Encoded key/value do not get double-encoded');
|
||||
}
|
||||
|
||||
public function testWithoutQueryValueHandlesEncoding()
|
||||
{
|
||||
// It also tests that the case of the percent-encoding does not matter,
|
||||
// i.e. both lowercase "%3d" and uppercase "%5E" can be removed.
|
||||
$uri = (new Uri())->withQuery('E%3dmc%5E2=einstein&foo=bar');
|
||||
$uri = Uri::withoutQueryValue($uri, 'E=mc^2');
|
||||
$this->assertSame('foo=bar', $uri->getQuery(), 'Handles key in decoded form');
|
||||
|
||||
$uri = (new Uri())->withQuery('E%3dmc%5E2=einstein&foo=bar');
|
||||
$uri = Uri::withoutQueryValue($uri, 'E%3Dmc%5e2');
|
||||
$this->assertSame('foo=bar', $uri->getQuery(), 'Handles key in encoded form');
|
||||
}
|
||||
|
||||
public function testSchemeIsNormalizedToLowercase()
|
||||
{
|
||||
$uri = new Uri('HTTP://example.com');
|
||||
|
||||
$this->assertSame('http', $uri->getScheme());
|
||||
$this->assertSame('http://example.com', (string) $uri);
|
||||
|
||||
$uri = (new Uri('//example.com'))->withScheme('HTTP');
|
||||
|
||||
$this->assertSame('http', $uri->getScheme());
|
||||
$this->assertSame('http://example.com', (string) $uri);
|
||||
}
|
||||
|
||||
public function testHostIsNormalizedToLowercase()
|
||||
{
|
||||
$uri = new Uri('//eXaMpLe.CoM');
|
||||
|
||||
$this->assertSame('example.com', $uri->getHost());
|
||||
$this->assertSame('//example.com', (string) $uri);
|
||||
|
||||
$uri = (new Uri())->withHost('eXaMpLe.CoM');
|
||||
|
||||
$this->assertSame('example.com', $uri->getHost());
|
||||
$this->assertSame('//example.com', (string) $uri);
|
||||
}
|
||||
|
||||
public function testPortIsNullIfStandardPortForScheme()
|
||||
{
|
||||
// HTTPS standard port
|
||||
$uri = new Uri('https://example.com:443');
|
||||
$this->assertNull($uri->getPort());
|
||||
$this->assertSame('example.com', $uri->getAuthority());
|
||||
|
||||
$uri = (new Uri('https://example.com'))->withPort(443);
|
||||
$this->assertNull($uri->getPort());
|
||||
$this->assertSame('example.com', $uri->getAuthority());
|
||||
|
||||
// HTTP standard port
|
||||
$uri = new Uri('http://example.com:80');
|
||||
$this->assertNull($uri->getPort());
|
||||
$this->assertSame('example.com', $uri->getAuthority());
|
||||
|
||||
$uri = (new Uri('http://example.com'))->withPort(80);
|
||||
$this->assertNull($uri->getPort());
|
||||
$this->assertSame('example.com', $uri->getAuthority());
|
||||
}
|
||||
|
||||
public function testPortIsReturnedIfSchemeUnknown()
|
||||
{
|
||||
$uri = (new Uri('//example.com'))->withPort(80);
|
||||
|
||||
$this->assertSame(80, $uri->getPort());
|
||||
$this->assertSame('example.com:80', $uri->getAuthority());
|
||||
}
|
||||
|
||||
public function testStandardPortIsNullIfSchemeChanges()
|
||||
{
|
||||
$uri = new Uri('http://example.com:443');
|
||||
$this->assertSame('http', $uri->getScheme());
|
||||
$this->assertSame(443, $uri->getPort());
|
||||
|
||||
$uri = $uri->withScheme('https');
|
||||
$this->assertNull($uri->getPort());
|
||||
}
|
||||
|
||||
public function testPortPassedAsStringIsCastedToInt()
|
||||
{
|
||||
$uri = (new Uri('//example.com'))->withPort('8080');
|
||||
|
||||
$this->assertSame(8080, $uri->getPort(), 'Port is returned as integer');
|
||||
$this->assertSame('example.com:8080', $uri->getAuthority());
|
||||
}
|
||||
|
||||
public function testPortCanBeRemoved()
|
||||
{
|
||||
$uri = (new Uri('http://example.com:8080'))->withPort(null);
|
||||
|
||||
$this->assertNull($uri->getPort());
|
||||
$this->assertSame('http://example.com', (string) $uri);
|
||||
}
|
||||
|
||||
public function testAuthorityWithUserInfoButWithoutHost()
|
||||
{
|
||||
$uri = (new Uri())->withUserInfo('user', 'pass');
|
||||
|
||||
$this->assertSame('user:pass', $uri->getUserInfo());
|
||||
$this->assertSame('', $uri->getAuthority());
|
||||
}
|
||||
|
||||
public function uriComponentsEncodingProvider()
|
||||
{
|
||||
$unreserved = 'a-zA-Z0-9.-_~!$&\'()*+,;=:@';
|
||||
|
||||
return [
|
||||
// Percent encode spaces
|
||||
['/pa th?q=va lue#frag ment', '/pa%20th', 'q=va%20lue', 'frag%20ment', '/pa%20th?q=va%20lue#frag%20ment'],
|
||||
// Percent encode multibyte
|
||||
['/€?€#€', '/%E2%82%AC', '%E2%82%AC', '%E2%82%AC', '/%E2%82%AC?%E2%82%AC#%E2%82%AC'],
|
||||
// Don't encode something that's already encoded
|
||||
['/pa%20th?q=va%20lue#frag%20ment', '/pa%20th', 'q=va%20lue', 'frag%20ment', '/pa%20th?q=va%20lue#frag%20ment'],
|
||||
// Percent encode invalid percent encodings
|
||||
['/pa%2-th?q=va%2-lue#frag%2-ment', '/pa%252-th', 'q=va%252-lue', 'frag%252-ment', '/pa%252-th?q=va%252-lue#frag%252-ment'],
|
||||
// Don't encode path segments
|
||||
['/pa/th//two?q=va/lue#frag/ment', '/pa/th//two', 'q=va/lue', 'frag/ment', '/pa/th//two?q=va/lue#frag/ment'],
|
||||
// Don't encode unreserved chars or sub-delimiters
|
||||
["/$unreserved?$unreserved#$unreserved", "/$unreserved", $unreserved, $unreserved, "/$unreserved?$unreserved#$unreserved"],
|
||||
// Encoded unreserved chars are not decoded
|
||||
['/p%61th?q=v%61lue#fr%61gment', '/p%61th', 'q=v%61lue', 'fr%61gment', '/p%61th?q=v%61lue#fr%61gment'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider uriComponentsEncodingProvider
|
||||
*/
|
||||
public function testUriComponentsGetEncodedProperly($input, $path, $query, $fragment, $output)
|
||||
{
|
||||
$uri = new Uri($input);
|
||||
$this->assertSame($path, $uri->getPath());
|
||||
$this->assertSame($query, $uri->getQuery());
|
||||
$this->assertSame($fragment, $uri->getFragment());
|
||||
$this->assertSame($output, (string) $uri);
|
||||
}
|
||||
|
||||
public function testWithPathEncodesProperly()
|
||||
{
|
||||
$uri = (new Uri())->withPath('/baz?#€/b%61r');
|
||||
// Query and fragment delimiters and multibyte chars are encoded.
|
||||
$this->assertSame('/baz%3F%23%E2%82%AC/b%61r', $uri->getPath());
|
||||
$this->assertSame('/baz%3F%23%E2%82%AC/b%61r', (string) $uri);
|
||||
}
|
||||
|
||||
public function testWithQueryEncodesProperly()
|
||||
{
|
||||
$uri = (new Uri())->withQuery('?=#&€=/&b%61r');
|
||||
// A query starting with a "?" is valid and must not be magically removed. Otherwise it would be impossible to
|
||||
// construct such an URI. Also the "?" and "/" does not need to be encoded in the query.
|
||||
$this->assertSame('?=%23&%E2%82%AC=/&b%61r', $uri->getQuery());
|
||||
$this->assertSame('??=%23&%E2%82%AC=/&b%61r', (string) $uri);
|
||||
}
|
||||
|
||||
public function testWithFragmentEncodesProperly()
|
||||
{
|
||||
$uri = (new Uri())->withFragment('#€?/b%61r');
|
||||
// A fragment starting with a "#" is valid and must not be magically removed. Otherwise it would be impossible to
|
||||
// construct such an URI. Also the "?" and "/" does not need to be encoded in the fragment.
|
||||
$this->assertSame('%23%E2%82%AC?/b%61r', $uri->getFragment());
|
||||
$this->assertSame('#%23%E2%82%AC?/b%61r', (string) $uri);
|
||||
}
|
||||
|
||||
public function testAllowsForRelativeUri()
|
||||
{
|
||||
$uri = (new Uri)->withPath('foo');
|
||||
$this->assertSame('foo', $uri->getPath());
|
||||
$this->assertSame('foo', (string) $uri);
|
||||
}
|
||||
|
||||
public function testAddsSlashForRelativeUriStringWithHost()
|
||||
{
|
||||
// If the path is rootless and an authority is present, the path MUST
|
||||
// be prefixed by "/".
|
||||
$uri = (new Uri)->withPath('foo')->withHost('example.com');
|
||||
$this->assertSame('foo', $uri->getPath());
|
||||
// concatenating a relative path with a host doesn't work: "//example.comfoo" would be wrong
|
||||
$this->assertSame('//example.com/foo', (string) $uri);
|
||||
}
|
||||
|
||||
public function testRemoveExtraSlashesWihoutHost()
|
||||
{
|
||||
// If the path is starting with more than one "/" and no authority is
|
||||
// present, the starting slashes MUST be reduced to one.
|
||||
$uri = (new Uri)->withPath('//foo');
|
||||
$this->assertSame('//foo', $uri->getPath());
|
||||
// URI "//foo" would be interpreted as network reference and thus change the original path to the host
|
||||
$this->assertSame('/foo', (string) $uri);
|
||||
}
|
||||
|
||||
public function testDefaultReturnValuesOfGetters()
|
||||
{
|
||||
$uri = new Uri();
|
||||
|
||||
$this->assertSame('', $uri->getScheme());
|
||||
$this->assertSame('', $uri->getAuthority());
|
||||
$this->assertSame('', $uri->getUserInfo());
|
||||
$this->assertSame('', $uri->getHost());
|
||||
$this->assertNull($uri->getPort());
|
||||
$this->assertSame('', $uri->getPath());
|
||||
$this->assertSame('', $uri->getQuery());
|
||||
$this->assertSame('', $uri->getFragment());
|
||||
}
|
||||
|
||||
public function testImmutability()
|
||||
{
|
||||
$uri = new Uri();
|
||||
|
||||
$this->assertNotSame($uri, $uri->withScheme('https'));
|
||||
$this->assertNotSame($uri, $uri->withUserInfo('user', 'pass'));
|
||||
$this->assertNotSame($uri, $uri->withHost('example.com'));
|
||||
$this->assertNotSame($uri, $uri->withPort(8080));
|
||||
$this->assertNotSame($uri, $uri->withPath('/path/123'));
|
||||
$this->assertNotSame($uri, $uri->withQuery('q=abc'));
|
||||
$this->assertNotSame($uri, $uri->withFragment('test'));
|
||||
}
|
||||
|
||||
public function testExtendingClassesInstantiates()
|
||||
{
|
||||
// The non-standard port triggers a cascade of private methods which
|
||||
// should not use late static binding to access private static members.
|
||||
// If they do, this will fatal.
|
||||
$this->assertInstanceOf(
|
||||
'\GuzzleHttp\Tests\Psr7\ExtendingClassTest',
|
||||
new ExtendingClassTest('http://h:9/')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ExtendingClassTest extends \GuzzleHttp\Psr7\Uri
|
||||
{
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Tests\Psr7;
|
||||
|
||||
require __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
class HasToString
|
||||
{
|
||||
public function __toString() {
|
||||
return 'foo';
|
||||
}
|
||||
}
|
5
tests/integration/vendor/ralouphie/getallheaders/.gitignore
vendored
Normal file
5
tests/integration/vendor/ralouphie/getallheaders/.gitignore
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
.idea
|
||||
.DS_store
|
||||
/vendor/
|
||||
composer.phar
|
||||
composer.lock
|
18
tests/integration/vendor/ralouphie/getallheaders/.travis.yml
vendored
Normal file
18
tests/integration/vendor/ralouphie/getallheaders/.travis.yml
vendored
Normal file
|
@ -0,0 +1,18 @@
|
|||
language: php
|
||||
|
||||
php:
|
||||
- 5.3
|
||||
- 5.4
|
||||
- 5.5
|
||||
- 5.6
|
||||
- 7.0
|
||||
|
||||
before_script:
|
||||
- composer install
|
||||
|
||||
script:
|
||||
- mkdir -p build/logs
|
||||
- php vendor/bin/phpunit -c phpunit.xml
|
||||
|
||||
after_script:
|
||||
- php vendor/bin/coveralls -v
|
21
tests/integration/vendor/ralouphie/getallheaders/LICENSE
vendored
Normal file
21
tests/integration/vendor/ralouphie/getallheaders/LICENSE
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Ralph Khattar
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
19
tests/integration/vendor/ralouphie/getallheaders/README.md
vendored
Normal file
19
tests/integration/vendor/ralouphie/getallheaders/README.md
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
getallheaders
|
||||
=============
|
||||
|
||||
PHP `getallheaders()` polyfill. Compatible with PHP >= 5.3.
|
||||
|
||||
[![Build Status](https://travis-ci.org/ralouphie/getallheaders.svg?branch=master)](https://travis-ci.org/ralouphie/getallheaders)
|
||||
[![Coverage Status](https://coveralls.io/repos/ralouphie/getallheaders/badge.png?branch=master)](https://coveralls.io/r/ralouphie/getallheaders?branch=master)
|
||||
[![Latest Stable Version](https://poser.pugx.org/ralouphie/getallheaders/v/stable.png)](https://packagist.org/packages/ralouphie/getallheaders)
|
||||
[![Latest Unstable Version](https://poser.pugx.org/ralouphie/getallheaders/v/unstable.png)](https://packagist.org/packages/ralouphie/getallheaders)
|
||||
[![License](https://poser.pugx.org/ralouphie/getallheaders/license.png)](https://packagist.org/packages/ralouphie/getallheaders)
|
||||
|
||||
|
||||
This is a simple polyfill for [`getallheaders()`](http://www.php.net/manual/en/function.getallheaders.php).
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
composer require ralouphie/getallheaders
|
||||
```
|
21
tests/integration/vendor/ralouphie/getallheaders/composer.json
vendored
Normal file
21
tests/integration/vendor/ralouphie/getallheaders/composer.json
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"name": "ralouphie/getallheaders",
|
||||
"description": "A polyfill for getallheaders.",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Ralph Khattar",
|
||||
"email": "ralph.khattar@gmail.com"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~3.7.0",
|
||||
"satooshi/php-coveralls": ">=1.0"
|
||||
},
|
||||
"autoload": {
|
||||
"files": ["src/getallheaders.php"]
|
||||
}
|
||||
}
|
22
tests/integration/vendor/ralouphie/getallheaders/phpunit.xml
vendored
Normal file
22
tests/integration/vendor/ralouphie/getallheaders/phpunit.xml
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
<phpunit
|
||||
bootstrap="vendor/autoload.php"
|
||||
convertErrorsToExceptions="true"
|
||||
convertNoticesToExceptions="true"
|
||||
convertWarningsToExceptions="true"
|
||||
strict="true">
|
||||
|
||||
<testsuite>
|
||||
<directory>./tests</directory>
|
||||
</testsuite>
|
||||
|
||||
<filter>
|
||||
<whitelist>
|
||||
<directory suffix=".php">src</directory>
|
||||
</whitelist>
|
||||
</filter>
|
||||
|
||||
<logging>
|
||||
<log type="coverage-clover" target="build/logs/clover.xml"/>
|
||||
</logging>
|
||||
|
||||
</phpunit>
|
46
tests/integration/vendor/ralouphie/getallheaders/src/getallheaders.php
vendored
Normal file
46
tests/integration/vendor/ralouphie/getallheaders/src/getallheaders.php
vendored
Normal file
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
if (!function_exists('getallheaders')) {
|
||||
|
||||
/**
|
||||
* Get all HTTP header key/values as an associative array for the current request.
|
||||
*
|
||||
* @return string[string] The HTTP header key/value pairs.
|
||||
*/
|
||||
function getallheaders()
|
||||
{
|
||||
$headers = array();
|
||||
|
||||
$copy_server = array(
|
||||
'CONTENT_TYPE' => 'Content-Type',
|
||||
'CONTENT_LENGTH' => 'Content-Length',
|
||||
'CONTENT_MD5' => 'Content-Md5',
|
||||
);
|
||||
|
||||
foreach ($_SERVER as $key => $value) {
|
||||
if (substr($key, 0, 5) === 'HTTP_') {
|
||||
$key = substr($key, 5);
|
||||
if (!isset($copy_server[$key]) || !isset($_SERVER[$key])) {
|
||||
$key = str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', $key))));
|
||||
$headers[$key] = $value;
|
||||
}
|
||||
} elseif (isset($copy_server[$key])) {
|
||||
$headers[$copy_server[$key]] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset($headers['Authorization'])) {
|
||||
if (isset($_SERVER['REDIRECT_HTTP_AUTHORIZATION'])) {
|
||||
$headers['Authorization'] = $_SERVER['REDIRECT_HTTP_AUTHORIZATION'];
|
||||
} elseif (isset($_SERVER['PHP_AUTH_USER'])) {
|
||||
$basic_pass = isset($_SERVER['PHP_AUTH_PW']) ? $_SERVER['PHP_AUTH_PW'] : '';
|
||||
$headers['Authorization'] = 'Basic ' . base64_encode($_SERVER['PHP_AUTH_USER'] . ':' . $basic_pass);
|
||||
} elseif (isset($_SERVER['PHP_AUTH_DIGEST'])) {
|
||||
$headers['Authorization'] = $_SERVER['PHP_AUTH_DIGEST'];
|
||||
}
|
||||
}
|
||||
|
||||
return $headers;
|
||||
}
|
||||
|
||||
}
|
121
tests/integration/vendor/ralouphie/getallheaders/tests/GetAllHeadersTest.php
vendored
Normal file
121
tests/integration/vendor/ralouphie/getallheaders/tests/GetAllHeadersTest.php
vendored
Normal file
|
@ -0,0 +1,121 @@
|
|||
<?php
|
||||
|
||||
class GetAllHeadersTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
|
||||
/**
|
||||
* @dataProvider testWorksData
|
||||
*/
|
||||
public function testWorks($test_type, $expected, $server)
|
||||
{
|
||||
foreach ($server as $key => $val) {
|
||||
$_SERVER[$key] = $val;
|
||||
}
|
||||
$result = getallheaders();
|
||||
$this->assertEquals($expected, $result, "Error testing $test_type works.");
|
||||
}
|
||||
|
||||
public function testWorksData()
|
||||
{
|
||||
return array(
|
||||
array(
|
||||
'normal case',
|
||||
array(
|
||||
'Key-One' => 'foo',
|
||||
'Key-Two' => 'bar',
|
||||
'Another-Key-For-Testing' => 'baz'
|
||||
),
|
||||
array(
|
||||
'HTTP_KEY_ONE' => 'foo',
|
||||
'HTTP_KEY_TWO' => 'bar',
|
||||
'HTTP_ANOTHER_KEY_FOR_TESTING' => 'baz'
|
||||
)
|
||||
),
|
||||
array(
|
||||
'Content-Type',
|
||||
array(
|
||||
'Content-Type' => 'two'
|
||||
),
|
||||
array(
|
||||
'HTTP_CONTENT_TYPE' => 'one',
|
||||
'CONTENT_TYPE' => 'two'
|
||||
)
|
||||
),
|
||||
array(
|
||||
'Content-Length',
|
||||
array(
|
||||
'Content-Length' => '222'
|
||||
),
|
||||
array(
|
||||
'CONTENT_LENGTH' => '222',
|
||||
'HTTP_CONTENT_LENGTH' => '111'
|
||||
)
|
||||
),
|
||||
array(
|
||||
'Content-Length (HTTP_CONTENT_LENGTH only)',
|
||||
array(
|
||||
'Content-Length' => '111'
|
||||
),
|
||||
array(
|
||||
'HTTP_CONTENT_LENGTH' => '111'
|
||||
)
|
||||
),
|
||||
array(
|
||||
'Content-MD5',
|
||||
array(
|
||||
'Content-Md5' => 'aef123'
|
||||
),
|
||||
array(
|
||||
'CONTENT_MD5' => 'aef123',
|
||||
'HTTP_CONTENT_MD5' => 'fea321'
|
||||
)
|
||||
),
|
||||
array(
|
||||
'Content-MD5 (HTTP_CONTENT_MD5 only)',
|
||||
array(
|
||||
'Content-Md5' => 'f123'
|
||||
),
|
||||
array(
|
||||
'HTTP_CONTENT_MD5' => 'f123'
|
||||
)
|
||||
),
|
||||
array(
|
||||
'Authorization (normal)',
|
||||
array(
|
||||
'Authorization' => 'testing'
|
||||
),
|
||||
array(
|
||||
'HTTP_AUTHORIZATION' => 'testing',
|
||||
)
|
||||
),
|
||||
array(
|
||||
'Authorization (redirect)',
|
||||
array(
|
||||
'Authorization' => 'testing redirect'
|
||||
),
|
||||
array(
|
||||
'REDIRECT_HTTP_AUTHORIZATION' => 'testing redirect',
|
||||
)
|
||||
),
|
||||
array(
|
||||
'Authorization (PHP_AUTH_USER + PHP_AUTH_PW)',
|
||||
array(
|
||||
'Authorization' => 'Basic ' . base64_encode('foo:bar')
|
||||
),
|
||||
array(
|
||||
'PHP_AUTH_USER' => 'foo',
|
||||
'PHP_AUTH_PW' => 'bar'
|
||||
)
|
||||
),
|
||||
array(
|
||||
'Authorization (PHP_AUTH_DIGEST)',
|
||||
array(
|
||||
'Authorization' => 'example-digest'
|
||||
),
|
||||
array(
|
||||
'PHP_AUTH_DIGEST' => 'example-digest'
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue