fn_b/app/Console/Commands/EditorialRequest.php

62 lines
2.7 KiB
PHP

<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Http;
final class EditorialRequest extends Command
{
protected $signature = 'editorial:request {method} {path} {--payload=} {--image=}';
protected $description = 'Call this environment\'s editorial API without exposing the credential';
public function handle(): int
{
$path = $this->argument('path');
$method = strtoupper($this->argument('method'));
if (! preg_match('~\A[a-zA-Z0-9_/-]+\z~', $path) || str_contains($path, '..') || ! in_array($method, ['GET', 'POST'])) {
$this->error('Invalid API operation.');
return 1;
}
$file = config('editorial.credential_file');
$credential = is_file($file) ? json_decode(file_get_contents($file), true) : null;
if (! $credential || ($credential['environment'] ?? '') !== app()->environment() || ($credential['project'] ?? '') !== 'fna-v3'
|| ($credential['base_url'] ?? '') !== config('editorial.base_url')) {
$this->error('Credential binding mismatch.');
return 1;
}
$base = rtrim(config('editorial.base_url'), '/');
if (app()->environment('local') && ! in_array(parse_url($base, PHP_URL_HOST), ['fna-v3.loc', 'localhost', '127.0.0.1'])) {
$this->error('Local client refuses a nonlocal target.');
return 1;
}
try {
$request = Http::withOptions(['proxy' => '', 'allow_redirects' => false])->withToken($credential['fields']['api_key'])->acceptJson()->connectTimeout(3)->timeout(30);
if ($this->option('image')) {
$image = $this->option('image');
if (! is_file($image)) {
$this->error('Image not found.');
return 1;
}
$response = $request->attach('image', fopen($image, 'r'), basename($image))->post($base.'/api/editorial/v1/'.$path);
} else {
$payload = $this->option('payload') ? json_decode(file_get_contents($this->option('payload')), true, 512, JSON_THROW_ON_ERROR) : [];
$response = $request->send($method, $base.'/api/editorial/v1/'.$path, $method === 'GET' ? [] : ['json' => $payload]);
}
$data = $response->json();
$this->line(json_encode(['http_status' => $response->status(), 'data' => $data], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
return $response->successful() ? 0 : 1;
} catch (\Throwable) {
$this->error('Editorial request failed; credential and request headers were not displayed.');
return 1;
}
}
}