This commit is contained in:
Marcel Pociot
2020-04-29 16:49:33 +02:00
parent c2084e6be6
commit 6cf206e0a2
35 changed files with 566 additions and 215 deletions

View File

@@ -2,14 +2,16 @@
namespace App\Client;
use App\Client\Http\Controllers\PushLogsToDashboardController;
use App\Client\Http\HttpClient;
use App\HttpServer\App;
use App\HttpServer\Controllers\AttachDataToLogController;
use App\HttpServer\Controllers\ClearLogsController;
use App\HttpServer\Controllers\DashboardController;
use App\HttpServer\Controllers\LogController;
use App\HttpServer\Controllers\ReplayLogController;
use App\HttpServer\Controllers\StoreLogController;
use App\Http\App;
use App\Client\Http\Controllers\AttachDataToLogController;
use App\Client\Http\Controllers\ClearLogsController;
use App\Client\Http\Controllers\DashboardController;
use App\Client\Http\Controllers\LogController;
use App\Client\Http\Controllers\ReplayLogController;
use App\Http\Controllers\StoreLogController;
use App\Http\RouteGenerator;
use App\WebSockets\Socket;
use Ratchet\WebSocket\WsServer;
use React\EventLoop\LoopInterface;
@@ -33,9 +35,13 @@ class Factory
/** @var App */
protected $app;
/** @var RouteGenerator */
protected $router;
public function __construct()
{
$this->loop = LoopFactory::create();
$this->router = new RouteGenerator();
}
public function setHost(string $host)
@@ -93,21 +99,18 @@ class Factory
protected function addRoutes()
{
$dashboardRoute = new Route('/', ['_controller' => app(DashboardController::class)], [], [], null, [], ['GET']);
$logRoute = new Route('/logs', ['_controller' => app(LogController::class)], [], [], null, [], ['GET']);
$storeLogRoute = new Route('/logs', ['_controller' => app(StoreLogController::class)], [], [], null, [], ['POST']);
$replayLogRoute = new Route('/replay/{log}', ['_controller' => app(ReplayLogController::class)], [], [], null, [], ['GET']);
$attachLogDataRoute = new Route('/logs/{request_id}/data', ['_controller' => app(AttachDataToLogController::class)], [], [], null, [], ['POST']);
$clearLogsRoute = new Route('/logs/clear', ['_controller' => app(ClearLogsController::class)], [], [], null, [], ['GET']);
$this->router->get('/', DashboardController::class);
$this->router->get('/logs', LogController::class);
$this->router->post('/logs', PushLogsToDashboardController::class);
$this->router->get('/replay/{log}', ReplayLogController::class);
$this->router->post('/logs/{request_id}/data', AttachDataToLogController::class);
$this->router->post('/logs/clear', ClearLogsController::class);
$this->app->route('/socket', new WsServer(new Socket()), ['*']);
$this->app->routes->add('dashboard', $dashboardRoute);
$this->app->routes->add('logs', $logRoute);
$this->app->routes->add('storeLogs', $storeLogRoute);
$this->app->routes->add('replayLog', $replayLogRoute);
$this->app->routes->add('attachLogData', $attachLogDataRoute);
$this->app->routes->add('clearLogs', $clearLogsRoute);
foreach ($this->router->getRoutes()->all() as $name => $route) {
$this->app->routes->add($name, $route);
}
}
protected function detectNextFreeDashboardPort($port = 4040): int
@@ -138,6 +141,11 @@ class Factory
return $this;
}
public function getApp(): App
{
return $this->app;
}
public function run()
{
$this->loop->run();

View File

@@ -1,10 +1,13 @@
<?php
namespace App\HttpServer\Controllers;
namespace App\Client\Http\Controllers;
use App\Http\Controllers\PostController;
use GuzzleHttp\Psr7\Response;
use Illuminate\Http\Request;
use App\Logger\RequestLogger;
use Ratchet\ConnectionInterface;
use function GuzzleHttp\Psr7\str;
class AttachDataToLogController extends PostController
{
@@ -24,6 +27,11 @@ class AttachDataToLogController extends PostController
$loggedRequest->setAdditionalData((array)$request->get('data', []));
$this->requestLogger->pushLogs();
$httpConnection->send(str(new Response(200)));
return;
}
$httpConnection->send(str(new Response(404)));
}
}

