flysystem-rackspace icon indicating copy to clipboard operation
flysystem-rackspace copied to clipboard

Seems not to work with PHP8 - Guzzle issue?

Open edgreenberg-mri opened this issue 1 year ago • 1 comments

Instantiating Flysystem/Rackspace fails with PHP8. I've had this working with PHP7.4 for at least a year or so.

On PHP8, we get:

Deprecated: Required parameter $archive follows optional parameter $path in /var/www/html/includes/vendor/rackspace/php-opencloud/lib/OpenCloud/ObjectStore/Service.php on line 167
PHP Fatal error:  Uncaught Guzzle\Common\Exception\InvalidArgumentException: Invalid handle provided in /var/www/html/includes/vendor/guzzle/guzzle/src/Guzzle/Http/Curl/CurlHandle.php:237
Stack trace:
#0 /var/www/html/includes/vendor/guzzle/guzzle/src/Guzzle/Http/Curl/CurlHandle.php(223): Guzzle\Http\Curl\CurlHandle->__construct()
... and so on

Any fix for this?

edgreenberg-mri avatar Mar 15 '23 12:03 edgreenberg-mri

The dependency rackspace/php-opencloud (which itself has this old guzzle as a dependency) is no longer supported and they recommend switching to php-opencloud/openstack

There are several flysystem adapters for openstack such as: https://github.com/chrisnharvey/flysystem-openstack-swift https://github.com/webalternatif/flysystem-openstack-swift

Here's some code to help you get started, as authenticating Rackspace through OpenStack isn't exactly straightforward.

This uses php-opencloud/openstack v3.10.0

$authUrl = 'https://identity.api.rackspacecloud.com/v2.0/';

$httpClient = new \GuzzleHttp\Client([
	'base_uri' => \OpenStack\Common\Transport\Utils::normalizeUrl($authUrl),
	'handler'  => \GuzzleHttp\HandlerStack::create(),
]);

$openstack = new \OpenStack\OpenStack([
	'authUrl'         => $authUrl,
	'identityService' => RackspaceIdentityService::factory($httpClient),
	'region'          => '{{ ADD RACKSPACE REGION }}',
	'user'            => [
		'username' => '{{ ADD RACKSPACE USERNAME HERE }}',
		'apiKey'   => '{{ ADD RACKSPACE API KEY HERE }}',
	],
]);

$container = $openstack->objectStoreV1([
	'catalogName' => 'cloudFiles',
])
	->getContainer('{{ ADD CONTAINER NAME HERE }}');

$adapter = new \Nimbusoft\Flysystem\OpenStack\SwiftAdapter($container);
$filesystem = new \League\Flysystem\Filesystem($adapter);

You also need to create the identity service referenced in the code:

use OpenStack\Common\Auth\IdentityService;
use OpenStack\Identity\v2\Models\Catalog;
use OpenStack\Identity\v2\Models\Token;
use OpenStack\Identity\v2\Service as V2Service;

class RackspaceIdentityService extends V2Service implements IdentityService
{
	public function authenticate(array $options = []): array
	{
		$response = $this->execute([
			'method'   => 'POST',
			'path'     => 'tokens',
			'skipAuth' => true,
			'params'   => [
				'username'   => [
					'type'     => 'string',
					'required' => true,
					'path'     => 'auth.RAX-KSKEY:apiKeyCredentials',
				],
				'apiKey'   => [
					'type'     => 'string',
					'required' => true,
					'path'     => 'auth.RAX-KSKEY:apiKeyCredentials',
				],
			],
		], $options['user']);

		$token = $this->model(Token::class, $response);

		$serviceUrl = $this->model(Catalog::class, $response)->getServiceUrl(
			$options['catalogName'],
			$options['catalogType'],
			$options['region'],
			$options['urlType']
		);

		return [$token, $serviceUrl];
	}
}

colethorsen avatar Sep 23 '24 21:09 colethorsen