forked from urvishpatelce/lxd-app
add parameter forwarding in URL
This commit is contained in:
BIN
backend/app/.DS_Store
vendored
Normal file
BIN
backend/app/.DS_Store
vendored
Normal file
Binary file not shown.
@ -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
|
||||
|
||||
@ -1,2 +1,3 @@
|
||||
{
|
||||
"test.lxdapp.local": "container-test"
|
||||
}
|
||||
Binary file not shown.
@ -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
|
||||
@ -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";
|
||||
|
||||
|
||||
@ -1,143 +0,0 @@
|
||||
<?php
|
||||
namespace App\Managers;
|
||||
use App\Services\LxdService;
|
||||
|
||||
class LXDProxyManager
|
||||
{
|
||||
protected LxdService $lxdService;
|
||||
protected string $mapFile = '/etc/nginx/lxd_map.conf';
|
||||
|
||||
public function __construct(LxdService $lxdService)
|
||||
{
|
||||
$this->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;
|
||||
}
|
||||
|
||||
}
|
||||
@ -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']);
|
||||
});
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user