View File

@@ -1,9 +1,10 @@
<?php
namespace App\HttpServer\Controllers;
namespace App\Client\Http\Controllers;
use App\Client\Http\HttpClient;
use App\HttpServer\QueryParameters;
use App\Http\Controllers\Controller;
use App\Http\QueryParameters;
use App\Logger\RequestLogger;
use GuzzleHttp\Psr7\Response;
use Ratchet\ConnectionInterface;

View File

@@ -1,8 +1,9 @@
<?php
namespace App\HttpServer\Controllers;
namespace App\Client\Http\Controllers;
use App\Client\Client;
use App\Http\Controllers\Controller;
use GuzzleHttp\Psr7\Response;
use function GuzzleHttp\Psr7\str;
use Psr\Http\Message\RequestInterface;

View File

@@ -1,7 +1,8 @@
<?php
namespace App\HttpServer\Controllers;
namespace App\Client\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Logger\RequestLogger;
use GuzzleHttp\Psr7\Response;
use Ratchet\ConnectionInterface;

View File

@@ -1,7 +1,8 @@
<?php
namespace App\HttpServer\Controllers;
namespace App\Client\Http\Controllers;
use App\Http\Controllers\Controller;
use Exception;
use App\WebSockets\Socket;
use GuzzleHttp\Psr7\Response;
@@ -10,7 +11,7 @@ use Ratchet\ConnectionInterface;
use function GuzzleHttp\Psr7\str;
use Psr\Http\Message\RequestInterface;
class StoreLogController extends Controller
class PushLogsToDashboardController extends Controller
{
public function onOpen(ConnectionInterface $connection, RequestInterface $request = null)

View File

@@ -1,9 +1,10 @@
<?php
namespace App\HttpServer\Controllers;
namespace App\Client\Http\Controllers;
use App\Client\Http\HttpClient;
use App\HttpServer\QueryParameters;
use App\Http\Controllers\Controller;
use App\Http\QueryParameters;
use App\Logger\RequestLogger;
use GuzzleHttp\Psr7\Response;
use Ratchet\ConnectionInterface;
@@ -26,8 +27,21 @@ class ReplayLogController extends Controller
public function onOpen(ConnectionInterface $connection, RequestInterface $request = null)
{
/** @var RequestLogger $logger */
$requestData = $this->requestLogger->findLoggedRequest(QueryParameters::create($request)->get('log'))->getRequestData();
$loggedRequest = $this->requestLogger->findLoggedRequest(QueryParameters::create($request)->get('log'));
if (is_null($loggedRequest)) {
$connection->send(
str(new Response(
404,
['Content-Type' => 'application/json'],
))
);
$connection->close();
return;
}
$requestData = $loggedRequest->getRequestData();
/** @var HttpClient $tunnel */
$this->httpClient->performRequest($requestData);

View File

@@ -1,6 +1,6 @@
<?php
namespace App\HttpServer;
namespace App\Http;
use Ratchet\Http\Router;
use Ratchet\Server\IoServer;
@@ -12,12 +12,15 @@ use Symfony\Component\Routing\RouteCollection;
class App extends \Ratchet\App
{
/** @var Server */
protected $socket;
public function __construct($httpHost, $port, $address, LoopInterface $loop)
{
$this->httpHost = $httpHost;
$this->port = $port;
$socket = new Reactor($address.':'.$port, $loop);
$this->socket = new Reactor($address.':'.$port, $loop);
$this->routes = new RouteCollection;
@@ -25,8 +28,13 @@ class App extends \Ratchet\App
$router = new Router($urlMatcher);
$httpServer = new HttpServer($router);
$httpServer = new Server($router);
$this->_server = new IoServer($httpServer, $socket, $loop);
$this->_server = new IoServer($httpServer, $this->socket, $loop);
}
public function close()
{
$this->socket->close();
}
}

View File

@@ -1,6 +1,6 @@
<?php
namespace App\HttpServer\Controllers;
namespace App\Http\Controllers;
use Exception;
use Ratchet\ConnectionInterface;

View File

@@ -1,8 +1,8 @@
<?php
namespace App\HttpServer\Controllers;
namespace App\Http\Controllers;
use App\HttpServer\QueryParameters;
use App\Http\QueryParameters;
use GuzzleHttp\Psr7\ServerRequest;
use Illuminate\Http\Request;
use Illuminate\Support\Collection;

View File

@@ -1,6 +1,6 @@
<?php
namespace App\HttpServer;
namespace App\Http;
use Psr\Http\Message\RequestInterface;

View File

@@ -1,6 +1,6 @@
<?php
namespace App\Server\Http;
namespace App\Http;
use Ratchet\WebSocket\MessageComponentInterface;
use Ratchet\WebSocket\WsServer;

View File

@@ -1,10 +1,10 @@
<?php
namespace App\HttpServer;
namespace App\Http;
use Ratchet\Http\HttpServerInterface;
class HttpServer extends \Ratchet\Http\HttpServer
class Server extends \Ratchet\Http\HttpServer
{
public function __construct(HttpServerInterface $component)
{

View File

@@ -32,7 +32,6 @@ class CliRequestLogger extends Logger
public function logRequest(LoggedRequest $loggedRequest)
{
return;
if ($this->requests->has($loggedRequest->id())) {
$this->requests[$loggedRequest->id()] = $loggedRequest;
} else {

View File

@@ -94,6 +94,11 @@ class LoggedRequest implements \JsonSerializable
$this->additionalData = array_merge($this->additionalData, $data);
}
public function getAdditionalData(): array
{
return $this->additionalData;
}
protected function isBinary(string $string): bool
{
return preg_match('~[^\x20-\x7E\t\r\n]~', $string) > 0;
@@ -122,26 +127,21 @@ class LoggedRequest implements \JsonSerializable
}
}
public function id()
public function id(): string
{
return $this->id;
}
public function getRequestData()
public function getRequestData(): ?string
{
return $this->rawRequest;
}
public function getResponse()
public function getResponse(): ?Response
{
return $this->parsedResponse;
}
protected function getResponseBody()
{
return \Laminas\Http\Response::fromString($this->rawResponse)->getBody();
}
protected function getPost()
{
$postData = [];

View File

@@ -19,6 +19,8 @@ class RequestLogger
/** @var CliRequestLogger */
protected $cliRequestLogger;
const MAX_LOGGED_REQUESTS = 10;
public function __construct(Browser $browser, CliRequestLogger $cliRequestLogger)
{
$this->client = $browser;
@@ -32,17 +34,19 @@ class RequestLogger
});
}
public function logRequest(string $rawRequest, Request $request)
public function logRequest(string $rawRequest, Request $request): LoggedRequest
{
$loggedRequest = new LoggedRequest($rawRequest, $request);
array_unshift($this->requests, $loggedRequest);
$this->requests = array_slice($this->requests, 0, 10);
$this->requests = array_slice($this->requests, 0, static::MAX_LOGGED_REQUESTS);
$this->cliRequestLogger->logRequest($loggedRequest);
$this->pushLogs();
return $loggedRequest;
}
public function logResponse(Request $request, string $rawResponse)
@@ -59,7 +63,7 @@ class RequestLogger
}
}
public function getData()
public function getData(): array
{
return $this->requests;
}
@@ -73,6 +77,7 @@ class RequestLogger
public function pushLogs()
{
// TODO: Make dashboard part configurable
$this
->client
->post(

View File

@@ -36,7 +36,7 @@ class AppServiceProvider extends ServiceProvider
$localConfigFile = getcwd() . DIRECTORY_SEPARATOR . '.expose.php';
if (file_exists($localConfigFile)) {
$localConfig = require_once $localConfigFile;
$localConfig = require $localConfigFile;
config()->set('expose', array_merge($builtInConfig, $localConfig));
return;
}
@@ -49,7 +49,7 @@ class AppServiceProvider extends ServiceProvider
]);
if (file_exists($configFile)) {
$globalConfig = require_once $configFile;
$globalConfig = require $configFile;
config()->set('expose', array_merge($builtInConfig, $globalConfig));
}
}

