diff --git a/backend/app/.DS_Store b/backend/app/.DS_Store new file mode 100644 index 0000000..175ed52 Binary files /dev/null and b/backend/app/.DS_Store differ diff --git a/backend/app/README.md b/backend/app/README.md index 6ac61fa..9edf7a0 100644 --- a/backend/app/README.md +++ b/backend/app/README.md @@ -86,7 +86,7 @@ NGINX config example: 4. **Map domain in /etc/hosts** ```bash - 127.0.0.1 mitul.lxdapp.local + 127.0.0.1 test.lxdapp.local 5. **Make sure LXD is working** ```bash @@ -112,7 +112,7 @@ NGINX config example: **Headers:** - Origin: http://mitul.lxdapp.local + Origin: http://customer.lxdapp.local **Response:** ```bash diff --git a/backend/app/config.json b/backend/app/config.json index 7a73a41..1961c59 100644 --- a/backend/app/config.json +++ b/backend/app/config.json @@ -1,2 +1,3 @@ { + "test.lxdapp.local": "container-test" } \ No newline at end of file diff --git a/backend/.DS_Store b/backend/app/public/last-access-logs/.DS_Store similarity index 97% rename from backend/.DS_Store rename to backend/app/public/last-access-logs/.DS_Store index fadd49a..5008ddf 100644 Binary files a/backend/.DS_Store and b/backend/app/public/last-access-logs/.DS_Store differ diff --git a/backend/app/public/last-access-logs/container-mitul.txt b/backend/app/public/last-access-logs/container-mitul.txt deleted file mode 100644 index a27696c..0000000 --- a/backend/app/public/last-access-logs/container-mitul.txt +++ /dev/null @@ -1,10 +0,0 @@ -2025-07-08 13:07:05 : http://10.110.90.30:80 -2025-07-08 13:29:10 : http://10.110.90.30:80 -2025-07-08 14:43:45 : http://10.110.90.144:80 -2025-07-08 14:50:28 : http://10.110.90.89:80 -2025-07-08 14:53:41 : http://10.110.90.89:80 -2025-07-08 15:07:07 : http://10.110.90.95:80 -2025-07-08 15:12:49 : http://10.110.90.95:80 -2025-07-08 15:23:59 : http://10.110.90.147:80 -2025-07-08 15:24:26 : http://10.110.90.147:80 -2025-07-09 06:15:42 : http://10.110.90.248:80 diff --git a/backend/app/src/Controllers/ProxyController.php b/backend/app/src/Controllers/ProxyController.php index 1824def..50248b2 100644 --- a/backend/app/src/Controllers/ProxyController.php +++ b/backend/app/src/Controllers/ProxyController.php @@ -2,7 +2,6 @@ namespace App\Controllers; -use App\Managers\LXDProxyManager; use Psr\Http\Message\ServerRequestInterface as Request; use Psr\Http\Message\ResponseInterface as Response; use GuzzleHttp\Client; @@ -20,7 +19,7 @@ class ProxyController $mainDomain = $_ENV['MAIN_DOMAIN'] ?? 'lxdapp.local'; $origin = $request->getHeaderLine('Origin'); - $domain = parse_url($origin, PHP_URL_HOST); // e.g. mitul.lxdapp.local + $domain = parse_url($origin, PHP_URL_HOST); // e.g. customer.lxdapp.local $params = (array)$request->getParsedBody(); $configPath = __DIR__ . '/../../config.json'; @@ -145,6 +144,74 @@ class ProxyController * Proxies the request to the container. */ private function proxyToContainer(Request $request, Response $response, string $ip, string $name): Response + { + $client = new Client([ + 'http_errors' => false, + 'timeout' => 10, + ]); + + $method = $request->getMethod(); + + $baseUrl = $ip ? "http://$ip" : "http://127.0.0.1:3000"; + + $uri = $request->getUri(); + $path = $uri->getPath(); + + // Remove /api/v1 prefix from path + $prefix = '/api/v1'; + if (strpos($path, $prefix) === 0) { + $path = substr($path, strlen($prefix)); + if ($path === '') { + $path = '/'; + } + } + + // Add .php extension if not present + if (!str_ends_with($path, '.php')) { + $path .= '.php'; + } + + $query = $uri->getQuery(); + $targetUrl = $baseUrl . $path . ($query ? '?' . $query : ''); + $options = [ + 'headers' => [], + 'http_errors' => false, + 'debug' => false, + ]; + + foreach ($request->getHeaders() as $headerName => $values) { + if (strtolower($headerName) !== 'host') { + $options['headers'][$headerName] = implode(', ', $values); + } + } + + $options['headers'] = [ + 'Host' => (string) $ip, + 'Accept-Encoding' => 'gzip, deflate', + 'Accept' => '*/*', + 'User-Agent' => 'SlimProxy/1.0', + ]; + + if (in_array($method, ['POST', 'PUT', 'PATCH', 'DELETE'])) { + $body = (string) $request->getBody(); + if ($body) { + $options['body'] = $body; + } + } + $forwarded = $client->request($method, $targetUrl, $options); + + $this->writeLastAccessLog($name, $targetUrl); + + foreach ($forwarded->getHeaders() as $headerName => $headerValues) { + $response = $response->withHeader($headerName, implode(', ', $headerValues)); + } + + $response->getBody()->write((string) $forwarded->getBody()); + + return $response->withStatus($forwarded->getStatusCode()); + } + + private function proxyToContainerOLD(Request $request, Response $response, string $ip, string $name): Response { $target = $ip ? "http://$ip:80" : "http://127.0.0.1:3000"; diff --git a/backend/app/src/Managers/LXDProxyManager.php b/backend/app/src/Managers/LXDProxyManager.php deleted file mode 100644 index e087b11..0000000 --- a/backend/app/src/Managers/LXDProxyManager.php +++ /dev/null @@ -1,143 +0,0 @@ -lxdService = $lxdService; - } - - /** - * Handle request to container: return IP or null if fallback needed. - */ - public function handleRequest(string $name, $domain) - { - try { - $container = $this->lxdService->containerExists($name); - - if (!$container) { - $this->lxdService->createContainer($name); - sleep(10); - - $this->lxdService->startContainer($name); - $maxRetries = 20; - $delay = 2; - - for ($i = 0; $i < $maxRetries; $i++) { - $status = $this->lxdService->getStatus($name); - if ($status['metadata']['status'] === 'Running') { - break; - } - sleep($delay); - } - - $this->lxdService->installPackages($name); - sleep(5); - - $ipv4 = $this->lxdService->getContainerIP($name); - $maxRetries = 20; - $waitSeconds = 3; - $ready = false; - for ($i = 0; $i < $maxRetries; $i++) { - // Try to connect to port 80 on container IP (you can use fsockopen, curl, or similar) - $connection = @fsockopen($ipv4, 80, $errno, $errstr, 2); - if ($connection) { - fclose($connection); - $ready = true; - break; - } - sleep($waitSeconds); - } - - $hostConfigPath = __DIR__ . '/../../config.json'; - if (file_exists($hostConfigPath)) { - $hostConfigData = json_decode(file_get_contents($hostConfigPath), true); - } else { - // If the file doesn't exist, initialize an empty array - $hostConfigData = []; - } - - // Step 3: Append the new container entry to the JSON data - $hostConfigData[$domain] = $name; - - // Step 4: Write the updated data back to the host-config.json file - file_put_contents($hostConfigPath, json_encode($hostConfigData, JSON_PRETTY_PRINT)); - - - @mkdir('/var/www/last-access', 0777, true); - @touch("/var/www/last-access/$name.txt"); - - return [ - 'status' => 'success', - 'ip' => $ipv4, - ]; - } - - if ($container['metadata']['status'] === 'Running') { - $ipv4 = $this->getIPv4FromMetadata($container['metadata']); - - return [ - 'status' => 'success', - 'ip' => $ipv4, - ]; - } - - // Start the container and wait for IP - $this->lxdService->startContainer($name); - - $maxRetries = 30; - $delay = 2; - $ipv4 = null; - - for ($i = 0; $i < $maxRetries; $i++) { - $status = $this->lxdService->getStatus($name); - $ipv4 = $this->getIPv4FromMetadata($status['metadata']); - - if (!empty($ipv4)) { - break; - } - - sleep($delay); - } - - if ($ipv4) { - return [ - 'status' => 'success', - 'ip' => $ipv4, - ]; - } - - return [ - 'status' => 'failed', - 'message' => 'Container did not acquire an IP in time.', - ]; - } catch (\Exception $e) { - return [ - 'status' => 'failed', - 'error' => $e->getMessage(), - ]; - } - - } - - public function getIPv4FromMetadata(array $metadata): ?string - { - if ( - isset($metadata['network']['eth0']['addresses']) && - is_array($metadata['network']['eth0']['addresses']) - ) { - foreach ($metadata['network']['eth0']['addresses'] as $addr) { - if (isset($addr['family']) && $addr['family'] === 'inet' && isset($addr['address'])) { - return $addr['address']; - } - } - } - return null; - } - -} diff --git a/backend/app/src/Routes/v1/proxy.php b/backend/app/src/Routes/v1/proxy.php index a1ee1fe..5e24fdd 100644 --- a/backend/app/src/Routes/v1/proxy.php +++ b/backend/app/src/Routes/v1/proxy.php @@ -6,6 +6,6 @@ use App\Controllers\ProxyController; return function (App $app) { // Proxy route $app->group('/api/v1', function ($group) { - $group->any('/proxy', [ProxyController::class, 'forward']); + $group->any('/{routes:.*}', [ProxyController::class, 'forward']); }); };