diff --git a/app/Client/Client.php b/app/Client/Client.php index e449ca2..3a17771 100644 --- a/app/Client/Client.php +++ b/app/Client/Client.php @@ -12,6 +12,7 @@ class Client protected $loop; protected $host; protected $port; + public static $subdomains = []; public function __construct(LoopInterface $loop, $host, $port) { @@ -31,6 +32,7 @@ class Client $connection->authenticate($sharedUrl, $subdomain); $clientConnection->on('authenticated', function ($data) { + static::$subdomains[] = "$data->subdomain.{$this->host}:{$this->port}"; dump("Connected to http://$data->subdomain.{$this->host}:{$this->port}"); }); }); diff --git a/app/Client/Connection.php b/app/Client/Connection.php index 57c4168..6b1fc58 100644 --- a/app/Client/Connection.php +++ b/app/Client/Connection.php @@ -71,4 +71,11 @@ class Connection ], ])); } + + public function ping() + { + $this->socket->write(json_encode([ + 'event' => 'pong', + ])); + } } diff --git a/app/Client/Factory.php b/app/Client/Factory.php index 5c60772..4008432 100644 --- a/app/Client/Factory.php +++ b/app/Client/Factory.php @@ -3,6 +3,8 @@ namespace App\Client; 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; @@ -67,6 +69,8 @@ class Factory $logRoute = new Route('/logs', ['_controller' => new LogController()], [], [], null, [], ['GET']); $storeLogRoute = new Route('/logs', ['_controller' => new StoreLogController()], [], [], null, [], ['POST']); $replayLogRoute = new Route('/replay/{log}', ['_controller' => new ReplayLogController()], [], [], null, [], ['GET']); + $attachLogDataRoute = new Route('/logs/{request_id}/data', ['_controller' => new AttachDataToLogController()], [], [], null, [], ['POST']); + $clearLogsRoute = new Route('/logs/clear', ['_controller' => new ClearLogsController()], [], [], null, [], ['GET']); $this->app->route('/socket', new WsServer(new Socket()), ['*']); @@ -74,19 +78,32 @@ class Factory $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); + } + + protected function detectNextFreeDashboardPort($port = 4040): int + { + while (is_resource(@fsockopen('127.0.0.1', $port))) { + $port++; + } + + return $port; } public function createHttpServer() { - $this->loop->futureTick(function () { - $dashboardUrl = 'http://127.0.0.1:4040/'; + $dashboardPort = $this->detectNextFreeDashboardPort(); - echo('Started Dashboard on port 4040'. PHP_EOL); + $this->loop->futureTick(function () use ($dashboardPort) { + $dashboardUrl = "http://127.0.0.1:{$dashboardPort}/"; - echo('If the dashboard does not automatically open, visit: '.$dashboardUrl . PHP_EOL); + echo("Started Dashboard on port {$dashboardPort}" . PHP_EOL); + + echo('If the dashboard does not automatically open, visit: ' . $dashboardUrl . PHP_EOL); }); - $this->app = new App('127.0.0.1', 4040, '0.0.0.0', $this->loop); + $this->app = new App('127.0.0.1', $dashboardPort, '0.0.0.0', $this->loop); $this->addRoutes(); diff --git a/app/Commands/ServeCommand.php b/app/Commands/ServeCommand.php index c191fdf..a9cf40f 100644 --- a/app/Commands/ServeCommand.php +++ b/app/Commands/ServeCommand.php @@ -5,6 +5,7 @@ namespace App\Commands; use App\Server\Factory; use Illuminate\Console\Scheduling\Schedule; use LaravelZero\Framework\Commands\Command; +use React\EventLoop\LoopInterface; class ServeCommand extends Command { @@ -15,6 +16,7 @@ class ServeCommand extends Command public function handle() { (new Factory()) + ->setLoop(app(LoopInterface::class)) ->setHost($this->argument('host')) ->setHostname($this->argument('hostname')) ->createServer() diff --git a/app/Commands/ShareCommand.php b/app/Commands/ShareCommand.php index 7d8bb86..a9b7b40 100644 --- a/app/Commands/ShareCommand.php +++ b/app/Commands/ShareCommand.php @@ -17,8 +17,8 @@ class ShareCommand extends Command { (new Factory()) ->setLoop(app(LoopInterface::class)) - //->setHost('beyond.sh') - //->setPort(8080) + ->setHost('beyond.sh') + ->setPort(8080) ->createClient($this->argument('host'), explode(',', $this->option('subdomain'))) ->createHttpServer() ->run(); diff --git a/app/HttpServer/Controllers/AttachDataToLogController.php b/app/HttpServer/Controllers/AttachDataToLogController.php new file mode 100644 index 0000000..bd5bf61 --- /dev/null +++ b/app/HttpServer/Controllers/AttachDataToLogController.php @@ -0,0 +1,22 @@ +findLoggedRequest($request->get('request_id', '')); + + if (! is_null($loggedRequest)) { + $loggedRequest->setAdditionalData((array)$request->get('data', [])); + + $requestLogger->pushLogs(); + } + } +} diff --git a/app/HttpServer/Controllers/ClearLogsController.php b/app/HttpServer/Controllers/ClearLogsController.php new file mode 100644 index 0000000..453404c --- /dev/null +++ b/app/HttpServer/Controllers/ClearLogsController.php @@ -0,0 +1,31 @@ +clear(); + + $connection->send( + str(new Response( + 200, + ['Content-Type' => 'application/json'], + '' + )) + ); + + $connection->close(); + } +} diff --git a/app/HttpServer/Controllers/DashboardController.php b/app/HttpServer/Controllers/DashboardController.php index 978fb45..5ccc930 100644 --- a/app/HttpServer/Controllers/DashboardController.php +++ b/app/HttpServer/Controllers/DashboardController.php @@ -2,6 +2,7 @@ namespace App\HttpServer\Controllers; +use App\Client\Client; use GuzzleHttp\Psr7\Response; use function GuzzleHttp\Psr7\str; use Psr\Http\Message\RequestInterface; @@ -15,10 +16,19 @@ class DashboardController extends Controller str(new Response( 200, ['Content-Type' => 'text/html'], - file_get_contents(base_path('resources/views/index.html')) + $this->getView() )) ); $connection->close(); } + + protected function getView(): string + { + $view = file_get_contents(base_path('resources/views/index.html')); + + $view = str_replace('%subdomains%', implode(' ', Client::$subdomains), $view); + + return $view; + } } diff --git a/app/HttpServer/Controllers/PostController.php b/app/HttpServer/Controllers/PostController.php new file mode 100644 index 0000000..7bce520 --- /dev/null +++ b/app/HttpServer/Controllers/PostController.php @@ -0,0 +1,69 @@ +contentLength = $this->findContentLength($request->getHeaders()); + + $connection->requestBuffer = (string) $request->getBody(); + + $connection->request = $request; + + $this->checkContentLength($connection); + } + + public function onMessage(ConnectionInterface $from, $msg) + { + $from->requestBuffer .= $msg; + + $this->checkContentLength($from); + } + + protected function findContentLength(array $headers): int + { + return Collection::make($headers)->first(function ($values, $header) { + return strtolower($header) === 'content-length'; + })[0] ?? 0; + } + + protected function checkContentLength(ConnectionInterface $connection) + { + if (strlen($connection->requestBuffer) === $connection->contentLength) { + $laravelRequest = $this->createLaravelRequest($connection); + + $this->handle($laravelRequest); + + $connection->close(); + + unset($connection->requestBuffer); + unset($connection->contentLength); + unset($connection->request); + } + } + + abstract public function handle(Request $request); + + protected function createLaravelRequest(ConnectionInterface $connection): Request + { + $serverRequest = (new ServerRequest( + $connection->request->getMethod(), + $connection->request->getUri(), + $connection->request->getHeaders(), + $connection->requestBuffer, + $connection->request->getProtocolVersion() + ))->withQueryParams(QueryParameters::create($connection->request)->all()); + + return Request::createFromBase((new HttpFoundationFactory)->createRequest($serverRequest)); + } +} diff --git a/app/Logger/LoggedRequest.php b/app/Logger/LoggedRequest.php index 521fd2a..754dc9c 100644 --- a/app/Logger/LoggedRequest.php +++ b/app/Logger/LoggedRequest.php @@ -7,7 +7,9 @@ use Illuminate\Support\Arr; use Illuminate\Support\Str; use Laminas\Http\Request; use Laminas\Http\Response; +use Namshi\Cuzzle\Formatter\CurlFormatter; use Riverline\MultiPartParser\StreamedPart; +use function GuzzleHttp\Psr7\parse_request; class LoggedRequest implements \JsonSerializable { @@ -35,12 +37,15 @@ class LoggedRequest implements \JsonSerializable /** @var string */ protected $subdomain; + /** @var array */ + protected $additionalData = []; + public function __construct(string $rawRequest, Request $parsedRequest) { - $this->id = (string)Str::uuid(); $this->startTime = now(); $this->rawRequest = $rawRequest; $this->parsedRequest = $parsedRequest; + $this->id = $this->getRequestId(); } /** @@ -61,6 +66,8 @@ class LoggedRequest implements \JsonSerializable 'body' => $this->isBinary($this->rawRequest) ? 'BINARY' : $this->parsedRequest->getContent(), 'query' => $this->parsedRequest->getQuery()->toArray(), 'post' => $this->getPost(), + 'curl' => (new CurlFormatter())->format(parse_request($this->rawRequest)), + 'additional_data' => $this->additionalData, ], ]; @@ -77,6 +84,11 @@ class LoggedRequest implements \JsonSerializable return $data; } + public function setAdditionalData(array $data) + { + $this->additionalData = array_merge($this->additionalData, $data); + } + protected function isBinary(string $string): bool { return preg_match('~[^\x20-\x7E\t\r\n]~', $string) > 0; @@ -174,4 +186,9 @@ class LoggedRequest implements \JsonSerializable { return Arr::get($this->parsedRequest->getHeaders()->toArray(), 'X-Original-Host'); } + + protected function getRequestId() + { + return Arr::get($this->parsedRequest->getHeaders()->toArray(), 'X-Expose-Request-ID', (string)Str::uuid()); + } } diff --git a/app/Logger/RequestLogger.php b/app/Logger/RequestLogger.php index 7d0b1c3..ec8f17d 100644 --- a/app/Logger/RequestLogger.php +++ b/app/Logger/RequestLogger.php @@ -51,7 +51,14 @@ class RequestLogger return $this->requests; } - protected function pushLogs() + public function clear() + { + $this->requests = []; + + $this->pushLogs(); + } + + public function pushLogs() { $this ->client diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index e267e66..92466c4 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -23,6 +23,7 @@ class AppServiceProvider extends ServiceProvider $this->app->singleton(RequestLogger::class, function () { $browser = new Browser(app(LoopInterface::class)); + return new RequestLogger($browser); }); } diff --git a/app/Server/Connections/Connection.php b/app/Server/Connections/Connection.php index 459bc9f..a295e41 100644 --- a/app/Server/Connections/Connection.php +++ b/app/Server/Connections/Connection.php @@ -32,14 +32,17 @@ class Connection return array_pop($this->proxies); } - public function rewriteHostInformation($serverHost, $port, string $data) + public function rewriteHostInformation($serverHost, $port, $requestId, string $data) { $appName = config('app.name'); $appVersion = config('app.version'); + $originalHost = "{$this->subdomain}.{$serverHost}:{$port}"; + $data = preg_replace('/Host: '.$this->subdomain.'.'.$serverHost.'(.*)\r\n/', "Host: {$this->host}\r\n" . - "X-Tunnel-By: {$appName} {$appVersion}\r\n" . - "X-Original-Host: {$this->subdomain}.{$serverHost}:{$port}\r\n", $data); + "X-Exposed-By: {$appName} {$appVersion}\r\n" . + "X-Expose-Request-ID: {$requestId}\r\n" . + "X-Original-Host: {$originalHost}\r\n", $data); return $data; } diff --git a/app/Server/Shaft.php b/app/Server/Expose.php similarity index 96% rename from app/Server/Shaft.php rename to app/Server/Expose.php index 796f7bb..a134bf1 100644 --- a/app/Server/Shaft.php +++ b/app/Server/Expose.php @@ -10,7 +10,7 @@ use Ratchet\ConnectionInterface; use Ratchet\MessageComponentInterface; use function GuzzleHttp\Psr7\parse_request; -class Shaft implements MessageComponentInterface +class Expose implements MessageComponentInterface { protected $connectionManager; diff --git a/app/Server/Factory.php b/app/Server/Factory.php index a626206..c6c296d 100644 --- a/app/Server/Factory.php +++ b/app/Server/Factory.php @@ -60,7 +60,7 @@ class Factory $connectionManager = new ConnectionManager($this->hostname, $this->port); - $app = new Shaft($connectionManager); + $app = new Expose($connectionManager); return new IoServer($app, $socket, $this->loop); } diff --git a/app/Server/Messages/ControlMessage.php b/app/Server/Messages/ControlMessage.php index ddcfa6d..392ce9f 100644 --- a/app/Server/Messages/ControlMessage.php +++ b/app/Server/Messages/ControlMessage.php @@ -5,6 +5,7 @@ namespace App\Server\Messages; use App\Server\Connections\ConnectionManager; use Illuminate\Support\Str; use Ratchet\ConnectionInterface; +use React\EventLoop\LoopInterface; use stdClass; class ControlMessage implements Message @@ -45,6 +46,13 @@ class ControlMessage implements Message 'subdomain' => $connectionInfo->subdomain, 'client_id' => $connectionInfo->client_id ])); + + $loop = app(LoopInterface::class); + $timer = $loop->addPeriodicTimer(5, function () use ($connection) { + $connection->send(json_encode([ + 'event' => 'ping' + ])); + }); } protected function registerProxy(ConnectionInterface $connection, $data) diff --git a/app/Server/Messages/TunnelMessage.php b/app/Server/Messages/TunnelMessage.php index a46e633..c176cea 100644 --- a/app/Server/Messages/TunnelMessage.php +++ b/app/Server/Messages/TunnelMessage.php @@ -69,10 +69,10 @@ class TunnelMessage implements Message private function copyDataToClient(Connection $clientConnection) { - $data = $clientConnection->rewriteHostInformation($this->connectionManager->host(), $this->connectionManager->port(), $this->connection->buffer); - $requestId = uniqid(); + $data = $clientConnection->rewriteHostInformation($this->connectionManager->host(), $this->connectionManager->port(), $requestId, $this->connection->buffer); + // Ask client to create a new proxy $clientConnection->socket->send(json_encode([ 'event' => 'createProxy', diff --git a/composer.json b/composer.json index d099d7a..62cb989 100644 --- a/composer.json +++ b/composer.json @@ -22,9 +22,13 @@ "cboden/ratchet": "^0.4.2", "clue/buzz-react": "^2.7", "guzzlehttp/guzzle": "^6.5", + "illuminate/http": "5.8.*|^6.0|^7.0", "laminas/laminas-http": "^2.11", "laravel-zero/framework": "^7.0", + "namshi/cuzzle": "^2.0", "react/socket": "^1.4", + "symfony/http-kernel": "^4.0|^5.0", + "symfony/psr-http-message-bridge": "^1.1|^2.0", "riverline/multipart-parser": "^2.0" }, "require-dev": { @@ -53,5 +57,5 @@ }, "minimum-stability": "dev", "prefer-stable": true, - "bin": ["phunnel"] + "bin": ["expose"] } diff --git a/composer.lock b/composer.lock index a81bbf8..ca251e7 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "5fb0e746e857756290dd83192601f8ec", + "content-hash": "f85ae104dc6c4806c3d1a158c5d182e6", "packages": [ { "name": "bfunky/http-parser", @@ -659,7 +659,7 @@ }, { "name": "illuminate/cache", - "version": "v7.4.0", + "version": "v7.6.2", "source": { "type": "git", "url": "https://github.com/illuminate/cache.git", @@ -710,7 +710,7 @@ }, { "name": "illuminate/config", - "version": "v7.4.0", + "version": "v7.6.2", "source": { "type": "git", "url": "https://github.com/illuminate/config.git", @@ -754,7 +754,7 @@ }, { "name": "illuminate/console", - "version": "v7.4.0", + "version": "v7.6.2", "source": { "type": "git", "url": "https://github.com/illuminate/console.git", @@ -808,16 +808,16 @@ }, { "name": "illuminate/container", - "version": "v7.4.0", + "version": "v7.6.2", "source": { "type": "git", "url": "https://github.com/illuminate/container.git", - "reference": "9108edffa95b34df94dc36721d92f380dd59bea3" + "reference": "10c5802e360595f5f2a8b6afa176b9542851e580" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/container/zipball/9108edffa95b34df94dc36721d92f380dd59bea3", - "reference": "9108edffa95b34df94dc36721d92f380dd59bea3", + "url": "https://api.github.com/repos/illuminate/container/zipball/10c5802e360595f5f2a8b6afa176b9542851e580", + "reference": "10c5802e360595f5f2a8b6afa176b9542851e580", "shasum": "" }, "require": { @@ -848,20 +848,20 @@ ], "description": "The Illuminate Container package.", "homepage": "https://laravel.com", - "time": "2020-03-18T13:25:12+00:00" + "time": "2020-04-06T13:33:36+00:00" }, { "name": "illuminate/contracts", - "version": "v7.4.0", + "version": "v7.6.2", "source": { "type": "git", "url": "https://github.com/illuminate/contracts.git", - "reference": "f13c89509345ceee05f3527a83f38c77c0f74579" + "reference": "69a40779d8fc43e3f43da973b9c0c20bdbd81203" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/contracts/zipball/f13c89509345ceee05f3527a83f38c77c0f74579", - "reference": "f13c89509345ceee05f3527a83f38c77c0f74579", + "url": "https://api.github.com/repos/illuminate/contracts/zipball/69a40779d8fc43e3f43da973b9c0c20bdbd81203", + "reference": "69a40779d8fc43e3f43da973b9c0c20bdbd81203", "shasum": "" }, "require": { @@ -892,20 +892,20 @@ ], "description": "The Illuminate Contracts package.", "homepage": "https://laravel.com", - "time": "2020-03-31T14:24:32+00:00" + "time": "2020-04-09T15:01:22+00:00" }, { "name": "illuminate/events", - "version": "v7.4.0", + "version": "v7.6.2", "source": { "type": "git", "url": "https://github.com/illuminate/events.git", - "reference": "442fd9cdbacc0732eea4018bc1f0df7e4004b8e8" + "reference": "59f6074ff6b14b475c7c97021dcbcd2e2bce2ebd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/events/zipball/442fd9cdbacc0732eea4018bc1f0df7e4004b8e8", - "reference": "442fd9cdbacc0732eea4018bc1f0df7e4004b8e8", + "url": "https://api.github.com/repos/illuminate/events/zipball/59f6074ff6b14b475c7c97021dcbcd2e2bce2ebd", + "reference": "59f6074ff6b14b475c7c97021dcbcd2e2bce2ebd", "shasum": "" }, "require": { @@ -937,11 +937,11 @@ ], "description": "The Illuminate Events package.", "homepage": "https://laravel.com", - "time": "2020-02-11T22:47:28+00:00" + "time": "2020-04-14T13:14:16+00:00" }, { "name": "illuminate/filesystem", - "version": "v7.4.0", + "version": "v7.6.2", "source": { "type": "git", "url": "https://github.com/illuminate/filesystem.git", @@ -993,17 +993,120 @@ "time": "2020-03-26T19:53:03+00:00" }, { - "name": "illuminate/support", - "version": "v7.4.0", + "name": "illuminate/http", + "version": "v7.6.2", "source": { "type": "git", - "url": "https://github.com/illuminate/support.git", - "reference": "6b5a135637bf901e5dd9c0e3d906a97d550d4cee" + "url": "https://github.com/illuminate/http.git", + "reference": "c11e7175b7b751ce8ae5dfac7fbe46d47b6c2f39" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/support/zipball/6b5a135637bf901e5dd9c0e3d906a97d550d4cee", - "reference": "6b5a135637bf901e5dd9c0e3d906a97d550d4cee", + "url": "https://api.github.com/repos/illuminate/http/zipball/c11e7175b7b751ce8ae5dfac7fbe46d47b6c2f39", + "reference": "c11e7175b7b751ce8ae5dfac7fbe46d47b6c2f39", + "shasum": "" + }, + "require": { + "ext-json": "*", + "illuminate/session": "^7.0", + "illuminate/support": "^7.0", + "php": "^7.2.5", + "symfony/http-foundation": "^5.0", + "symfony/http-kernel": "^5.0", + "symfony/mime": "^5.0" + }, + "suggest": { + "ext-gd": "Required to use Illuminate\\Http\\Testing\\FileFactory::image().", + "guzzlehttp/guzzle": "Required to use the HTTP Client (^6.3.1|^7.0)." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "7.x-dev" + } + }, + "autoload": { + "psr-4": { + "Illuminate\\Http\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Illuminate Http package.", + "homepage": "https://laravel.com", + "time": "2020-04-15T18:37:09+00:00" + }, + { + "name": "illuminate/session", + "version": "v7.6.2", + "source": { + "type": "git", + "url": "https://github.com/illuminate/session.git", + "reference": "4285f5208e0a59286763c591281d5d6e66e66b84" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/illuminate/session/zipball/4285f5208e0a59286763c591281d5d6e66e66b84", + "reference": "4285f5208e0a59286763c591281d5d6e66e66b84", + "shasum": "" + }, + "require": { + "ext-json": "*", + "illuminate/contracts": "^7.0", + "illuminate/filesystem": "^7.0", + "illuminate/support": "^7.0", + "php": "^7.2.5", + "symfony/finder": "^5.0", + "symfony/http-foundation": "^5.0" + }, + "suggest": { + "illuminate/console": "Required to use the session:table command (^7.0)." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "7.x-dev" + } + }, + "autoload": { + "psr-4": { + "Illuminate\\Session\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Illuminate Session package.", + "homepage": "https://laravel.com", + "time": "2020-01-07T13:49:44+00:00" + }, + { + "name": "illuminate/support", + "version": "v7.6.2", + "source": { + "type": "git", + "url": "https://github.com/illuminate/support.git", + "reference": "b6f64a42377f86b293960e0b7f6920ae59e578d2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/illuminate/support/zipball/b6f64a42377f86b293960e0b7f6920ae59e578d2", + "reference": "b6f64a42377f86b293960e0b7f6920ae59e578d2", "shasum": "" }, "require": { @@ -1052,20 +1155,20 @@ ], "description": "The Illuminate Support package.", "homepage": "https://laravel.com", - "time": "2020-03-30T13:52:20+00:00" + "time": "2020-04-15T19:48:40+00:00" }, { "name": "illuminate/testing", - "version": "v7.4.0", + "version": "v7.6.2", "source": { "type": "git", "url": "https://github.com/illuminate/testing.git", - "reference": "55fde302562febe3461c5732e6972b1626bfabcc" + "reference": "670d48ce1afd008d6e48b2a77c29691ffd4581a3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/testing/zipball/55fde302562febe3461c5732e6972b1626bfabcc", - "reference": "55fde302562febe3461c5732e6972b1626bfabcc", + "url": "https://api.github.com/repos/illuminate/testing/zipball/670d48ce1afd008d6e48b2a77c29691ffd4581a3", + "reference": "670d48ce1afd008d6e48b2a77c29691ffd4581a3", "shasum": "" }, "require": { @@ -1103,97 +1206,7 @@ ], "description": "The Illuminate Testing package.", "homepage": "https://laravel.com", - "time": "2020-03-30T13:58:03+00:00" - }, - { - "name": "jakub-onderka/php-console-color", - "version": "v0.2", - "source": { - "type": "git", - "url": "https://github.com/JakubOnderka/PHP-Console-Color.git", - "reference": "d5deaecff52a0d61ccb613bb3804088da0307191" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/JakubOnderka/PHP-Console-Color/zipball/d5deaecff52a0d61ccb613bb3804088da0307191", - "reference": "d5deaecff52a0d61ccb613bb3804088da0307191", - "shasum": "" - }, - "require": { - "php": ">=5.4.0" - }, - "require-dev": { - "jakub-onderka/php-code-style": "1.0", - "jakub-onderka/php-parallel-lint": "1.0", - "jakub-onderka/php-var-dump-check": "0.*", - "phpunit/phpunit": "~4.3", - "squizlabs/php_codesniffer": "1.*" - }, - "type": "library", - "autoload": { - "psr-4": { - "JakubOnderka\\PhpConsoleColor\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-2-Clause" - ], - "authors": [ - { - "name": "Jakub Onderka", - "email": "jakub.onderka@gmail.com" - } - ], - "abandoned": "php-parallel-lint/php-console-color", - "time": "2018-09-29T17:23:10+00:00" - }, - { - "name": "jakub-onderka/php-console-highlighter", - "version": "v0.4", - "source": { - "type": "git", - "url": "https://github.com/JakubOnderka/PHP-Console-Highlighter.git", - "reference": "9f7a229a69d52506914b4bc61bfdb199d90c5547" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/JakubOnderka/PHP-Console-Highlighter/zipball/9f7a229a69d52506914b4bc61bfdb199d90c5547", - "reference": "9f7a229a69d52506914b4bc61bfdb199d90c5547", - "shasum": "" - }, - "require": { - "ext-tokenizer": "*", - "jakub-onderka/php-console-color": "~0.2", - "php": ">=5.4.0" - }, - "require-dev": { - "jakub-onderka/php-code-style": "~1.0", - "jakub-onderka/php-parallel-lint": "~1.0", - "jakub-onderka/php-var-dump-check": "~0.1", - "phpunit/phpunit": "~4.0", - "squizlabs/php_codesniffer": "~1.5" - }, - "type": "library", - "autoload": { - "psr-4": { - "JakubOnderka\\PhpConsoleHighlighter\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jakub Onderka", - "email": "acci@acci.cz", - "homepage": "http://www.acci.cz/" - } - ], - "description": "Highlight PHP code in terminal", - "abandoned": "php-parallel-lint/php-console-highlighter", - "time": "2018-09-29T18:48:56+00:00" + "time": "2020-04-14T14:05:27+00:00" }, { "name": "jolicode/jolinotif", @@ -1642,16 +1655,16 @@ }, { "name": "laravel-zero/foundation", - "version": "v7.4.0", + "version": "v7.6.1", "source": { "type": "git", "url": "https://github.com/laravel-zero/foundation.git", - "reference": "99b7b78ceb78252249478e1cde228e5e48e3fd64" + "reference": "61438f6d9220d2e20f8610ccbe894507d89f8f1a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel-zero/foundation/zipball/99b7b78ceb78252249478e1cde228e5e48e3fd64", - "reference": "99b7b78ceb78252249478e1cde228e5e48e3fd64", + "url": "https://api.github.com/repos/laravel-zero/foundation/zipball/61438f6d9220d2e20f8610ccbe894507d89f8f1a", + "reference": "61438f6d9220d2e20f8610ccbe894507d89f8f1a", "shasum": "" }, "require": { @@ -1680,7 +1693,7 @@ "framework", "laravel" ], - "time": "2020-04-01T08:40:16+00:00" + "time": "2020-04-14T16:39:20+00:00" }, { "name": "laravel-zero/framework", @@ -1852,6 +1865,56 @@ ], "time": "2020-03-17T18:58:12+00:00" }, + { + "name": "namshi/cuzzle", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/namshi/cuzzle.git", + "reference": "89849bb9c729a3d8aabf94c0b66e77c7df38abda" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/namshi/cuzzle/zipball/89849bb9c729a3d8aabf94c0b66e77c7df38abda", + "reference": "89849bb9c729a3d8aabf94c0b66e77c7df38abda", + "shasum": "" + }, + "require": { + "guzzlehttp/guzzle": "^6.0", + "php": ">=5.5.0", + "psr/log": "^1.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.2.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Namshi\\Cuzzle\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nikita Nefedov", + "email": "inefedor@gmail.com" + }, + { + "name": "cirpo", + "email": "alessandro.cinelli@gmail.com" + } + ], + "description": "Get the cURL shell command from a Guzzle request", + "time": "2016-11-23T08:01:36+00:00" + }, { "name": "nesbot/carbon", "version": "2.32.2", @@ -1925,28 +1988,28 @@ }, { "name": "nunomaduro/collision", - "version": "v4.1.3", + "version": "v4.2.0", "source": { "type": "git", "url": "https://github.com/nunomaduro/collision.git", - "reference": "a430bce33d1ad07f756ea6cae9afce9ef8670b42" + "reference": "d50490417eded97be300a92cd7df7badc37a9018" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nunomaduro/collision/zipball/a430bce33d1ad07f756ea6cae9afce9ef8670b42", - "reference": "a430bce33d1ad07f756ea6cae9afce9ef8670b42", + "url": "https://api.github.com/repos/nunomaduro/collision/zipball/d50490417eded97be300a92cd7df7badc37a9018", + "reference": "d50490417eded97be300a92cd7df7badc37a9018", "shasum": "" }, "require": { "facade/ignition-contracts": "^1.0", "filp/whoops": "^2.4", - "jakub-onderka/php-console-highlighter": "^0.4", "php": "^7.2.5", "symfony/console": "^5.0" }, "require-dev": { "facade/ignition": "^2.0", "fideloper/proxy": "^4.2", + "friendsofphp/php-cs-fixer": "^2.16", "fruitcake/laravel-cors": "^1.0", "laravel/framework": "^7.0", "laravel/tinker": "^2.0", @@ -1991,7 +2054,7 @@ "php", "symfony" ], - "time": "2020-03-07T12:46:00+00:00" + "time": "2020-04-04T19:56:08+00:00" }, { "name": "nunomaduro/laravel-console-summary", @@ -2321,6 +2384,52 @@ ], "time": "2017-02-14T16:28:37+00:00" }, + { + "name": "psr/event-dispatcher", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/event-dispatcher.git", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", + "shasum": "" + }, + "require": { + "php": ">=7.2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\EventDispatcher\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Standard interfaces for event handling.", + "keywords": [ + "events", + "psr", + "psr-14" + ], + "time": "2019-01-08T18:20:26+00:00" + }, { "name": "psr/http-message", "version": "1.0.1", @@ -3301,6 +3410,134 @@ "homepage": "https://symfony.com", "time": "2020-03-30T14:14:32+00:00" }, + { + "name": "symfony/event-dispatcher", + "version": "v5.0.7", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "24f40d95385774ed5c71dbf014edd047e2f2f3dc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/24f40d95385774ed5c71dbf014edd047e2f2f3dc", + "reference": "24f40d95385774ed5c71dbf014edd047e2f2f3dc", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "symfony/event-dispatcher-contracts": "^2" + }, + "conflict": { + "symfony/dependency-injection": "<4.4" + }, + "provide": { + "psr/event-dispatcher-implementation": "1.0", + "symfony/event-dispatcher-implementation": "2.0" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "^4.4|^5.0", + "symfony/dependency-injection": "^4.4|^5.0", + "symfony/expression-language": "^4.4|^5.0", + "symfony/http-foundation": "^4.4|^5.0", + "symfony/service-contracts": "^1.1|^2", + "symfony/stopwatch": "^4.4|^5.0" + }, + "suggest": { + "symfony/dependency-injection": "", + "symfony/http-kernel": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\EventDispatcher\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony EventDispatcher Component", + "homepage": "https://symfony.com", + "time": "2020-03-27T16:56:45+00:00" + }, + { + "name": "symfony/event-dispatcher-contracts", + "version": "v2.0.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher-contracts.git", + "reference": "af23c2584d4577d54661c434446fb8fbed6025dd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/af23c2584d4577d54661c434446fb8fbed6025dd", + "reference": "af23c2584d4577d54661c434446fb8fbed6025dd", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "psr/event-dispatcher": "^1" + }, + "suggest": { + "symfony/event-dispatcher-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\EventDispatcher\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to dispatching event", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "time": "2019-11-18T17:27:11+00:00" + }, { "name": "symfony/finder", "version": "v5.0.7", @@ -3405,6 +3642,102 @@ "homepage": "https://symfony.com", "time": "2020-03-30T14:14:32+00:00" }, + { + "name": "symfony/http-kernel", + "version": "v5.0.7", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-kernel.git", + "reference": "ad574c55d451127cab1c45b4ac51bf283e340cf0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/ad574c55d451127cab1c45b4ac51bf283e340cf0", + "reference": "ad574c55d451127cab1c45b4ac51bf283e340cf0", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "psr/log": "~1.0", + "symfony/error-handler": "^4.4|^5.0", + "symfony/event-dispatcher": "^5.0", + "symfony/http-foundation": "^4.4|^5.0", + "symfony/polyfill-ctype": "^1.8", + "symfony/polyfill-php73": "^1.9" + }, + "conflict": { + "symfony/browser-kit": "<4.4", + "symfony/cache": "<5.0", + "symfony/config": "<5.0", + "symfony/dependency-injection": "<4.4", + "symfony/doctrine-bridge": "<5.0", + "symfony/form": "<5.0", + "symfony/http-client": "<5.0", + "symfony/mailer": "<5.0", + "symfony/messenger": "<5.0", + "symfony/translation": "<5.0", + "symfony/twig-bridge": "<5.0", + "symfony/validator": "<5.0", + "twig/twig": "<2.4" + }, + "provide": { + "psr/log-implementation": "1.0" + }, + "require-dev": { + "psr/cache": "~1.0", + "symfony/browser-kit": "^4.4|^5.0", + "symfony/config": "^5.0", + "symfony/console": "^4.4|^5.0", + "symfony/css-selector": "^4.4|^5.0", + "symfony/dependency-injection": "^4.4|^5.0", + "symfony/dom-crawler": "^4.4|^5.0", + "symfony/expression-language": "^4.4|^5.0", + "symfony/finder": "^4.4|^5.0", + "symfony/process": "^4.4|^5.0", + "symfony/routing": "^4.4|^5.0", + "symfony/stopwatch": "^4.4|^5.0", + "symfony/translation": "^4.4|^5.0", + "symfony/translation-contracts": "^1.1|^2", + "twig/twig": "^2.4|^3.0" + }, + "suggest": { + "symfony/browser-kit": "", + "symfony/config": "", + "symfony/console": "", + "symfony/dependency-injection": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpKernel\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony HttpKernel Component", + "homepage": "https://symfony.com", + "time": "2020-03-30T15:04:59+00:00" + }, { "name": "symfony/mime", "version": "v5.0.7", @@ -3808,6 +4141,70 @@ "homepage": "https://symfony.com", "time": "2020-03-27T16:56:45+00:00" }, + { + "name": "symfony/psr-http-message-bridge", + "version": "v2.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/psr-http-message-bridge.git", + "reference": "ce709cd9c90872c08c2427b45739d5f3c781ab4f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/psr-http-message-bridge/zipball/ce709cd9c90872c08c2427b45739d5f3c781ab4f", + "reference": "ce709cd9c90872c08c2427b45739d5f3c781ab4f", + "shasum": "" + }, + "require": { + "php": "^7.1", + "psr/http-message": "^1.0", + "symfony/http-foundation": "^4.4 || ^5.0" + }, + "require-dev": { + "nyholm/psr7": "^1.1", + "symfony/phpunit-bridge": "^4.4 || ^5.0" + }, + "suggest": { + "nyholm/psr7": "For a super lightweight PSR-7/17 implementation" + }, + "type": "symfony-bridge", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Bridge\\PsrHttpMessage\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + } + ], + "description": "PSR HTTP message bridge", + "homepage": "http://symfony.com", + "keywords": [ + "http", + "http-message", + "psr-17", + "psr-7" + ], + "time": "2020-01-02T08:07:11+00:00" + }, { "name": "symfony/routing", "version": "v5.0.7", @@ -4153,16 +4550,16 @@ }, { "name": "vlucas/phpdotenv", - "version": "v4.1.3", + "version": "v4.1.4", "source": { "type": "git", "url": "https://github.com/vlucas/phpdotenv.git", - "reference": "88f7acc95150bca002a498899f8b52f318e444c2" + "reference": "feb6dad5ae24b1380827aee1629b730080fde500" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/88f7acc95150bca002a498899f8b52f318e444c2", - "reference": "88f7acc95150bca002a498899f8b52f318e444c2", + "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/feb6dad5ae24b1380827aee1629b730080fde500", + "reference": "feb6dad5ae24b1380827aee1629b730080fde500", "shasum": "" }, "require": { @@ -4213,7 +4610,7 @@ "env", "environment" ], - "time": "2020-03-27T23:37:15+00:00" + "time": "2020-04-12T15:20:09+00:00" }, { "name": "voku/portable-ascii", diff --git a/config/app.php b/config/app.php index 83174b4..10c90fa 100644 --- a/config/app.php +++ b/config/app.php @@ -13,7 +13,7 @@ return [ | */ - 'name' => 'Phunnel', + 'name' => 'Expose', /* |-------------------------------------------------------------------------- diff --git a/phunnel b/expose similarity index 100% rename from phunnel rename to expose diff --git a/resources/views/index.html b/resources/views/index.html index cee1de8..e6953c8 100644 --- a/resources/views/index.html +++ b/resources/views/index.html @@ -2,9 +2,82 @@
- + -+ Waiting for requests on: %subdomains% +
+|
- - {{ log.request.method }} - {{ log.request.uri }} - - {{ log.subdomain }} - |
-
-
- {{ log.response.status }} - {{ log.response.reason }}
-
-
- ...
-
- |
-
-
- {{ log.duration }}ms
-
- |
-
|
+ + {{ log.request.method }} + {{ log.request.uri }} + + {{ log.subdomain }} + |
+
+
+ {{ log.response.status }} - {{ log.response.reason }}
+
+
+ ...
+
+ |
+
+
+ {{ log.duration }}ms
+
+ |
+
Status code: {{ currentLog.response?.status}} @@ -135,7 +236,8 @@ {{ parameter.name }}
{{ currentLog.response.body }}
+ {{ currentLog.response.body }}
+