View File

@@ -4,7 +4,7 @@ namespace App\Server;
use App\Contracts\ConnectionManager as ConnectionManagerContract;
use App\Contracts\SubdomainGenerator;
use App\HttpServer\HttpServer;
use App\Http\Server as HttpServer;
use App\Server\Connections\ConnectionManager;
use App\Server\Http\Controllers\Admin\DeleteUsersController;
use App\Server\Http\Controllers\Admin\ListSitesController;
@@ -14,7 +14,7 @@ use App\Server\Http\Controllers\Admin\StoreUsersController;
use App\Server\Http\Controllers\Admin\VerifyLoginController;
use App\Server\Http\Controllers\ControlMessageController;
use App\Server\Http\Controllers\TunnelMessageController;
use App\Server\Http\RouteGenerator;
use App\Http\RouteGenerator;
use App\Server\Http\Router;
use App\Server\SubdomainGenerator\RandomSubdomainGenerator;
use Clue\React\SQLite\DatabaseInterface;

View File

@@ -2,7 +2,7 @@
namespace App\Server\Http\Controllers\Admin;
use App\HttpServer\Controllers\PostController;
use App\Http\Controllers\PostController;
use Clue\React\SQLite\DatabaseInterface;
use Clue\React\SQLite\Result;
use GuzzleHttp\Psr7\Response;

