diff --git a/.circleci/config.yml b/.circleci/config.yml
new file mode 100644
index 0000000..b974a2b
--- /dev/null
+++ b/.circleci/config.yml
@@ -0,0 +1,33 @@
+version: 2
+
+jobs:
+ build:
+ docker:
+ - image: circleci/php:7.1-cli
+
+ working_directory: ~/repo
+
+ steps:
+ - checkout
+
+ - restore_cache:
+ keys:
+ - v1-dependencies-{{ checksum "composer.json" }}
+ - v1-dependencies-
+
+ - run: composer install -n --prefer-dist
+
+ - save_cache:
+ paths:
+ - ./vendor
+ key: v1-dependencies-{{ checksum "composer.json" }}
+
+ - run: mkdir test/unit/_junit
+ - run: vendor/bin/phpunit -c test/unit/phpunit.xml --log-junit test/unit/_junit/junit.xml -d memory_limit=512M
+
+ - store_test_results:
+ path: test/unit/_junit
+
+ - store_artifacts:
+ path: test/unit/_coverage
+ destination: TestCoverage
diff --git a/.scrutinizer.yml b/.scrutinizer.yml
index f6f6001..b84b29f 100644
--- a/.scrutinizer.yml
+++ b/.scrutinizer.yml
@@ -1,14 +1,14 @@
build:
environment:
php:
- version: 7.0.8
+ version: 7.1.0
tests:
override:
- -
- command: 'vendor/bin/phpunit --coverage-clover=coverage'
- coverage:
- file: 'coverage'
- format: 'php-clover'
+ -
+ command: 'vendor/bin/phpunit test/unit --coverage-clover coverage --whitelist src'
+ coverage:
+ file: 'coverage'
+ format: 'php-clover'
checks:
php:
@@ -17,5 +17,5 @@ checks:
filter:
excluded_paths:
- - test/*
- - vendor/*
\ No newline at end of file
+ - test/*
+ - vendor/*
diff --git a/README.md b/README.md
index c530420..e84b7de 100644
--- a/README.md
+++ b/README.md
@@ -7,16 +7,19 @@ See also, the [JavaScript implementation][fetch-js] that ships as standard in al
***
-
+
-
+
-
+
-
+
+
+
+
## Example usage: compute multiple HTTP requests in parallel.
diff --git a/circle.yml b/circle.yml
deleted file mode 100644
index 9bcc9a6..0000000
--- a/circle.yml
+++ /dev/null
@@ -1,11 +0,0 @@
-machine:
- php:
- version: 7.0.4
-
-test:
- override:
- - vendor/bin/phpunit
-
-notify:
- webhooks:
- - url: https://webhooks.gitter.im/e/22c9d06e726e91ddc7c5
\ No newline at end of file
diff --git a/composer.json b/composer.json
index 6c508a7..0a7ca30 100644
--- a/composer.json
+++ b/composer.json
@@ -1,44 +1,64 @@
{
- "name": "phpgt/fetch",
- "description": "Asynchronous HTTP client with promises.",
- "type": "library",
-
- "require": {
- "php": ">=7.1",
- "react/event-loop": "^1.0.0",
- "react/promise": "^2.4",
- "phpcurl/curlwrapper": "^2.1",
- "react/stream": "^0.4.4"
- },
- "require-dev": {
- "phpunit/phpunit": "5.*|7.*"
- },
-
- "license": "MIT",
-
- "authors": [
- {
- "name": "Greg Bowler",
- "email": "greg.bowler@g105b.com"
- }
- ],
-
- "autoload": {
- "psr-4": {
- "Gt\\Fetch\\": "./src"
- }
- },
-
- "keywords": [
- "http",
- "fetch",
- "async",
- "asynchronous",
- "xmlhttprequest",
- "ajax",
- "get",
- "post",
- "curl",
- "curl_multi"
- ]
+ "name": "phpgt/fetch",
+ "description": "Asynchronous HTTP client with promises for PHP 7 applications.",
+ "type": "library",
+ "license": "MIT",
+
+ "minimum-stability": "dev",
+
+ "provide": {
+ "php-http/client-implementation": "1.0",
+ "php-http/async-client-implementation": "1.0"
+ },
+
+ "require": {
+ "php": ">=7.1.0",
+ "ext-curl": "*",
+ "ext-json": "*",
+ "phpgt/http": "dev-master",
+ "phpgt/curl": "dev-master",
+
+ "php-http/httplug": "^1.1",
+ "php-http/promise": "^1.0.0",
+
+ "react/event-loop": "^1.0.0",
+ "react/stream": "^1.0.0",
+ "react/promise": "^2.7.0"
+ },
+
+ "require-dev": {
+ "phpunit/phpunit": "7.*"
+ },
+
+ "autoload": {
+ "psr-4": {
+ "Gt\\Fetch\\": "./src"
+ }
+ },
+
+ "autoload-dev": {
+ "psr-4": {
+ "Gt\\Fetch\\Test\\": "./test/unit"
+ }
+ },
+
+ "authors": [
+ {
+ "name": "Greg Bowler",
+ "email": "greg.bowler@g105b.com"
+ }
+ ],
+
+ "keywords": [
+ "http",
+ "fetch",
+ "async",
+ "asynchronous",
+ "xmlhttprequest",
+ "ajax",
+ "get",
+ "post",
+ "curl",
+ "curl_multi"
+ ]
}
diff --git a/composer.lock b/composer.lock
index 534ed32..a3cbb13 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,34 +4,29 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "4174bcc8fae1dd8c102c1ef9dd7330f9",
+ "content-hash": "c1586ff2609b6f54325decdb4fc03ac2",
"packages": [
{
"name": "evenement/evenement",
- "version": "v2.1.0",
+ "version": "v3.0.1",
"source": {
"type": "git",
"url": "https://github.com/igorw/evenement.git",
- "reference": "6ba9a777870ab49f417e703229d53931ed40fd7a"
+ "reference": "531bfb9d15f8aa57454f5f0285b18bec903b8fb7"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/igorw/evenement/zipball/6ba9a777870ab49f417e703229d53931ed40fd7a",
- "reference": "6ba9a777870ab49f417e703229d53931ed40fd7a",
+ "url": "https://api.github.com/repos/igorw/evenement/zipball/531bfb9d15f8aa57454f5f0285b18bec903b8fb7",
+ "reference": "531bfb9d15f8aa57454f5f0285b18bec903b8fb7",
"shasum": ""
},
"require": {
- "php": ">=5.4.0"
+ "php": ">=7.0"
},
"require-dev": {
- "phpunit/phpunit": "^6.0||^5.7||^4.8.35"
+ "phpunit/phpunit": "^6.0"
},
"type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "2.0-dev"
- }
- },
"autoload": {
"psr-0": {
"Evenement": "src"
@@ -52,34 +47,178 @@
"event-dispatcher",
"event-emitter"
],
- "time": "2017-07-17T17:39:19+00:00"
+ "time": "2017-07-23T21:35:13+00:00"
},
{
- "name": "phpcurl/curlwrapper",
- "version": "2.1.0",
+ "name": "php-http/httplug",
+ "version": "dev-master",
"source": {
"type": "git",
- "url": "https://github.com/phpcurl/curlwrapper.git",
- "reference": "9e58c7f0d52c5f44e5a50f39d28c9870d4b1de8c"
+ "url": "https://github.com/php-http/httplug.git",
+ "reference": "7e296052447a8c8c391c619ba2058284e578e033"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpcurl/curlwrapper/zipball/9e58c7f0d52c5f44e5a50f39d28c9870d4b1de8c",
- "reference": "9e58c7f0d52c5f44e5a50f39d28c9870d4b1de8c",
+ "url": "https://api.github.com/repos/php-http/httplug/zipball/7e296052447a8c8c391c619ba2058284e578e033",
+ "reference": "7e296052447a8c8c391c619ba2058284e578e033",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.4",
+ "php-http/promise": "^1.0",
+ "psr/http-message": "^1.0"
+ },
+ "require-dev": {
+ "henrikbjorn/phpspec-code-coverage": "^1.0",
+ "phpspec/phpspec": "^2.4"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.2-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Http\\Client\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Eric GELOEN",
+ "email": "geloen.eric@gmail.com"
+ },
+ {
+ "name": "Márk Sági-Kazár",
+ "email": "mark.sagikazar@gmail.com"
+ }
+ ],
+ "description": "HTTPlug, the HTTP client abstraction for PHP",
+ "homepage": "http://httplug.io",
+ "keywords": [
+ "client",
+ "http"
+ ],
+ "time": "2018-10-18T10:18:22+00:00"
+ },
+ {
+ "name": "php-http/promise",
+ "version": "dev-master",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-http/promise.git",
+ "reference": "1cc44dc01402d407fc6da922591deebe4659826f"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-http/promise/zipball/1cc44dc01402d407fc6da922591deebe4659826f",
+ "reference": "1cc44dc01402d407fc6da922591deebe4659826f",
+ "shasum": ""
+ },
+ "require-dev": {
+ "henrikbjorn/phpspec-code-coverage": "^1.0",
+ "phpspec/phpspec": "^2.4"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Http\\Promise\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Márk Sági-Kazár",
+ "email": "mark.sagikazar@gmail.com"
+ },
+ {
+ "name": "Joel Wurtz",
+ "email": "joel.wurtz@gmail.com"
+ }
+ ],
+ "description": "Promise used for asynchronous HTTP requests",
+ "homepage": "http://httplug.io",
+ "keywords": [
+ "promise"
+ ],
+ "time": "2017-11-22T21:24:54+00:00"
+ },
+ {
+ "name": "phpgt/cookie",
+ "version": "dev-master",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/PhpGt/Cookie.git",
+ "reference": "a59344f71a4999f6fa68e2724504c0949f176537"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/PhpGt/Cookie/zipball/a59344f71a4999f6fa68e2724504c0949f176537",
+ "reference": "a59344f71a4999f6fa68e2724504c0949f176537",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^7.3"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Gt\\Cookie\\": "./src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Greg Bowler",
+ "email": "greg.bowler@g105b.com"
+ }
+ ],
+ "description": "Object oriented cookie handler.",
+ "time": "2018-10-23T19:08:27+00:00"
+ },
+ {
+ "name": "phpgt/curl",
+ "version": "dev-master",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/PhpGt/Curl.git",
+ "reference": "18d6d88ad03d5c77891898b923d0cea54a209091"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/PhpGt/Curl/zipball/18d6d88ad03d5c77891898b923d0cea54a209091",
+ "reference": "18d6d88ad03d5c77891898b923d0cea54a209091",
"shasum": ""
},
"require": {
"ext-curl": "*",
- "php": ">=5.5.0"
+ "php": ">=7.1.0"
},
"require-dev": {
- "phpunit/phpunit": "^4.8 || ^5.0",
- "squizlabs/php_codesniffer": "^2.0"
+ "phpunit/phpunit": "7.2.7"
},
"type": "library",
"autoload": {
"psr-4": {
- "PHPCurl\\CurlWrapper\\": "src/"
+ "Gt\\Curl\\": "./src"
}
},
"notification-url": "https://packagist.org/downloads/",
@@ -88,27 +227,138 @@
],
"authors": [
{
- "name": "Alexey Karapetov",
- "email": "karapetov@gmail.com",
- "role": "Developer"
+ "name": "Greg Bowler",
+ "email": "greg.bowler@g105b.com"
}
],
- "description": "The simplest OOP wrapper for curl, curl_multi, curl_share functions. Use CURL as a dependency, not hard-coded!",
+ "description": "cURL object wrapper.",
"keywords": [
- "OOP",
- "Phpcurl",
"curl",
"curl_multi",
- "curl_share",
- "dependency",
- "injection",
- "mock",
- "phpunit",
- "testable",
- "testing",
- "wrapper"
+ "http",
+ "interface"
],
- "time": "2017-01-21T03:54:06+00:00"
+ "time": "2018-08-08T10:39:16+00:00"
+ },
+ {
+ "name": "phpgt/http",
+ "version": "dev-master",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/PhpGt/Http.git",
+ "reference": "874335333dc015e8cce998b30b0411e91f968b16"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/PhpGt/Http/zipball/874335333dc015e8cce998b30b0411e91f968b16",
+ "reference": "874335333dc015e8cce998b30b0411e91f968b16",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1",
+ "phpgt/cookie": "*",
+ "phpgt/input": "*",
+ "psr/http-message": "^1.0.1",
+ "willdurand/negotiation": "^2.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^6.4"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Gt\\Http\\": "./src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "PSR-7 HTTP message implementation.",
+ "time": "2018-09-16T18:21:07+00:00"
+ },
+ {
+ "name": "phpgt/input",
+ "version": "dev-master",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/PhpGt/Input.git",
+ "reference": "7b45be4a8819d10c449542ef88d1f29df345a2a2"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/PhpGt/Input/zipball/7b45be4a8819d10c449542ef88d1f29df345a2a2",
+ "reference": "7b45be4a8819d10c449542ef88d1f29df345a2a2",
+ "shasum": ""
+ },
+ "require": {
+ "phpgt/http": "dev-master"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^7.3"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Gt\\Input\\": "./src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "Encapsulated user input.",
+ "time": "2018-10-23T11:54:34+00:00"
+ },
+ {
+ "name": "psr/http-message",
+ "version": "dev-master",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/http-message.git",
+ "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
+ "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Http\\Message\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "http://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for HTTP messages",
+ "homepage": "https://github.com/php-fig/http-message",
+ "keywords": [
+ "http",
+ "http-message",
+ "psr",
+ "psr-7",
+ "request",
+ "response"
+ ],
+ "time": "2016-08-06T14:39:51+00:00"
},
{
"name": "react/event-loop",
@@ -153,7 +403,7 @@
},
{
"name": "react/promise",
- "version": "v2.7.0",
+ "version": "2.x-dev",
"source": {
"type": "git",
"url": "https://github.com/reactphp/promise.git",
@@ -199,30 +449,26 @@
},
{
"name": "react/stream",
- "version": "v0.4.6",
+ "version": "v1.0.0",
"source": {
"type": "git",
"url": "https://github.com/reactphp/stream.git",
- "reference": "44dc7f51ea48624110136b535b9ba44fd7d0c1ee"
+ "reference": "fdd0140f42805d65bf9687636503db0b326d2244"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/reactphp/stream/zipball/44dc7f51ea48624110136b535b9ba44fd7d0c1ee",
- "reference": "44dc7f51ea48624110136b535b9ba44fd7d0c1ee",
+ "url": "https://api.github.com/repos/reactphp/stream/zipball/fdd0140f42805d65bf9687636503db0b326d2244",
+ "reference": "fdd0140f42805d65bf9687636503db0b326d2244",
"shasum": ""
},
"require": {
- "evenement/evenement": "^2.0|^1.0",
- "php": ">=5.3.8"
+ "evenement/evenement": "^3.0 || ^2.0 || ^1.0",
+ "php": ">=5.3.8",
+ "react/event-loop": "^1.0 || ^0.5 || ^0.4 || ^0.3.5"
},
"require-dev": {
"clue/stream-filter": "~1.2",
- "react/event-loop": "^0.4|^0.3",
- "react/promise": "^2.0|^1.0"
- },
- "suggest": {
- "react/event-loop": "^0.4",
- "react/promise": "^2.0"
+ "phpunit/phpunit": "^6.4 || ^5.7 || ^4.8.35"
},
"type": "library",
"autoload": {
@@ -234,38 +480,97 @@
"license": [
"MIT"
],
- "description": "Basic readable and writable stream interfaces that support piping.",
+ "description": "Event-driven readable and writable streams for non-blocking I/O in ReactPHP",
"keywords": [
+ "event-driven",
+ "io",
+ "non-blocking",
"pipe",
- "stream"
+ "reactphp",
+ "readable",
+ "stream",
+ "writable"
+ ],
+ "time": "2018-07-11T14:38:16+00:00"
+ },
+ {
+ "name": "willdurand/negotiation",
+ "version": "2.x-dev",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/willdurand/Negotiation.git",
+ "reference": "cf78c9ac47e8e1e141bf609c71e9e2c3a7780dcf"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/willdurand/Negotiation/zipball/cf78c9ac47e8e1e141bf609c71e9e2c3a7780dcf",
+ "reference": "cf78c9ac47e8e1e141bf609c71e9e2c3a7780dcf",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.4.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.5"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.3-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Negotiation\\": "src/Negotiation"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "William Durand",
+ "email": "will+git@drnd.me"
+ }
],
- "time": "2017-01-25T14:44:14+00:00"
+ "description": "Content Negotiation tools for PHP provided as a standalone library.",
+ "homepage": "http://williamdurand.fr/Negotiation/",
+ "keywords": [
+ "accept",
+ "content",
+ "format",
+ "header",
+ "negotiation"
+ ],
+ "time": "2017-08-04T15:54:30+00:00"
}
],
"packages-dev": [
{
"name": "doctrine/instantiator",
- "version": "1.1.0",
+ "version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/doctrine/instantiator.git",
- "reference": "185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda"
+ "reference": "8c8c1afee0f929f17528fe1721de5d58e15f71c7"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/doctrine/instantiator/zipball/185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda",
- "reference": "185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda",
+ "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8c8c1afee0f929f17528fe1721de5d58e15f71c7",
+ "reference": "8c8c1afee0f929f17528fe1721de5d58e15f71c7",
"shasum": ""
},
"require": {
"php": "^7.1"
},
"require-dev": {
- "athletic/athletic": "~0.1.8",
+ "doctrine/coding-standard": "^5.0",
"ext-pdo": "*",
"ext-phar": "*",
- "phpunit/phpunit": "^6.2.3",
- "squizlabs/php_codesniffer": "^3.0.2"
+ "phpbench/phpbench": "^0.13",
+ "phpstan/phpstan-shim": "^0.9.2",
+ "phpunit/phpunit": "^7.0"
},
"type": "library",
"extra": {
@@ -290,16 +595,16 @@
}
],
"description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
- "homepage": "https://github.com/doctrine/instantiator",
+ "homepage": "https://www.doctrine-project.org/projects/instantiator.html",
"keywords": [
"constructor",
"instantiate"
],
- "time": "2017-07-22T11:58:36+00:00"
+ "time": "2018-10-15T11:30:00+00:00"
},
{
"name": "myclabs/deep-copy",
- "version": "1.8.1",
+ "version": "1.x-dev",
"source": {
"type": "git",
"url": "https://github.com/myclabs/DeepCopy.git",
@@ -347,7 +652,7 @@
},
{
"name": "phar-io/manifest",
- "version": "1.0.3",
+ "version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/phar-io/manifest.git",
@@ -601,7 +906,7 @@
},
{
"name": "phpspec/prophecy",
- "version": "1.8.0",
+ "version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/phpspec/prophecy.git",
@@ -664,7 +969,7 @@
},
{
"name": "phpunit/php-code-coverage",
- "version": "6.1.3",
+ "version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
@@ -727,16 +1032,16 @@
},
{
"name": "phpunit/php-file-iterator",
- "version": "2.0.2",
+ "version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-file-iterator.git",
- "reference": "050bedf145a257b1ff02746c31894800e5122946"
+ "reference": "2da97ea973af95b5ccef2d5bae0f4a976f3923a0"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/050bedf145a257b1ff02746c31894800e5122946",
- "reference": "050bedf145a257b1ff02746c31894800e5122946",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/2da97ea973af95b5ccef2d5bae0f4a976f3923a0",
+ "reference": "2da97ea973af95b5ccef2d5bae0f4a976f3923a0",
"shasum": ""
},
"require": {
@@ -773,7 +1078,7 @@
"filesystem",
"iterator"
],
- "time": "2018-09-13T20:33:42+00:00"
+ "time": "2018-10-10T04:54:51+00:00"
},
{
"name": "phpunit/php-text-template",
@@ -818,16 +1123,16 @@
},
{
"name": "phpunit/php-timer",
- "version": "2.0.0",
+ "version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-timer.git",
- "reference": "8b8454ea6958c3dee38453d3bd571e023108c91f"
+ "reference": "9ef9968ba27999219d76ae3cef97aa0fa87bd90f"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/8b8454ea6958c3dee38453d3bd571e023108c91f",
- "reference": "8b8454ea6958c3dee38453d3bd571e023108c91f",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/9ef9968ba27999219d76ae3cef97aa0fa87bd90f",
+ "reference": "9ef9968ba27999219d76ae3cef97aa0fa87bd90f",
"shasum": ""
},
"require": {
@@ -863,20 +1168,20 @@
"keywords": [
"timer"
],
- "time": "2018-02-01T13:07:23+00:00"
+ "time": "2018-06-04T07:17:52+00:00"
},
{
"name": "phpunit/php-token-stream",
- "version": "3.0.0",
+ "version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-token-stream.git",
- "reference": "21ad88bbba7c3d93530d93994e0a33cd45f02ace"
+ "reference": "711ca0c13c66f6b66c2ecb586e56415815034330"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/21ad88bbba7c3d93530d93994e0a33cd45f02ace",
- "reference": "21ad88bbba7c3d93530d93994e0a33cd45f02ace",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/711ca0c13c66f6b66c2ecb586e56415815034330",
+ "reference": "711ca0c13c66f6b66c2ecb586e56415815034330",
"shasum": ""
},
"require": {
@@ -912,20 +1217,20 @@
"keywords": [
"tokenizer"
],
- "time": "2018-02-01T13:16:43+00:00"
+ "time": "2018-06-06T10:32:05+00:00"
},
{
"name": "phpunit/phpunit",
- "version": "7.4.3",
+ "version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
- "reference": "c151651fb6ed264038d486ea262e243af72e5e64"
+ "reference": "4749b966a603713c35806d7a71c54492ee209c38"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c151651fb6ed264038d486ea262e243af72e5e64",
- "reference": "c151651fb6ed264038d486ea262e243af72e5e64",
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/4749b966a603713c35806d7a71c54492ee209c38",
+ "reference": "4749b966a603713c35806d7a71c54492ee209c38",
"shasum": ""
},
"require": {
@@ -946,7 +1251,7 @@
"phpunit/php-timer": "^2.0",
"sebastian/comparator": "^3.0",
"sebastian/diff": "^3.0",
- "sebastian/environment": "^3.1 || ^4.0",
+ "sebastian/environment": "^4.0",
"sebastian/exporter": "^3.1",
"sebastian/global-state": "^2.0",
"sebastian/object-enumerator": "^3.0.3",
@@ -970,7 +1275,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "7.4-dev"
+ "dev-master": "7.5-dev"
}
},
"autoload": {
@@ -996,20 +1301,20 @@
"testing",
"xunit"
],
- "time": "2018-10-23T05:57:41+00:00"
+ "time": "2018-10-23T05:29:44+00:00"
},
{
"name": "sebastian/code-unit-reverse-lookup",
- "version": "1.0.1",
+ "version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git",
- "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18"
+ "reference": "22f5f5ff892d51035dd1fb4cd6b224a640ffb206"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/4419fcdb5eabb9caa61a27c7a1db532a6b55dd18",
- "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18",
+ "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/22f5f5ff892d51035dd1fb4cd6b224a640ffb206",
+ "reference": "22f5f5ff892d51035dd1fb4cd6b224a640ffb206",
"shasum": ""
},
"require": {
@@ -1041,20 +1346,20 @@
],
"description": "Looks up which function or method a line of code belongs to",
"homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/",
- "time": "2017-03-04T06:30:41+00:00"
+ "time": "2018-05-15T05:52:48+00:00"
},
{
"name": "sebastian/comparator",
- "version": "3.0.2",
+ "version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/comparator.git",
- "reference": "5de4fc177adf9bce8df98d8d141a7559d7ccf6da"
+ "reference": "2256ef8e824cc494ddeebaa00fabe7ab4d83fc75"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/5de4fc177adf9bce8df98d8d141a7559d7ccf6da",
- "reference": "5de4fc177adf9bce8df98d8d141a7559d7ccf6da",
+ "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2256ef8e824cc494ddeebaa00fabe7ab4d83fc75",
+ "reference": "2256ef8e824cc494ddeebaa00fabe7ab4d83fc75",
"shasum": ""
},
"require": {
@@ -1105,11 +1410,11 @@
"compare",
"equality"
],
- "time": "2018-07-12T15:12:46+00:00"
+ "time": "2018-09-07T13:55:31+00:00"
},
{
"name": "sebastian/diff",
- "version": "3.0.1",
+ "version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/diff.git",
@@ -1165,28 +1470,28 @@
},
{
"name": "sebastian/environment",
- "version": "3.1.0",
+ "version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/environment.git",
- "reference": "cd0871b3975fb7fc44d11314fd1ee20925fce4f5"
+ "reference": "c38399052e96de3846f635b8791c2e447a06040d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/cd0871b3975fb7fc44d11314fd1ee20925fce4f5",
- "reference": "cd0871b3975fb7fc44d11314fd1ee20925fce4f5",
+ "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/c38399052e96de3846f635b8791c2e447a06040d",
+ "reference": "c38399052e96de3846f635b8791c2e447a06040d",
"shasum": ""
},
"require": {
- "php": "^7.0"
+ "php": "^7.1"
},
"require-dev": {
- "phpunit/phpunit": "^6.1"
+ "phpunit/phpunit": "^7.4"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "3.1.x-dev"
+ "dev-master": "4.0-dev"
}
},
"autoload": {
@@ -1211,20 +1516,20 @@
"environment",
"hhvm"
],
- "time": "2017-07-01T08:51:00+00:00"
+ "time": "2018-10-23T06:03:07+00:00"
},
{
"name": "sebastian/exporter",
- "version": "3.1.0",
+ "version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/exporter.git",
- "reference": "234199f4528de6d12aaa58b612e98f7d36adb937"
+ "reference": "c8c4f196e32858e4448bc285e542b61a4c40d9dc"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/234199f4528de6d12aaa58b612e98f7d36adb937",
- "reference": "234199f4528de6d12aaa58b612e98f7d36adb937",
+ "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/c8c4f196e32858e4448bc285e542b61a4c40d9dc",
+ "reference": "c8c4f196e32858e4448bc285e542b61a4c40d9dc",
"shasum": ""
},
"require": {
@@ -1278,20 +1583,20 @@
"export",
"exporter"
],
- "time": "2017-04-03T13:19:02+00:00"
+ "time": "2018-06-28T14:22:04+00:00"
},
{
"name": "sebastian/global-state",
- "version": "2.0.0",
+ "version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/global-state.git",
- "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4"
+ "reference": "30367ea06c5cc3bf684457ac793fb2b863d783c6"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4",
- "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4",
+ "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/30367ea06c5cc3bf684457ac793fb2b863d783c6",
+ "reference": "30367ea06c5cc3bf684457ac793fb2b863d783c6",
"shasum": ""
},
"require": {
@@ -1329,20 +1634,20 @@
"keywords": [
"global state"
],
- "time": "2017-04-27T15:39:26+00:00"
+ "time": "2018-05-15T05:52:33+00:00"
},
{
"name": "sebastian/object-enumerator",
- "version": "3.0.3",
+ "version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/object-enumerator.git",
- "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5"
+ "reference": "06d95dc84f06fc6cc246b8bf48facebcf0fe8069"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/7cfd9e65d11ffb5af41198476395774d4c8a84c5",
- "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5",
+ "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/06d95dc84f06fc6cc246b8bf48facebcf0fe8069",
+ "reference": "06d95dc84f06fc6cc246b8bf48facebcf0fe8069",
"shasum": ""
},
"require": {
@@ -1376,20 +1681,20 @@
],
"description": "Traverses array structures and object graphs to enumerate all referenced objects",
"homepage": "https://github.com/sebastianbergmann/object-enumerator/",
- "time": "2017-08-03T12:35:26+00:00"
+ "time": "2018-05-15T05:52:18+00:00"
},
{
"name": "sebastian/object-reflector",
- "version": "1.1.1",
+ "version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/object-reflector.git",
- "reference": "773f97c67f28de00d397be301821b06708fca0be"
+ "reference": "7707193304715e3caddf28fc73c02c12ed6f350c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/773f97c67f28de00d397be301821b06708fca0be",
- "reference": "773f97c67f28de00d397be301821b06708fca0be",
+ "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/7707193304715e3caddf28fc73c02c12ed6f350c",
+ "reference": "7707193304715e3caddf28fc73c02c12ed6f350c",
"shasum": ""
},
"require": {
@@ -1421,20 +1726,20 @@
],
"description": "Allows reflection of object attributes, including inherited and non-public ones",
"homepage": "https://github.com/sebastianbergmann/object-reflector/",
- "time": "2017-03-29T09:07:27+00:00"
+ "time": "2018-05-15T05:50:44+00:00"
},
{
"name": "sebastian/recursion-context",
- "version": "3.0.0",
+ "version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/recursion-context.git",
- "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8"
+ "reference": "dbe1869c13935c6080c834fc61424834b9ad5907"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8",
- "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8",
+ "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/dbe1869c13935c6080c834fc61424834b9ad5907",
+ "reference": "dbe1869c13935c6080c834fc61424834b9ad5907",
"shasum": ""
},
"require": {
@@ -1474,11 +1779,11 @@
],
"description": "Provides functionality to recursively process PHP variables",
"homepage": "http://www.github.com/sebastianbergmann/recursion-context",
- "time": "2017-03-03T06:23:57+00:00"
+ "time": "2018-05-15T05:52:05+00:00"
},
{
"name": "sebastian/resource-operations",
- "version": "2.0.1",
+ "version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/resource-operations.git",
@@ -1603,16 +1908,16 @@
},
{
"name": "webmozart/assert",
- "version": "1.3.0",
+ "version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/webmozart/assert.git",
- "reference": "0df1908962e7a3071564e857d86874dad1ef204a"
+ "reference": "53927dddf3afa2088b355188e143bba42159bf5d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/webmozart/assert/zipball/0df1908962e7a3071564e857d86874dad1ef204a",
- "reference": "0df1908962e7a3071564e857d86874dad1ef204a",
+ "url": "https://api.github.com/repos/webmozart/assert/zipball/53927dddf3afa2088b355188e143bba42159bf5d",
+ "reference": "53927dddf3afa2088b355188e143bba42159bf5d",
"shasum": ""
},
"require": {
@@ -1649,16 +1954,20 @@
"check",
"validate"
],
- "time": "2018-01-29T19:49:41+00:00"
+ "time": "2018-05-29T14:25:02+00:00"
}
],
"aliases": [],
- "minimum-stability": "stable",
- "stability-flags": [],
+ "minimum-stability": "dev",
+ "stability-flags": {
+ "phpgt/http": 20,
+ "phpgt/curl": 20
+ },
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
- "php": ">=7.1"
+ "php": ">=7.1.0",
+ "ext-curl": "*"
},
"platform-dev": []
}
diff --git a/phpunit.xml b/phpunit.xml
deleted file mode 100644
index 823f5e2..0000000
--- a/phpunit.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
- test/unit
-
-
-
-
-
-
-
-
-
-
- src
-
-
-
\ No newline at end of file
diff --git a/src/Body.php b/src/Body.php
deleted file mode 100644
index 536b7a0..0000000
--- a/src/Body.php
+++ /dev/null
@@ -1,70 +0,0 @@
-promise();
- $this->readRawBodyDeferredArray []= $deferredJson;
- $this->readRawBodyDeferredTransformArray []= function($data) {
- return json_decode($data);
- };
-
- return $promise;
-}
-
-/**
- * Returns a promise that resolves with a UTF-8 encoded string.
- */
-public function text():Promise {
- $deferredText = new Deferred();
- $promise = $deferredText->promise();
- $this->readRawBodyDeferredArray []= $deferredText;
- $this->readRawBodyDeferredTransformArray []= function($data) {
- $charset = $this->getCharset();
- $toEncoding = "utf-8";
- return mb_convert_encoding($data, $toEncoding, $charset);
- };
-
- return $promise;
-}
-
-}#
\ No newline at end of file
diff --git a/src/BodyResponse.php b/src/BodyResponse.php
new file mode 100644
index 0000000..0a7b9e2
--- /dev/null
+++ b/src/BodyResponse.php
@@ -0,0 +1,52 @@
+promise();
+ }
+
+ public function blob():Promise {
+ $deferred = new Deferred();
+ return $deferred->promise();
+ }
+
+ public function formData():Promise {
+ $deferred = new Deferred();
+ return $deferred->promise();
+ }
+
+ public function json(int $depth = 512, int $options = 0):Promise {
+ $deferred = new Deferred();
+
+ $json = json_decode(
+ $this->getBody(),
+ false,
+ $depth,
+ $options
+ );
+ if(is_null($json)) {
+ $errorMessage = json_last_error_msg();
+ throw new JsonDecodeException($errorMessage);
+ }
+
+ $deferred->resolve($json);
+
+ return $deferred->promise();
+ }
+
+ public function text():Promise {
+
+ var_dump($this->getBody()->read(100));die();
+ $deferred = new Deferred();
+ $deferred->resolve((string)$this->getBody());
+ return $deferred->promise();
+ }
+}
\ No newline at end of file
diff --git a/src/BodyResponseFactory.php b/src/BodyResponseFactory.php
new file mode 100644
index 0000000..d6ab123
--- /dev/null
+++ b/src/BodyResponseFactory.php
@@ -0,0 +1,17 @@
+getStatusCode(),
+ $response->getResponseHeaders(),
+ $response->getBody()
+ );
+
+ return $bodyResponse;
+ }
+}
\ No newline at end of file
diff --git a/src/CurlHandleMissingException.php b/src/CurlHandleMissingException.php
deleted file mode 100644
index 9d24279..0000000
--- a/src/CurlHandleMissingException.php
+++ /dev/null
@@ -1,4 +0,0 @@
-headerArray[$name] []= $value;
-}
-
-/**
- * Deletes a header from the current Headers object. Throws a HeaderException
- * if the provided name does not exist.
- */
-public function delete(string $name) {
-
-}
-
-/**
- * Returns the first value of a given header from within a Headers object. If
- * the requested header doesn't exist in the Headers object, the call
- * returns null.
- */
-public function get(string $name) {
- if($this->has($name)) {
- return $this->headerArray[$name][0];
- }
-
- return null;
-}
-
-/**
- * Returns an array of all the values of a header within a Headers object with
- * a given name. If the requested header doesn't exist in the Headers object,
- * it returns an empty array.
- */
-public function getAll():array {
-
-}
-
-/**
- * Returns a boolean stating whether a Headers object contains a certain header.
- */
-public function has(string $name):bool {
- return !empty($this->headerArray[$name]);
-}
-
-/**
- * Sets a new value for an existing header inside a Headers object, or adds the
- * header if it does not already exist.
- *
- * The difference between set() and append() is that if the specified header
- * already exists and accepts multiple values, set() overwrites the existing
- * value with the new one, whereas append() appends the new value to the end of
- * the set of values.
- *
- * @param string $name The header name
- * @param string|array $value The header value, either a string or array of
- * strings to append to the same header
- */
-public function set(string $name, $value) {
- $this->headerArray[$name] = [];
- $this->append($name, $value);
-}
-
-}#
\ No newline at end of file
diff --git a/src/Http.php b/src/Http.php
index bfb292a..0750347 100644
--- a/src/Http.php
+++ b/src/Http.php
@@ -1,108 +1,127 @@
interval = $interval;
- $this->loop = EventLoopFactory::create();
- $this->requestResolver = new RequestResolver($this->loop);
-}
-
-public function __call($name, $arguments) {
- switch($name) {
- case Request::METHOD_GET:
- case Request::METHOD_POST:
- case Request::METHOD_HEAD:
- case Request::METHOD_PUT:
- case Request::METHOD_DELETE:
- case Request::METHOD_OPTIONS:
- case Request::METHOD_PATCH:
- if(!isset($arguments[1])) {
- $arguments[1] = [];
- }
- $arguments[1]["method"] = $name;
-
- return call_user_func_array([$this, "request"], $arguments);
- break;
-
- default:
- trigger_error("Call to undefined method "
- . __CLASS__
- . "::"
- . $name
- . "()"
- , E_USER_ERROR
+use React\EventLoop\Factory as EventLoopFactory;
+use React\Promise\PromiseInterface;
+
+class Http extends GlobalFetchHelper implements HttpClient, HttpAsyncClient {
+ const REFERRER = "PhpGt/Fetch";
+
+ /** @var float */
+ protected $interval;
+ /** @var StreamSelectLoop */
+ protected $loop;
+ /** @var RequestResolver */
+ protected $requestResolver;
+ /** @var array cURL options */
+ protected $options = [
+ CURLOPT_CUSTOMREQUEST => "GET",
+ CURLOPT_FOLLOWLOCATION => true,
+ CURLOPT_REFERER => self::REFERRER,
+ ];
+ protected $timer;
+
+ public function __construct(
+ array $options = [],
+ float $interval = 0.01
+ ) {
+ $this->options = $options + $this->options;
+ $this->interval = $interval;
+
+ $this->loop = EventLoopFactory::create();
+ $this->requestResolver = new RequestResolver($this->loop);
+ }
+
+ /**
+ * @interface HttpClient
+ */
+ public function sendRequest(
+ RequestInterface $request
+ ):ResponseInterface {
+ // TODO: Implement sendRequest() method.
+ }
+
+ /**
+ * @interface HttpAsyncClient
+ */
+ public function sendAsyncRequest(
+ RequestInterface $request
+ ):Promise {
+ // TODO: Implement sendAsyncRequest() method.
+ }
+
+ /**
+ * Creates a new Deferred object to perform the resolution of the request and
+ * returns a PSR-7 compatible promise that represents the result of the response
+ *
+ * Long-hand for the GlobalFetchHelper get, head, post, etc.
+ *
+ * @param string|UriInterface $input
+ * @param array $init
+ * @return PromiseInterface
+ */
+ public function fetch($input, array $init = []):PromiseInterface {
+ $deferred = new Deferred();
+ $promise = $deferred->promise();
+
+ $uri = $this->ensureUriInterface($input);
+
+ $this->requestResolver->add(
+ $uri,
+ $init,
+ $deferred
);
+ return $promise;
+ }
+
+ public function getOptions():array {
+ return $this->options;
+ }
+
+ /**
+ * @param string|UriInterface $uri
+ * @return string
+ */
+ public function ensureUriInterface($uri):UriInterface {
+ if(is_string($uri)) {
+ $uri = new Uri($uri);
+ }
+
+ return $uri;
}
-}
-
-/**
- * @param string|Request $input Defines the resource that you wish to fetch
- * @param array $init An associative array containing any custom settings that
- * you wish to apply to the request
- *
- * @return \React\Promise\Promise
- */
-public function request($input, array $init = []) {
- $deferred = new Deferred();
- $promise = $deferred->promise();
-
- if(!$input instanceof Request) {
- $input = new Request($input, $init);
+
+ /**
+ * Executes all promises in parallel, returning only when all promises
+ * have been fulfilled.
+ */
+ public function wait() {
+ $this->timer = $this->loop->addPeriodicTimer(
+ $this->interval,
+ [$this->requestResolver, "tick"]
+ );
+ $this->loop->run();
+// $this->requestResolver->temporaryThing();
}
- $this->requestResolver->add($input, $deferred);
-
- return $promise;
-}
-
-/**
- * Executes all promises in parallel, not returning until all requests have
- * completed.
- */
-public function wait() {
- $this->timer = $this->loop->addPeriodicTimer(
- $this->interval, [$this->requestResolver, "tick"]
- );
- $this->loop->run();
-}
-
-/**
- * Executes all promises in parallel, returning a promise that resolves when
- * all HTTP requests have completed.
- *
- * @return \React\Promise\Promise Resolved when all HTTP requests have
- * completed
- */
-public function all() {
- $deferred = new Deferred();
- $this->wait();
- $deferred->resolve(true);
-
- return $deferred->promise();
-}
-
-}#
+ /**
+ * Begins execution of all promises, returning its own Promise that will
+ * resolve when the last HTTP request is fully resolved.
+ */
+ public function all():PromiseInterface {
+ $deferred = new Deferred();
+ $promise = $deferred->promise();
+ $this->wait();
+
+ $deferred->resolve(true);
+ return $promise;
+ }
+}
\ No newline at end of file
diff --git a/src/HttpBodyException.php b/src/HttpBodyException.php
deleted file mode 100644
index 99d0b14..0000000
--- a/src/HttpBodyException.php
+++ /dev/null
@@ -1,4 +0,0 @@
-method = $method;
-
- if(!empty($init["headers"])
- && is_array($init["headers"])) {
- $this->headers = $init["headers"];
- }
-
- if(!empty($init["body"])) {
- if(($method === self::METHOD_GET || $method === self::METHOD_HEAD)) {
- throw new HttpInitException("body");
- }
-
- $this->body = $init["body"];
- }
-
- if(!empty($init["credentials"])) {
- if(!in_array(
- strtolower($init["credentials"]), self::AVAILABLE_CREDENTIALS)) {
- throw new HttpInitException("credentials");
- }
- }
-
- if(!empty($init["redirect"])) {
- if(!in_array(
- strtolower($init["redirect"]), self::AVAILABLE_REDIRECTS)) {
- throw new HttpInitException("redirect");
- }
-
- $this->redirect = $init["redirect"];
- }
-
- if(!empty($init["referrer"])) {
- if(!is_string($init["referrer"])) {
- throw new HttpInitException("referrer");
- }
-
- $this->referrer = $init["referrer"];
- }
-
- if(!empty($init["integrity"])) {
- if(!is_string($init["integrity"])) {
- throw new HttpInitException("integrity");
- }
-
- $this->integrity = $init["integrity"];
- }
-
- $this->curl = new $curlClass($uri);
- $this->curlInit($curlOpt);
-}
-
-public function getCurlHandle() {
- return $this->curl;
-}
-
-public function getResponseCode():int {
- return (int)$this->curl->getInfo(CURLINFO_HTTP_CODE);
-}
-
-public function setStream(callable $callback) {
- $this->curl->setOpt(CURLOPT_WRITEFUNCTION, $callback);
-}
-
-private function curlInit($options = []) {
- $defaultOptions = [];
-
- $defaultOptions[CURLOPT_CUSTOMREQUEST] = $this->method;
-
- if(isset($this->headers)) {
- $defaultOptions[CURLOPT_HTTPHEADER] = $this->headers;
- }
-
- if(isset($this->body)) {
- $defaultOptions[CURLOPT_POSTFIELDS] = $this->body;
- }
-// TODO: Set up cookie jar for $this->credentials
-// as described https://developer.mozilla.org/en-US/docs/Web/API/GlobalFetch/fetch
-
- if($this->redirect === self::REDIRECT_FOLLOW) {
- $defaultOptions[CURLOPT_FOLLOWLOCATION] = true;
- }
- else {
- $defaultOptions[CURLOPT_FOLLOWLOCATION] = false;
- }
-
- if(isset($this->referrer)) {
- $defaultOptions[CURLOPT_REFERER] = $this->referrer;
- }
-
- $options = array_merge($defaultOptions, $options);
-
-// The returntransfer option MUST be set, otherwise the promise resolution
-// callbacks will not be able to get the content of the HTTP requests.
- $options[CURLOPT_RETURNTRANSFER] = true;
- $options[CURLOPT_HEADER] = true;
-
- $this->curl->setOptArray($options);
-}
-
-}#
diff --git a/src/RequestResolver.php b/src/RequestResolver.php
index 3c6442a..b5403de 100644
--- a/src/RequestResolver.php
+++ b/src/RequestResolver.php
@@ -1,118 +1,114 @@
loop = $loop;
- $this->curlMulti = new $curlMultiClass();
-}
-
-public function add(Request $request, Deferred $deferred) {
- $this->requestArray []= $request;
- $this->deferredArray []= $deferred;
-}
-
-/**
- * Called from an event loop. This function periodically checks the status of
- * the requests within requestArray, resolving corresponding Deferred objects
- * as requests complete.
- */
-public function tick() {
- if(is_null($this->openConnectionCount)) {
- $this->start();
+ protected $loop;
+
+ /** @var CurlInterface[] */
+ protected $curlReferenceList;
+ /** @var Deferred[] */
+ protected $deferredReferenceList;
+ /** @var Response[] */
+ protected $responseReferenceList;
+
+ /** @var CurlMultiInterface */
+ protected $curlMulti;
+
+ public function __construct(
+ LoopInterface $loop,
+ string $curlMultiClass = CurlMulti::class
+ ) {
+ $this->loop = $loop;
+ $this->curlReferenceList = [];
+ $this->deferredReferenceList = [];
+ $this->curlMulti = new $curlMultiClass();
}
-// Set by the curlMulti->infoRead (passed by reference). Note this is not
-// the same as the number of requests or responses that are open.
- $messagesInQueue = 0;
+ public function add(
+ UriInterface $uri,
+ array $init,
+ Deferred $deferred
+ ):void {
+ $curl = new Curl($uri);
- do {
-// always returns false until at least one curl handle has response headers
-// ready to read. (The body might not be there yet though.)
- $info = $this->curlMulti->infoRead($messagesInQueue);
-
- if($info === false) {
- break;
+ if(!empty($init["curlopt"])) {
+ $curl->setOptArray($init["curlopt"]);
}
- $request = $this->matchRequest($info["handle"]);
- $requestIndex = array_search($request, $this->requestArray);
- $httpStatusCode = $request->getResponseCode();
- $this->responseArray[$requestIndex]->complete($httpStatusCode);
-
- } while($messagesInQueue > 0);
+ $curl->setOpt(CURLOPT_RETURNTRANSFER, true);
+ $curl->setOpt(CURLOPT_HEADER, true);
- if($this->openConnectionCount === 0) {
-// TODO: Do we need to do anything else here?
- $this->loop->stop();
+ $this->curlMulti->add($curl);
+ $this->curlReferenceList []= $curl;
+ $this->deferredReferenceList []= $deferred;
+ $this->responseReferenceList []= new Response();
}
-// Wait for activity on any of the handles.
- $this->curlMulti->select();
-
-// Execute the multi handle for processing next tick.
-// openConnectionCount is passed by reference and updated by this call in each tick
- $status = $this->curlMulti->exec($this->openConnectionCount);
- if($status !== CURLM_OK) {
- throw new CurlMultiException($status);
- }
-}
-
-/**
- * Adds each request's curl handle to the multi stack.
- */
-private function start() {
- foreach($this->requestArray as $i => $request) {
- $response = new Response($this->deferredArray[$i], $this->loop);
- $this->responseArray []= $response;
- $request->setStream([$response, "stream"]);
-
- $successCode = $this->curlMulti->add($request->getCurlHandle());
- if($successCode !== 0) {
- throw new CurlMultiException($successCode);
- }
- }
-}
-
-/**
- * Matches and returns the Request object containing the provided curl handle.
- *
- * @param $ch mixed Underlying lib-curl resource
- *
- * @return Request
- * @throws CurlHandleMissingException
- */
-private function matchRequest($ch) {
- foreach($this->requestArray as $request) {
- if($request->getCurlHandle()->getHandle() === $ch) {
- return $request;
+ public function tick():void {
+ $active = 0;
+
+ ob_start();
+ $curlMultiCode = $this->curlMulti->exec($active);
+ ob_end_clean();
+
+ while($state = $this->curlMulti->infoRead()) {
+ foreach($this->curlReferenceList as $i => $ch) {
+ if($state->getHandle() !== $ch) {
+ continue;
+ }
+
+ $content = $this->curlMulti->getContent(
+ $ch
+ );
+ $response = $this->responseReferenceList[$i];
+ if($response->getStatusCode()) {
+ $body = $response->getBody();
+ $body->write($content);
+
+ break;
+ }
+
+ list(
+ $headerString,
+ $bodyString
+ ) = explode(
+ "\r\n\r\n",
+ $content
+ );
+
+
+ $headerParser = new Parser($headerString);
+ $response = $response->withProtocolVersion(
+ $headerParser->getProtocolVersion()
+ );
+ $response = $response->withStatus(
+ $headerParser->getStatusCode()
+ );
+
+ foreach($headerParser->getKeyValues() as $key => $value) {
+ $response = $response->withAddedHeader(
+ $key,
+ $value
+ );
+ }
+
+ $body = $response->getBody();
+ $body->write($bodyString);
+
+ $this->deferredReferenceList[$i]->resolve(
+ BodyResponseFactory::fromResponse($response)
+ );
+ }
}
}
-
- throw new CurlHandleMissingException($ch);
-}
-
-}#
+}
\ No newline at end of file
diff --git a/src/RequestResolverCurlException.php b/src/RequestResolverCurlException.php
deleted file mode 100644
index 04fff14..0000000
--- a/src/RequestResolverCurlException.php
+++ /dev/null
@@ -1,4 +0,0 @@
-headers = new Headers();
- $this->deferredResponse = $deferredResponse;
-}
-
-public function __get($name) {
- switch($name) {
- case "status":
- return $this->statusCode;
- break;
-
- default:
- trigger_error("Undefined property: "
- . __CLASS__
- . "::\$"
- . $name
- , E_USER_NOTICE
- );
- return null;
- }
-}
-
-public function stream($curlHandle, string $data):int {
- $bytesRead = strlen($data);
-
- if($this->streamTarget === self::STREAM_TARGET_HEADERS) {
- if ($this->setHeaders($data) !== true) {
- $this->streamTarget = self::STREAM_TARGET_BODY;
- $this->curlInfo = curl_getinfo($curlHandle);
- $this->deferredResponse->resolve($this);
- }
- }
-
- if($this->streamTarget === self::STREAM_TARGET_BODY) {
- $this->rawBody .= $data;
-
- foreach ($this->readRawBodyDeferredArray as $readRawBodyDeferred) {
- if (is_callable([$readRawBodyDeferred, "notify"])) {
- $readRawBodyDeferred->notify($data);
- }
- }
- }
-
- return $bytesRead;
-}
-
-/**
- * Called when the underlying curl handle completes. At this point, all of the
- * response has arrived, so we can resolve any functions reading the body.
- *
- * Each deferred reader has its own transform function to manupulate the body
- * into the expected format, which is called within the same iteration.
- *
- * @param $statusCode int The HTTP status code of the completed response
- */
-public function complete(int $statusCode) {
- $this->statusCode = $statusCode;
- foreach($this->readRawBodyDeferredArray as $i => $readRawBodyDeferred) {
- $readRawBodyDeferred->resolve(
- $this->readRawBodyDeferredTransformArray[$i]($this->rawBody)
- );
- }
-}
-
-public function redirect() {
-// TODO: Implement redirect()
- throw new \Exception("Method not yet implemented");
-}
-
-/**
- * Parses the raw header(s) provided as a string to this function and sets them
- * using the Headers object.
- *
- * @param string $rawHeader The unprocessed HTTP header string, direct from the
- * web server
- *
- * @return bool True if the header(s) have been set, false if the header section
- * has ended
- */
-private function setHeaders(string $rawHeader):bool {
- foreach($this->parseHeaders($rawHeader) as $header => $value) {
- if(empty($header)
- && empty($value)) {
- return false;
- }
-
- $this->headers->append($header, $value);
- }
-
- return true;
-}
-
-/**
- * Parses provided header string, returning KVP array.
- * Code taken from http://php.net/manual/bg/function.http-parse-headers.php
- * as not all systems will have PECL HTTP extension installed.
- *
- * @param $rawHeaders string The raw headers to be parsed
- * @return array An array of headers
- */
-private function parseHeaders(string $rawHeaders):array {
- $headers = [];
- $key = "";
-
- foreach(explode("\n", $rawHeaders) as $i => $h) {
- $h = explode(":", $h, 2);
-
- if(isset($h[1])) {
- if(!isset($headers[$h[0]])) {
- $headers[$h[0]] = trim($h[1]);
- }
- else if(is_array($headers[$h[0]])) {
- $headers[$h[0]] = array_merge(
- $headers[$h[0]],
- array(trim($h[1]))
- );
- }
- else {
- $headers[$h[0]] = array_merge(
- array($headers[$h[0]]),
- array(trim($h[1]))
- );
- }
-
- $key = $h[0];
- }
- else {
- if(substr($h[0], 0, 1) === "\t") {
- $headers[$key] .= "\r\n\t" . trim($h[0]);
- }
- else if(!$key) {
- if(empty($headers[0])) {
- $headers[0] = trim($h[0]);
- }
- }
- }
- }
-
- return $headers;
-}
-
-
-public function clone() {
-// TODO: Implement clone()
- throw new \Exception("Method not yet implemented");
-}
-
-public function error() {
-// TODO: Implement error()
- throw new \Exception("Method not yet implemented");
-}
-
-/**
- * Extracts and returns the character set value from the Content-Type header
- * value of $this object, if set. If not set, or none is found, the default
- * encoding type is returned.
- *
- * @return string The character set used to store body text.
- */
-private function getCharset():string {
- $charset = mb_internal_encoding();
-
- if(isset($this->headers)
- && $this->headers->has("Content-Type")) {
- $contentTypeString = $this->headers->get("Content-Type");
- $charsetEquals = "charset=";
-
- if(!strstr($contentTypeString, $charsetEquals)) {
- return $charset;
- }
-
- $charset = substr(
- $contentTypeString,
- strpos($contentTypeString, $charsetEquals) + strlen($charsetEquals)
- );
-
- $delimiterPosition = strpos($charset, ";");
- if($delimiterPosition > 0) {
- $charset = substr($charset, 0, $delimiterPosition);
- }
- }
-
- return $charset;
-}
-
-}#
diff --git a/test/unit/GlobalFetchHelperTest.php b/test/unit/GlobalFetchHelperTest.php
new file mode 100644
index 0000000..dace05d
--- /dev/null
+++ b/test/unit/GlobalFetchHelperTest.php
@@ -0,0 +1,37 @@
+ $httpMethod,
+ ];
+
+ $observerArray[$httpMethod] = $this->getMockBuilder(
+ GlobalFetchHelper::class
+ )
+ ->setMethods(["fetch"])
+ ->getMock();
+
+ $observerArray[$httpMethod]->expects($this->once())
+ ->method("fetch")
+ ->with($uri, $initArray);
+
+ $observerArray[$httpMethod]->$lowerCaseMethod($uri);
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/unit/Helper.php b/test/unit/Helper.php
deleted file mode 100644
index 1b305b3..0000000
--- a/test/unit/Helper.php
+++ /dev/null
@@ -1,4 +0,0 @@
-request(self::URL);
- $this->assertInstanceOf("\React\Promise\Promise", $promise);
-
- $promise2 = $http->all();
- $this->assertInstanceOf("\React\Promise\Promise", $promise2);
-}
-
-public function testCallbackInvoked() {
- $stubStdClass = $this->getMockBuilder(stdClass::class)
- ->setMethods(["mockCallback"])
- ->getMock();
- $stubStdClass->expects($this->once())
- ->method("mockCallback");
-
- $http = new Http();
- $http->request(self::URL)
- ->then([$stubStdClass, "mockCallback"]);
-
- $http->wait();
-}
-
-public function testMultipleCallbacksInvoked() {
- $stubStdClass = $this->getMockBuilder(stdClass::class)
- ->setMethods(["mockCallback1", "mockCallback2", "mockCallback3"])
- ->getMock();
- $stubStdClass->expects($this->once())
- ->method("mockCallback1");
- $stubStdClass->expects($this->once())
- ->method("mockCallback2");
- $stubStdClass->expects($this->once())
- ->method("mockCallback3");
-
- $http = new Http();
- $http->request(self::URL)
- ->then([$stubStdClass, "mockCallback1"])
- ->then([$stubStdClass, "mockCallback2"]);
-
- $http->request(self::URL)
- ->then([$stubStdClass, "mockCallback3"]);
-
- $http->wait();
-}
-
-public function testResponseType() {
- $http = new Http();
- $http->request(self::URL)
- ->then(function($response) {
- $this->assertInstanceOf("\Gt\Fetch\Response", $response);
- });
- $http->wait();
-}
-
-public function testAllMethod() {
- $stubStdClass = $this->getMockBuilder(stdClass::class)
- ->setMethods(["mockCallback"])
- ->getMock();
- $stubStdClass->expects($this->once())
- ->method("mockCallback");
-
- $http = new Http();
- $http->request(self::URL);
-
- $http->all()->then([$stubStdClass, "mockCallback"]);
-}
-
-public function testShorthandMethods() {
- $http = new Http();
-
- foreach(["get","post","head","put","delete","options","patch"] as $method) {
- $http->$method(self::URL);
- }
-
- $this->setExpectedException("PHPUnit_Framework_Error");
- $http->notAMethod();
-}
-
-}#
\ No newline at end of file
diff --git a/test/unit/HttpTest.php b/test/unit/HttpTest.php
new file mode 100644
index 0000000..37663b4
--- /dev/null
+++ b/test/unit/HttpTest.php
@@ -0,0 +1,40 @@
+assertNotEmpty($http->getOptions());
+ }
+
+ public function testDefaultOptionsOverridden() {
+ $http = new Http();
+ $options = $http->getOptions();
+ $this->assertTrue($options[CURLOPT_FOLLOWLOCATION]);
+
+ $options = [
+ CURLOPT_FOLLOWLOCATION => false,
+ ];
+ $http = new Http($options);
+ $actualOptions = $http->getOptions();
+ $this->assertEquals(false, $actualOptions[CURLOPT_FOLLOWLOCATION]);
+ }
+
+ public function testEnsureStringUri() {
+ $http = new Http();
+ $uriToUse = Helper::URI_SIMPLE;
+ $request = new Request("GET", $uriToUse);
+
+ $this->assertEquals($uriToUse, $http->ensureUriInterface($request));
+ $this->assertEquals($uriToUse, $http->ensureUriInterface($uriToUse));
+ }
+
+}
\ No newline at end of file
diff --git a/test/unit/UriTest.php b/test/unit/UriTest.php
new file mode 100644
index 0000000..0d6b892
--- /dev/null
+++ b/test/unit/UriTest.php
@@ -0,0 +1,90 @@
+assertEquals("fake", $uri->getScheme());
+ $this->assertEquals("php.gt", $uri->getAuthority());
+ $this->assertEquals("", $uri->getUserInfo());
+ $this->assertEquals("php.gt", $uri->getHost());
+ $this->assertNull($uri->getPort());
+ $this->assertEquals("/fetch", $uri->getPath());
+ $this->assertEquals("", $uri->getQuery());
+ $this->assertEquals("", $uri->getFragment());
+ }
+
+ public function testComplexUrl() {
+ $uri = new Uri(Helper::URI_COMPLEX);
+
+ $this->assertEquals("fake", $uri->getScheme());
+ $this->assertEquals("someuser:somepassword@php.gt:8008", $uri->getAuthority());
+ $this->assertEquals("someuser:somepassword", $uri->getUserInfo());
+ $this->assertEquals("php.gt", $uri->getHost());
+ $this->assertEquals(8008, $uri->getPort());
+ $this->assertEquals("/fetch", $uri->getPath());
+ $this->assertEquals("id=105", $uri->getQuery());
+ $this->assertEquals("example", $uri->getFragment());
+ }
+
+ public function testWithScheme() {
+ $uri = new Uri(Helper::URI_SIMPLE);
+ $newUri = $uri->withScheme("updated");
+
+ $this->assertEquals("updated", $newUri->getScheme());
+ $this->assertEquals("updated://php.gt/fetch", (string)$newUri);
+ }
+
+ public function testWithUserInfo() {
+ $uri = new Uri(Helper::URI_SIMPLE);
+ $newUri = $uri->withUserInfo("admin", "secret");
+
+ $this->assertEquals("admin:secret", $newUri->getUserInfo());
+ $this->assertEquals("fake://admin:secret@php.gt/fetch", (string)$newUri);
+ }
+
+ public function testWithHost() {
+ $uri = new Uri(Helper::URI_SIMPLE);
+ $newUri = $uri->withHost("phpgt.com");
+
+ $this->assertEquals("phpgt.com", $newUri->getHost());
+ $this->assertEquals("fake://phpgt.com/fetch", (string)$newUri);
+ }
+
+ public function testWithPort() {
+ $uri = new Uri(Helper::URI_SIMPLE);
+ $newUri = $uri->withPort(1234);
+
+ $this->assertEquals(1234, $newUri->getPort());
+ $this->assertEquals("fake://php.gt:1234/fetch", (string)$newUri);
+ }
+
+ public function testWithPath() {
+ $uri = new Uri(Helper::URI_SIMPLE);
+ $newUri = $uri->withPath("/webengine");
+
+ $this->assertEquals("/webengine", $newUri->getPath());
+ $this->assertEquals("fake://php.gt/webengine", (string)$newUri);
+ }
+
+ public function testWithQuery() {
+ $uri = new Uri(Helper::URI_SIMPLE);
+ $newUri = $uri->withQuery("name=Scarlett");
+
+ $this->assertEquals("name=Scarlett", $newUri->getQuery());
+ $this->assertEquals("fake://php.gt/fetch?name=Scarlett", (string)$newUri);
+ }
+
+ public function testWithFragment() {
+ $uri = new Uri(Helper::URI_SIMPLE);
+ $newUri = $uri->withFragment("example");
+
+ $this->assertEquals("example", $newUri->getFragment());
+ $this->assertEquals("fake://php.gt/fetch#example", (string)$newUri);
+ }
+}
\ No newline at end of file
diff --git a/test/unit/phpunit.xml b/test/unit/phpunit.xml
new file mode 100644
index 0000000..2aceb67
--- /dev/null
+++ b/test/unit/phpunit.xml
@@ -0,0 +1,19 @@
+
+
+
+
+ .
+
+
+
+
+
+
+
+
+
+
+ ../../src
+
+
+
\ No newline at end of file