Spaces:
Sleeping
Sleeping
Delete api/hf_proxy.php
Browse files- api/hf_proxy.php +0 -116
api/hf_proxy.php
DELETED
|
@@ -1,116 +0,0 @@
|
|
| 1 |
-
<?php
|
| 2 |
-
header('Content-Type: application/json; charset=utf-8');
|
| 3 |
-
header('Access-Control-Allow-Origin: *');
|
| 4 |
-
header('Access-Control-Allow-Methods: POST, OPTIONS');
|
| 5 |
-
header('Access-Control-Allow-Headers: Content-Type');
|
| 6 |
-
|
| 7 |
-
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') { http_response_code(204); exit; }
|
| 8 |
-
if ($_SERVER['REQUEST_METHOD'] !== 'POST') { http_response_code(405); exit; }
|
| 9 |
-
|
| 10 |
-
$hfKey = $_ENV['HF_API_KEY'] ?? $_SERVER['HF_API_KEY'] ?? getenv('HF_API_KEY') ?? '';
|
| 11 |
-
|
| 12 |
-
// Fallback a archivo .env si la variable de entorno no esta definida
|
| 13 |
-
if (!$hfKey && file_exists(__DIR__ . '/.env')) {
|
| 14 |
-
foreach (file(__DIR__ . '/.env', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) as $line) {
|
| 15 |
-
if (str_starts_with($line, 'HF_API_KEY=')) { $hfKey = trim(substr($line, 11)); break; }
|
| 16 |
-
}
|
| 17 |
-
}
|
| 18 |
-
|
| 19 |
-
if (!$hfKey) { http_response_code(503); echo json_encode(['error' => 'Servicio no configurado.']); exit; }
|
| 20 |
-
|
| 21 |
-
$body = json_decode(file_get_contents('php://input'), true);
|
| 22 |
-
$SPACE = 'https://blackmistcode-morphos-medgemma.hf.space/gradio_api';
|
| 23 |
-
$auth = ['Content-Type: application/json', "Authorization: Bearer $hfKey"];
|
| 24 |
-
|
| 25 |
-
set_time_limit(120);
|
| 26 |
-
|
| 27 |
-
function hf_get(string $url, array $headers, ?string $post = null): array {
|
| 28 |
-
$ch = curl_init($url);
|
| 29 |
-
curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => $headers, CURLOPT_TIMEOUT => 120]);
|
| 30 |
-
if ($post !== null) { curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $post); }
|
| 31 |
-
return [curl_exec($ch), curl_getinfo($ch, CURLINFO_HTTP_CODE)];
|
| 32 |
-
}
|
| 33 |
-
|
| 34 |
-
function uploadImagen(string $space, string $hfKey, string $dataUrl): ?array {
|
| 35 |
-
if (!preg_match('/^data:(image\/[\w+]+);base64,(.+)$/s', $dataUrl, $m)) return null;
|
| 36 |
-
$mimeType = $m[1];
|
| 37 |
-
$ext = explode('/', $mimeType)[1] ?? 'jpg';
|
| 38 |
-
$binary = base64_decode($m[2]);
|
| 39 |
-
if ($binary === false) return null;
|
| 40 |
-
|
| 41 |
-
// Construye manualmente el cuerpo multipart para enviar la imagen al upload endpoint de Gradio
|
| 42 |
-
$boundary = bin2hex(random_bytes(16));
|
| 43 |
-
$body = "--$boundary\r\n"
|
| 44 |
-
. "Content-Disposition: form-data; name=\"files\"; filename=\"image.$ext\"\r\n"
|
| 45 |
-
. "Content-Type: $mimeType\r\n\r\n"
|
| 46 |
-
. $binary
|
| 47 |
-
. "\r\n--$boundary--\r\n";
|
| 48 |
-
|
| 49 |
-
$ch = curl_init("$space/upload");
|
| 50 |
-
curl_setopt_array($ch, [
|
| 51 |
-
CURLOPT_RETURNTRANSFER => true,
|
| 52 |
-
CURLOPT_POST => true,
|
| 53 |
-
CURLOPT_POSTFIELDS => $body,
|
| 54 |
-
CURLOPT_HTTPHEADER => [
|
| 55 |
-
"Authorization: Bearer $hfKey",
|
| 56 |
-
"Content-Type: multipart/form-data; boundary=$boundary",
|
| 57 |
-
],
|
| 58 |
-
CURLOPT_TIMEOUT => 60,
|
| 59 |
-
]);
|
| 60 |
-
$result = curl_exec($ch);
|
| 61 |
-
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
| 62 |
-
curl_close($ch);
|
| 63 |
-
|
| 64 |
-
// Si el upload falla, devuelve la imagen inline para que el modelo la procese igualmente
|
| 65 |
-
if ($code >= 400 || !$result) {
|
| 66 |
-
return ['url' => $dataUrl, 'orig_name' => "image.$ext", 'mime_type' => $mimeType];
|
| 67 |
-
}
|
| 68 |
-
|
| 69 |
-
$files = json_decode($result, true);
|
| 70 |
-
$path = is_array($files) && isset($files[0]) ? $files[0] : null;
|
| 71 |
-
if (!$path) {
|
| 72 |
-
return ['url' => $dataUrl, 'orig_name' => "image.$ext", 'mime_type' => $mimeType];
|
| 73 |
-
}
|
| 74 |
-
|
| 75 |
-
return [
|
| 76 |
-
'path' => $path,
|
| 77 |
-
'url' => "$space/file=" . $path,
|
| 78 |
-
'orig_name' => "image.$ext",
|
| 79 |
-
'mime_type' => $mimeType,
|
| 80 |
-
];
|
| 81 |
-
}
|
| 82 |
-
|
| 83 |
-
$rawImages = array_slice(array_values($body['images'] ?? []), 0, 4);
|
| 84 |
-
$data = [];
|
| 85 |
-
foreach ($rawImages as $img) {
|
| 86 |
-
$data[] = $img ? uploadImagen($SPACE, $hfKey, $img) : null;
|
| 87 |
-
}
|
| 88 |
-
while (count($data) < 4) $data[] = null;
|
| 89 |
-
$data[] = $body['prompt'] ?? '';
|
| 90 |
-
|
| 91 |
-
[$submitBody, $code] = hf_get("$SPACE/call/analyze", $auth, json_encode(['data' => $data]));
|
| 92 |
-
|
| 93 |
-
if ($code >= 400) { http_response_code(502); echo json_encode(['error' => "Error Space: HTTP $code"]); exit; }
|
| 94 |
-
|
| 95 |
-
$eventId = json_decode($submitBody, true)['event_id'] ?? null;
|
| 96 |
-
if (!$eventId) { http_response_code(502); echo json_encode(['error' => 'No se obtuvo event_id.']); exit; }
|
| 97 |
-
|
| 98 |
-
[$stream] = hf_get("$SPACE/call/analyze/$eventId", ["Authorization: Bearer $hfKey"]);
|
| 99 |
-
|
| 100 |
-
$result = $error = null; $lastEvent = '';
|
| 101 |
-
// Parsea el stream SSE de Gradio buscando el evento 'complete' o 'process_completed'
|
| 102 |
-
foreach (explode("\n", $stream) as $raw) {
|
| 103 |
-
$line = rtrim($raw, "\r");
|
| 104 |
-
if (str_starts_with($line, 'event:')) $lastEvent = trim(substr($line, 6));
|
| 105 |
-
elseif (str_starts_with($line, 'data:')) {
|
| 106 |
-
$parsed = json_decode(trim(substr($line, 5)), true);
|
| 107 |
-
if (in_array($lastEvent, ['complete', 'process_completed']))
|
| 108 |
-
$result = is_array($parsed) ? $parsed[0] : ($parsed['output'] ?? $parsed);
|
| 109 |
-
elseif ($lastEvent === 'error')
|
| 110 |
-
$error = $parsed['error'] ?? 'Error del modelo.';
|
| 111 |
-
}
|
| 112 |
-
}
|
| 113 |
-
|
| 114 |
-
if ($error) { http_response_code(503); echo json_encode(['error' => $error]); }
|
| 115 |
-
elseif ($result !== null) { echo json_encode(['text' => $result]); }
|
| 116 |
-
else { http_response_code(502); echo json_encode(['error' => 'Sin respuesta del modelo.']); }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|