From ab17646eecc29e572ffd213266685d75ac67663c Mon Sep 17 00:00:00 2001 From: Julien Rosset Date: Sat, 4 Sep 2021 15:58:13 +0200 Subject: [PATCH] Replace cUrl by Guzzle and code corrections --- composer.json | 7 +- composer.lock | 448 +++++++++++++++++++++++++++++++++++++++++++++- php/Connector.php | 66 ++++--- 3 files changed, 488 insertions(+), 33 deletions(-) diff --git a/composer.json b/composer.json index 2db254d..f965eb1 100644 --- a/composer.json +++ b/composer.json @@ -2,10 +2,11 @@ "description": "A connector between Gitea and Packagist for auto-update", "minimum-stability": "stable", - "require": { + "require": { "php": "~7.4 || ~8.0", - "ext-curl": "*", - "jrosset/envreader": "^1.0" + "ext-mbstring": "*", + "jrosset/envreader": "^1.0", + "guzzlehttp/guzzle": "^7.0" }, "autoload": { "psr-4": { diff --git a/composer.lock b/composer.lock index 20b1af8..440f197 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,246 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "1823efd4243bab20abda1d1730af4490", + "content-hash": "2de9bc5a9feb1c9ce48a719b94bbb0f0", "packages": [ + { + "name": "guzzlehttp/guzzle", + "version": "7.3.0", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "7008573787b430c1c1f650e3722d9bba59967628" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/7008573787b430c1c1f650e3722d9bba59967628", + "reference": "7008573787b430c1c1f650e3722d9bba59967628", + "shasum": "" + }, + "require": { + "ext-json": "*", + "guzzlehttp/promises": "^1.4", + "guzzlehttp/psr7": "^1.7 || ^2.0", + "php": "^7.2.5 || ^8.0", + "psr/http-client": "^1.0" + }, + "provide": { + "psr/http-client-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.4.1", + "ext-curl": "*", + "php-http/client-integration-tests": "^3.0", + "phpunit/phpunit": "^8.5.5 || ^9.3.5", + "psr/log": "^1.1" + }, + "suggest": { + "ext-curl": "Required for CURL handler support", + "ext-intl": "Required for Internationalized Domain Name (IDN) support", + "psr/log": "Required for using the Log middleware" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "7.3-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://sagikazarmark.hu" + } + ], + "description": "Guzzle is a PHP HTTP client library", + "homepage": "http://guzzlephp.org/", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "psr-18", + "psr-7", + "rest", + "web service" + ], + "support": { + "issues": "https://github.com/guzzle/guzzle/issues", + "source": "https://github.com/guzzle/guzzle/tree/7.3.0" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://github.com/alexeyshockov", + "type": "github" + }, + { + "url": "https://github.com/gmponos", + "type": "github" + } + ], + "time": "2021-03-23T11:33:13+00:00" + }, + { + "name": "guzzlehttp/promises", + "version": "1.4.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/promises.git", + "reference": "8e7d04f1f6450fef59366c399cfad4b9383aa30d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/promises/zipball/8e7d04f1f6450fef59366c399cfad4b9383aa30d", + "reference": "8e7d04f1f6450fef59366c399cfad4b9383aa30d", + "shasum": "" + }, + "require": { + "php": ">=5.5" + }, + "require-dev": { + "symfony/phpunit-bridge": "^4.4 || ^5.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Promise\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Guzzle promises library", + "keywords": [ + "promise" + ], + "support": { + "issues": "https://github.com/guzzle/promises/issues", + "source": "https://github.com/guzzle/promises/tree/1.4.1" + }, + "time": "2021-03-07T09:25:29+00:00" + }, + { + "name": "guzzlehttp/psr7", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/guzzle/psr7.git", + "reference": "1dc8d9cba3897165e16d12bb13d813afb1eb3fe7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/1dc8d9cba3897165e16d12bb13d813afb1eb3fe7", + "reference": "1dc8d9cba3897165e16d12bb13d813afb1eb3fe7", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.0", + "ralouphie/getallheaders": "^3.0" + }, + "provide": { + "psr/http-factory-implementation": "1.0", + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.4.1", + "http-interop/http-factory-tests": "^0.9", + "phpunit/phpunit": "^8.5.8 || ^9.3.10" + }, + "suggest": { + "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Psr7\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Tobias Schultze", + "homepage": "https://github.com/Tobion" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://sagikazarmark.hu" + } + ], + "description": "PSR-7 message implementation that also provides common utility methods", + "keywords": [ + "http", + "message", + "psr-7", + "request", + "response", + "stream", + "uri", + "url" + ], + "support": { + "issues": "https://github.com/guzzle/psr7/issues", + "source": "https://github.com/guzzle/psr7/tree/2.0.0" + }, + "time": "2021-06-30T20:03:07+00:00" + }, { "name": "jrosset/envreader", "version": "v1.0.0", @@ -88,6 +326,210 @@ "wiki": "https://git.jrosset.ovh/jrosset/PhpSingleton/wiki" }, "time": "2021-09-03T16:34:55+00:00" + }, + { + "name": "psr/http-client", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-client.git", + "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", + "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0", + "psr/http-message": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP clients", + "homepage": "https://github.com/php-fig/http-client", + "keywords": [ + "http", + "http-client", + "psr", + "psr-18" + ], + "support": { + "source": "https://github.com/php-fig/http-client/tree/master" + }, + "time": "2020-06-29T06:28:15+00:00" + }, + { + "name": "psr/http-factory", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-factory.git", + "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/12ac7fcd07e5b077433f5f2bee95b3a771bf61be", + "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be", + "shasum": "" + }, + "require": { + "php": ">=7.0.0", + "psr/http-message": "^1.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 interfaces for PSR-7 HTTP message factories", + "keywords": [ + "factory", + "http", + "message", + "psr", + "psr-17", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-factory/tree/master" + }, + "time": "2019-04-30T12:38:16+00:00" + }, + { + "name": "psr/http-message", + "version": "1.0.1", + "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" + ], + "support": { + "source": "https://github.com/php-fig/http-message/tree/master" + }, + "time": "2016-08-06T14:39:51+00:00" + }, + { + "name": "ralouphie/getallheaders", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/ralouphie/getallheaders.git", + "reference": "120b605dfeb996808c31b6477290a714d356e822" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", + "reference": "120b605dfeb996808c31b6477290a714d356e822", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.1", + "phpunit/phpunit": "^5 || ^6.5" + }, + "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.", + "support": { + "issues": "https://github.com/ralouphie/getallheaders/issues", + "source": "https://github.com/ralouphie/getallheaders/tree/develop" + }, + "time": "2019-03-08T08:55:37+00:00" } ], "packages-dev": [ ], @@ -97,8 +539,8 @@ "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": "~7.4 || ~8.0", - "ext-curl": "*" + "php": "~7.4 || ~8.0", + "ext-mbstring": "*" }, "platform-dev": [ ], "plugin-api-version": "2.1.0" diff --git a/php/Connector.php b/php/Connector.php index a26df0d..805ee3c 100644 --- a/php/Connector.php +++ b/php/Connector.php @@ -2,6 +2,8 @@ namespace SiteWeb; +use GuzzleHttp\Client; +use GuzzleHttp\RequestOptions; use stdClass; use Throwable; @@ -20,10 +22,9 @@ class Connector { $packagist->apiToken = Env::getInstance()->getProperty(Env::PROPERTY_PACKAGIST_APITOKEN); } catch (Throwable $e) { - $this->exitError('Invalid environment: ' . $e->getMessage()); + $this->exitError('Invalid environment: [' . get_class($e) . '] ' . $e->getMessage()); } //endregion - //region Check request method and content type $requestMethod = mb_strtoupper(trim($_SERVER['REQUEST_METHOD'] ?? '')); if ($requestMethod !== 'POST') { @@ -38,18 +39,18 @@ class Connector { //region Check payload $payload = trim(file_get_contents("php://input")); if (empty($payload)) { - $this->exitError('No payload'); + $this->exitError('No Gitea payload'); } $payloadSignatureExpected = $_SERVER['HTTP_X_GITEA_SIGNATURE'] ?? ''; if (empty($payloadSignatureExpected)) { - $this->exitError('No payload signature'); + $this->exitError('No Gitea payload signature'); } $payloadSignature = hash_hmac('sha256', $payload, $packagist->apiToken, false); if ($payloadSignatureExpected !== $payloadSignature) { - $this->exitError('Payload signatures don\'t match'); + $this->exitError('Gitea payload signatures don\'t match'); } $giteaData = new stdClass(); @@ -57,39 +58,50 @@ class Connector { $giteaData = json_decode($payload, false, 512, JSON_THROW_ON_ERROR); } catch (Throwable $e) { - $this->exitError('Invalid payload (JSON decoding failed): ' . $e->getMessage()); + $this->exitError('Invalid Gitea payload (JSON decoding failed): [' . get_class($e) . '] ' . $e->getMessage()); } //endregion //region Build Packagist data $packagistData = new stdClass(); $packagistData->repository = new stdClass(); - $packagistData->repository->url = 'https://git.jrosset.ovh/' . $giteaData->full_name; - //endregion + $packagistData->repository->url = $giteaData->repository->html_url; - //region Send data to Packagist - $cUrl = curl_init('https://packagist.org/api/update-package?username=' . $packagist->username . '&apiToken=' . $packagist->apiToken); - curl_setopt($cUrl, CURLOPT_POST, 1); - curl_setopt($cUrl, CURLOPT_RETURNTRANSFER, 1); - curl_setopt($cUrl, CURLOPT_HEADER, 1); - curl_setopt($cUrl, CURLOPT_POSTFIELDS, $packagistData); - curl_setopt($cUrl, CURLOPT_SSL_VERIFYPEER, 1); - curl_setopt($cUrl, CURLOPT_SSL_VERIFYHOST, 2); - curl_setopt($cUrl, CURLOPT_FORBID_REUSE, 1); - if (($response = curl_exec($cUrl)) === false) { - $this->exitError('Failed to send data: cUrl failed'); + $packagistDataJSON = null; + try { + $packagistDataJSON = json_encode($packagistData, JSON_THROW_ON_ERROR); + } + catch (Throwable $e) { + $this->exitError('Invalid Packagist payload (JSON encoding failed): [' . get_class($e) . '] ' . $e->getMessage()); } //endregion - //region Treat response - $responseCode = curl_getinfo($cUrl, CURLINFO_RESPONSE_CODE); - $responseHeadersSize = curl_getinfo($cUrl, CURLINFO_HEADER_SIZE); - $responseHeaders = preg_split('/\r?\n/', substr($response, 0, $responseHeadersSize)); - foreach ($responseHeaders as $responseHeader) { - header($responseHeader, true, $responseCode); + //region Send data to Packagist + $response = null; + try { + $request = new Client(); + $response = $request->post( + 'https://packagist.org/api/update-package', + [ + RequestOptions::QUERY => [ + 'username' => $packagist->username, + 'apiToken' => $packagist->apiToken, + ], + RequestOptions::HTTP_ERRORS => false, + RequestOptions::HEADERS => [ + 'Content-Type' => 'application/json', + ], + RequestOptions::BODY => $packagistDataJSON, + ] + ); } - - echo substr($response, $responseHeadersSize); // Response body + catch (Throwable $e) { + $this->exitError('Failed to send data: ' . $e->getMessage()); + } + //endregion + //region Return the Packagist response + header('Content-Type: application/json', true, $response->getStatusCode()); + echo $response->getBody(); exit; //endregion }