From de89c84316527f40834776c0fc58499534b93062 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E8=92=8B=E5=B0=8F=E9=99=8C?= <xiaomo.drip@gmail.com>
Date: Sat, 21 Dec 2024 00:26:37 +0800
Subject: [PATCH] 1111

---
 go.php | 135 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 135 insertions(+)
 create mode 100644 go.php

diff --git a/go.php b/go.php
new file mode 100644
index 0000000..76ccbaf
--- /dev/null
+++ b/go.php
@@ -0,0 +1,135 @@
+<?php
+
+use Swoole\Coroutine\Http\Server;
+use Swoole\Coroutine\Http\Client;
+use Swoole\Coroutine;
+
+$port = 9001;
+$apiEndpoint = 'https://oss.x-php.com/get/';
+$cacheDir = __DIR__ . '/.cache';
+$pathIndex = [];
+$viewsInfo = [
+    'request' => 0,
+    'cacheHit' => 0,
+    'apiCall' => 0,
+    'cacheCall' => 0,
+    'cacheReadError' => 0,
+    'fetchApiError' => 0,
+    'fetchApiWarning' => 0,
+];
+
+// Ensure cache directory exists
+if (!is_dir($cacheDir)) {
+    mkdir($cacheDir, 0777, true);
+}
+
+Swoole\Coroutine\run(function () use ($port, $apiEndpoint, $cacheDir, &$pathIndex, &$viewsInfo) {
+    $server = new Server('0.0.0.0', $port, false);
+
+    $server->set([
+        'daemonize' => true,
+    ]);
+
+    $server->handle('/', function ($request, $response) use ($apiEndpoint, $cacheDir, &$pathIndex, &$viewsInfo) {
+        $viewsInfo['request']++;
+
+        $uri = $request->server['request_uri'];
+        $parsedUrl = parse_url($uri);
+        parse_str($parsedUrl['query'] ?? '', $query);
+
+        $reqPath = explode('/', trim($parsedUrl['path'], '/'))[0] ?? '';
+        $token = implode('/', array_slice(explode('/', trim($parsedUrl['path'], '/')), 1));
+
+        if ($reqPath === 'endpoint') {
+            return sendJsonResponse($response, [
+                'code' => 200,
+                'data' => [
+                    'api' => $apiEndpoint,
+                    'port' => $port,
+                    'cacheDir' => $cacheDir,
+                    'pathIndexCount' => count($pathIndex),
+                    'viewsInfo' => $viewsInfo,
+                ],
+            ]);
+        }
+
+        if (empty($token) || $token === 'undefined') {
+            $token = $reqPath;
+            $reqPath = 'go';
+        }
+
+        if (!in_array($reqPath, ['avatar', 'go', 'bbs', 'www', 'url', 'thumb'])) {
+            return sendErrorResponse($response, 404, 'Not Found');
+        }
+
+        if (!$token) {
+            return sendErrorResponse($response, 400, 'Bad Request: Missing Token or path');
+        }
+
+        $uniqidhex = md5($reqPath . $token . ($query['sign'] ?? ''));
+
+        if (isset($pathIndex[$uniqidhex]) && isCacheValid($cacheDir, $pathIndex[$uniqidhex])) {
+            $viewsInfo['cacheHit']++;
+            return serveFromCache($cacheDir, $pathIndex[$uniqidhex], $response);
+        }
+
+        $viewsInfo['apiCall']++;
+        fetchApiData($apiEndpoint, $reqPath, $token, $query['sign'] ?? '', function ($apiData) use ($cacheDir, &$pathIndex, $uniqidhex, $response) {
+            if ($apiData['code'] === 200 && isset($apiData['data']['url'])) {
+                $pathIndex[$uniqidhex] = $uniqidhex;
+                file_put_contents("$cacheDir/$uniqidhex.meta", json_encode($apiData['data']));
+                file_put_contents("$cacheDir/$uniqidhex.content", file_get_contents($apiData['data']['url']));
+
+                serveFromCache($cacheDir, $uniqidhex, $response);
+            } else {
+                sendErrorResponse($response, 502, 'Bad Gateway: ' . json_encode($apiData));
+            }
+        });
+    });
+
+
+    $server->start();
+});
+
+function isCacheValid($cacheDir, $cacheFile) {
+    return file_exists("$cacheDir/$cacheFile.meta") && file_exists("$cacheDir/$cacheFile.content");
+}
+
+function serveFromCache($cacheDir, $cacheFile, $response) {
+    $cacheData = json_decode(file_get_contents("$cacheDir/$cacheFile.meta"), true);
+    $response->header('Content-Type', $cacheData['headers']['Content-Type'] ?? 'application/octet-stream');
+    $response->header('Cloud-Type', $cacheData['cloudtype']);
+    $response->header('Cloud-Expiration', $cacheData['expiration']);
+    $response->header('ETag', $cacheData['uniqid'] ?? '');
+    $response->header('Cache-Control', 'public, max-age=31536000');
+    $response->header('Expires', gmdate('D, d M Y H:i:s', time() + 31536000000) . ' GMT');
+    $response->header('Accept-Ranges', 'bytes');
+    $response->header('Connection', 'keep-alive');
+    $response->header('Date', gmdate('D, d M Y H:i:s') . ' GMT');
+    $response->header('Last-Modified', gmdate('D, d M Y H:i:s') . ' GMT');
+    $response->end(file_get_contents("$cacheDir/$cacheFile.content"));
+}
+
+function fetchApiData($apiEndpoint, $reqPath, $token, $sign, $callback) {
+    Coroutine::create(function () use ($apiEndpoint, $reqPath, $token, $sign, $callback) {
+        $client = new Client(parse_url($apiEndpoint, PHP_URL_HOST), 443, true);
+        $client->setHeaders([
+            'Accept' => 'application/json',
+            'User-Agent' => 'Swoole-Client',
+            'token' => $token,
+        ]);
+        $client->get(parse_url($apiEndpoint, PHP_URL_PATH) . "?type=$reqPath&sign=$sign");
+        $callback(json_decode($client->body, true));
+        $client->close();
+    });
+}
+
+function sendJsonResponse($response, $data) {
+    $response->header('Content-Type', 'application/json');
+    $response->end(json_encode($data));
+}
+
+function sendErrorResponse($response, $status, $message) {
+    $response->status($status);
+    $response->end($message);
+}