View File

@@ -3,7 +3,7 @@
namespace App\Server\Http\Controllers\Admin;
use App\Contracts\ConnectionManager;
use App\HttpServer\Controllers\PostController;
use App\Http\Controllers\PostController;
use App\Server\Configuration;
use Clue\React\SQLite\DatabaseInterface;
use Clue\React\SQLite\Result;

View File

@@ -2,7 +2,7 @@
namespace App\Server\Http\Controllers\Admin;
use App\HttpServer\Controllers\PostController;
use App\Http\Controllers\PostController;
use Clue\React\SQLite\DatabaseInterface;
use Clue\React\SQLite\Result;
use GuzzleHttp\Psr7\Response;

View File

@@ -3,7 +3,7 @@
namespace App\Server\Http\Controllers\Admin;
use App\Contracts\ConnectionManager;
use App\HttpServer\Controllers\PostController;
use App\Http\Controllers\PostController;
use Clue\React\SQLite\DatabaseInterface;
use Clue\React\SQLite\Result;
use GuzzleHttp\Psr7\Response;

View File

@@ -2,7 +2,7 @@
namespace App\Server\Http\Controllers\Admin;
use App\HttpServer\Controllers\PostController;
use App\Http\Controllers\PostController;
use Clue\React\SQLite\DatabaseInterface;
use Clue\React\SQLite\Result;
use GuzzleHttp\Psr7\Response;

View File

@@ -3,7 +3,7 @@
namespace App\Server\Http\Controllers\Admin;
use App\Contracts\ConnectionManager;
use App\HttpServer\Controllers\PostController;
use App\Http\Controllers\PostController;
use Clue\React\SQLite\DatabaseInterface;
use Clue\React\SQLite\Result;
use GuzzleHttp\Psr7\Response;

View File

@@ -3,7 +3,7 @@
namespace App\Server\Http\Controllers;
use App\Contracts\ConnectionManager;
use App\HttpServer\QueryParameters;
use App\Http\QueryParameters;
use Clue\React\SQLite\DatabaseInterface;
use Clue\React\SQLite\Result;
use Ratchet\WebSocket\MessageComponentInterface;

View File

@@ -3,7 +3,7 @@
namespace App\Server\Http\Controllers;
use App\Contracts\ConnectionManager;
use App\HttpServer\Controllers\PostController;
use App\Http\Controllers\PostController;
use App\Server\Configuration;
use App\Server\Connections\ControlConnection;
use GuzzleHttp\Psr7\Response;

View File

@@ -2,7 +2,7 @@
namespace App\Server\Http;
use App\HttpServer\QueryParameters;
use App\Http\QueryParameters;
use GuzzleHttp\Psr7\ServerRequest;
use Psr\Http\Message\RequestInterface;
use Ratchet\ConnectionInterface;