query('SELECT 1'); JsonResponse::ok([ 'status' => 'ok', 'service' => 'url-shortener', 'db' => 'connected', ]); } if ($uri === '/api/v1/shorten') { if ($method === 'GET') { $result = ShortenService::handle( (string) ($_GET['url'] ?? ''), (string) ($_GET['bearer'] ?? ''), (string) ($_GET['signer'] ?? ''), isset($_GET['ttl']) ? (int) $_GET['ttl'] : null ); } elseif ($method === 'POST') { $raw = file_get_contents('php://input') ?: ''; $body = json_decode($raw, true); if (!is_array($body)) { JsonResponse::error(400, 'INVALID_URL', 'expected JSON body'); } $result = ShortenService::handle( (string) ($body['url'] ?? ''), (string) ($body['bearer'] ?? ''), (string) ($body['signer'] ?? ''), isset($body['ttl']) ? (int) $body['ttl'] : null ); } else { JsonResponse::error(405, 'INTERNAL', 'method not allowed'); } $http = (int) ($result['http'] ?? 200); unset($result['http']); if (($result['code'] ?? '') === '0') { JsonResponse::ok($result, $http); } JsonResponse::error($http, (string) $result['code'], (string) $result['desc'], [ 'url' => $result['url'] ?? '', 'bearer' => $result['bearer'] ?? '', ]); } if (preg_match('#^/api/v1/qr/([a-f0-9]{6,16})\.png$#', $uri, $m)) { $size = isset($_GET['size']) ? (int) $_GET['size'] : 256; QrHandler::handle($m[1], $size); } if (preg_match('#^/([a-f0-9]{6,16})$#', $uri, $m)) { if ($method === 'GET' || $method === 'HEAD') { RedirectHandler::handle($m[1], $method); } JsonResponse::error(405, 'INTERNAL', 'method not allowed'); } http_response_code(404); header('Content-Type: application/json; charset=utf-8'); echo json_encode(['code' => 'NOT_FOUND', 'desc' => 'not found'], JSON_UNESCAPED_SLASHES); } catch (Throwable $e) { error_log('url-shortener: ' . $e->getMessage()); JsonResponse::error(500, 'INTERNAL', 'server error'); }