Skip to content

Instantly share code, notes, and snippets.

@wlkns
Created May 25, 2023 07:47
Show Gist options
  • Save wlkns/e3e6a83298df789d05c54a2aa0762e0b to your computer and use it in GitHub Desktop.
Save wlkns/e3e6a83298df789d05c54a2aa0762e0b to your computer and use it in GitHub Desktop.
Laravel HTTP Proxy Filesystem Adapter
<?php
namespace App\Filesystem\Adapters;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Str;
use League\Flysystem\Config;
use League\Flysystem\FileAttributes;
use League\Flysystem\FilesystemAdapter;
use League\Flysystem\FilesystemException;
/**
* Provides a http proxy filestore.
*/
class HttpProxyAdapter implements FilesystemAdapter
{
private string $base;
public function __construct(string $base)
{
if ( ! Str::startsWith($base, ['http://', 'https://'])) {
throw new \Exception('Filesystem base must start with http:// or https://');
}
$this->base = Str::finish($base, '/');
}
public function fileExists(string $path): bool
{
return true;
}
public function directoryExists(string $path): bool
{
return true;
}
public function write(string $path, string $contents, Config $config): void
{
$this->throwUnsupportedException(__FUNCTION__);
}
public function writeStream(string $path, $contents, Config $config): void
{
$this->throwUnsupportedException(__FUNCTION__);
}
public function httpUrl(string $path): string
{
return $this->base . $path;
}
public function read(string $path): string
{
$response = Http::withOptions($this->httpOptions())->get($this->httpUrl($path));
if ( ! $response->successful()) {
return false;
}
return $response->body();
}
public function readStream(string $path)
{
$response = Http::withOptions($this->httpOptions(['stream' => true]))->get($this->httpUrl($path));
return $response->getBody()->detach();
}
public function delete(string $path): void
{
$this->throwUnsupportedException(__FUNCTION__);
}
public function deleteDirectory(string $path): void
{
$this->throwUnsupportedException(__FUNCTION__);
}
public function createDirectory(string $path, Config $config): void
{
$this->throwUnsupportedException(__FUNCTION__);
}
public function setVisibility(string $path, string $visibility): void
{
$this->throwUnsupportedException(__FUNCTION__);
}
public function visibility(string $path): FileAttributes
{
return $this->getFileAttributes($path);
}
public function mimeType(string $path): FileAttributes
{
return $this->getFileAttributes($path);
}
public function lastModified(string $path): FileAttributes
{
return $this->getFileAttributes($path);
}
public function fileSize(string $path): FileAttributes
{
return $this->getFileAttributes($path);
}
public function listContents(string $path, bool $deep): iterable
{
return [];
}
public function move(string $source, string $destination, Config $config): void
{
$this->throwUnsupportedException(__FUNCTION__);
}
public function copy(string $source, string $destination, Config $config): void
{
$this->throwUnsupportedException(__FUNCTION__);
}
private function throwUnsupportedException($function)
{
throw new FilesystemException("Not possible to {$function} using this driver.");
}
private function httpOptions(array $options = []): array
{
return array_merge(
['verify' => false],
$options
);
}
private function getFileAttributes(string $path)
{
$response = Http::withOptions($this->httpOptions())->head($this->httpUrl($path));
if ( ! $response->ok()) {
throw new FilesystemException("Unable to find file at: {$path}.");
}
return new FileAttributes(
$path,
$response->header('Content-Length') ?: 0,
null,
$response->header('Last-Modified') ? Carbon::parse($response->header('Last-Modified'))->getTimestamp() : null,
$response->header('Content-Type'),
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment