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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -36,7 +36,7 @@ class AppServiceProvider extends ServiceProvider
$localConfigFile = getcwd() . DIRECTORY_SEPARATOR . '.expose.php'; $localConfigFile = getcwd() . DIRECTORY_SEPARATOR . '.expose.php';
if (file_exists($localConfigFile)) { if (file_exists($localConfigFile)) {
$localConfig = require_once $localConfigFile; $localConfig = require $localConfigFile;
config()->set('expose', array_merge($builtInConfig, $localConfig)); config()->set('expose', array_merge($builtInConfig, $localConfig));
return; return;
} }
@@ -49,7 +49,7 @@ class AppServiceProvider extends ServiceProvider
]); ]);
if (file_exists($configFile)) { if (file_exists($configFile)) {
$globalConfig = require_once $configFile; $globalConfig = require $configFile;
config()->set('expose', array_merge($builtInConfig, $globalConfig)); 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\ConnectionManager as ConnectionManagerContract;
use App\Contracts\SubdomainGenerator; use App\Contracts\SubdomainGenerator;
use App\HttpServer\HttpServer; use App\Http\Server as HttpServer;
use App\Server\Connections\ConnectionManager; use App\Server\Connections\ConnectionManager;
use App\Server\Http\Controllers\Admin\DeleteUsersController; use App\Server\Http\Controllers\Admin\DeleteUsersController;
use App\Server\Http\Controllers\Admin\ListSitesController; 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\Admin\VerifyLoginController;
use App\Server\Http\Controllers\ControlMessageController; use App\Server\Http\Controllers\ControlMessageController;
use App\Server\Http\Controllers\TunnelMessageController; use App\Server\Http\Controllers\TunnelMessageController;
use App\Server\Http\RouteGenerator; use App\Http\RouteGenerator;
use App\Server\Http\Router; use App\Server\Http\Router;
use App\Server\SubdomainGenerator\RandomSubdomainGenerator; use App\Server\SubdomainGenerator\RandomSubdomainGenerator;
use Clue\React\SQLite\DatabaseInterface; use Clue\React\SQLite\DatabaseInterface;

View File

@@ -2,7 +2,7 @@
namespace App\Server\Http\Controllers\Admin; 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\DatabaseInterface;
use Clue\React\SQLite\Result; use Clue\React\SQLite\Result;
use GuzzleHttp\Psr7\Response; use GuzzleHttp\Psr7\Response;

View File

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

View File

@@ -2,7 +2,7 @@
namespace App\Server\Http\Controllers\Admin; 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\DatabaseInterface;
use Clue\React\SQLite\Result; use Clue\React\SQLite\Result;
use GuzzleHttp\Psr7\Response; use GuzzleHttp\Psr7\Response;

View File

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

View File

@@ -2,7 +2,7 @@
namespace App\Server\Http\Controllers\Admin; 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\DatabaseInterface;
use Clue\React\SQLite\Result; use Clue\React\SQLite\Result;
use GuzzleHttp\Psr7\Response; use GuzzleHttp\Psr7\Response;

View File

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

View File

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

View File

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

View File

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

View File

@@ -31,7 +31,7 @@
"illuminate/validation": "^7.7", "illuminate/validation": "^7.7",
"laminas/laminas-http": "^2.11", "laminas/laminas-http": "^2.11",
"laravel-zero/framework": "^7.0", "laravel-zero/framework": "^7.0",
"mockery/mockery": "^1.3.1", "mockery/mockery": "^1.3",
"namshi/cuzzle": "^2.0", "namshi/cuzzle": "^2.0",
"nyholm/psr7": "^1.2", "nyholm/psr7": "^1.2",
"phpunit/phpunit": "^8.5", "phpunit/phpunit": "^8.5",

218
composer.lock generated
View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "3199f5982eed399c719f72239be99a83", "content-hash": "17ed4fb1b80fc6efe2594c3bfbbf3c7f",
"packages": [], "packages": [],
"packages-dev": [ "packages-dev": [
{ {
@@ -1047,7 +1047,7 @@
}, },
{ {
"name": "illuminate/cache", "name": "illuminate/cache",
"version": "v7.7.1", "version": "v7.9.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/illuminate/cache.git", "url": "https://github.com/illuminate/cache.git",
@@ -1098,7 +1098,7 @@
}, },
{ {
"name": "illuminate/config", "name": "illuminate/config",
"version": "v7.7.1", "version": "v7.9.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/illuminate/config.git", "url": "https://github.com/illuminate/config.git",
@@ -1142,16 +1142,16 @@
}, },
{ {
"name": "illuminate/console", "name": "illuminate/console",
"version": "v7.7.1", "version": "v7.9.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/illuminate/console.git", "url": "https://github.com/illuminate/console.git",
"reference": "364648fc102ca0b3a7834934ed5885c11e285f29" "reference": "3056c8d5069115c0bc86a5dc70b22710d427e259"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/illuminate/console/zipball/364648fc102ca0b3a7834934ed5885c11e285f29", "url": "https://api.github.com/repos/illuminate/console/zipball/3056c8d5069115c0bc86a5dc70b22710d427e259",
"reference": "364648fc102ca0b3a7834934ed5885c11e285f29", "reference": "3056c8d5069115c0bc86a5dc70b22710d427e259",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -1192,20 +1192,20 @@
], ],
"description": "The Illuminate Console package.", "description": "The Illuminate Console package.",
"homepage": "https://laravel.com", "homepage": "https://laravel.com",
"time": "2020-04-20T09:32:33+00:00" "time": "2020-04-24T09:01:47+00:00"
}, },
{ {
"name": "illuminate/container", "name": "illuminate/container",
"version": "v7.7.1", "version": "v7.9.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/illuminate/container.git", "url": "https://github.com/illuminate/container.git",
"reference": "aa8dfe90a3eb31dc760adc911647be5d2e129c8a" "reference": "78a134ab5bcf6e6e50321dfb0d602b698898698d"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/illuminate/container/zipball/aa8dfe90a3eb31dc760adc911647be5d2e129c8a", "url": "https://api.github.com/repos/illuminate/container/zipball/78a134ab5bcf6e6e50321dfb0d602b698898698d",
"reference": "aa8dfe90a3eb31dc760adc911647be5d2e129c8a", "reference": "78a134ab5bcf6e6e50321dfb0d602b698898698d",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -1236,20 +1236,20 @@
], ],
"description": "The Illuminate Container package.", "description": "The Illuminate Container package.",
"homepage": "https://laravel.com", "homepage": "https://laravel.com",
"time": "2020-04-20T14:17:11+00:00" "time": "2020-04-23T13:57:26+00:00"
}, },
{ {
"name": "illuminate/contracts", "name": "illuminate/contracts",
"version": "v7.7.1", "version": "v7.9.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/illuminate/contracts.git", "url": "https://github.com/illuminate/contracts.git",
"reference": "69a40779d8fc43e3f43da973b9c0c20bdbd81203" "reference": "4f9cad4bd982e9f100b1f0a42677fdd3bbfa48fd"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/illuminate/contracts/zipball/69a40779d8fc43e3f43da973b9c0c20bdbd81203", "url": "https://api.github.com/repos/illuminate/contracts/zipball/4f9cad4bd982e9f100b1f0a42677fdd3bbfa48fd",
"reference": "69a40779d8fc43e3f43da973b9c0c20bdbd81203", "reference": "4f9cad4bd982e9f100b1f0a42677fdd3bbfa48fd",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -1280,11 +1280,11 @@
], ],
"description": "The Illuminate Contracts package.", "description": "The Illuminate Contracts package.",
"homepage": "https://laravel.com", "homepage": "https://laravel.com",
"time": "2020-04-09T15:01:22+00:00" "time": "2020-04-28T07:21:27+00:00"
}, },
{ {
"name": "illuminate/events", "name": "illuminate/events",
"version": "v7.7.1", "version": "v7.9.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/illuminate/events.git", "url": "https://github.com/illuminate/events.git",
@@ -1329,7 +1329,7 @@
}, },
{ {
"name": "illuminate/filesystem", "name": "illuminate/filesystem",
"version": "v7.7.1", "version": "v7.9.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/illuminate/filesystem.git", "url": "https://github.com/illuminate/filesystem.git",
@@ -1382,16 +1382,16 @@
}, },
{ {
"name": "illuminate/http", "name": "illuminate/http",
"version": "v7.7.1", "version": "v7.9.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/illuminate/http.git", "url": "https://github.com/illuminate/http.git",
"reference": "05444c7ecfad9e12c42d75f6b9a3dd0adb8b0a57" "reference": "d9f6088b0296fa41c0a4afa6a2ec27a156d4917e"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/illuminate/http/zipball/05444c7ecfad9e12c42d75f6b9a3dd0adb8b0a57", "url": "https://api.github.com/repos/illuminate/http/zipball/d9f6088b0296fa41c0a4afa6a2ec27a156d4917e",
"reference": "05444c7ecfad9e12c42d75f6b9a3dd0adb8b0a57", "reference": "d9f6088b0296fa41c0a4afa6a2ec27a156d4917e",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -1430,11 +1430,11 @@
], ],
"description": "The Illuminate Http package.", "description": "The Illuminate Http package.",
"homepage": "https://laravel.com", "homepage": "https://laravel.com",
"time": "2020-04-20T08:03:18+00:00" "time": "2020-04-24T17:19:43+00:00"
}, },
{ {
"name": "illuminate/pipeline", "name": "illuminate/pipeline",
"version": "v7.7.1", "version": "v7.9.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/illuminate/pipeline.git", "url": "https://github.com/illuminate/pipeline.git",
@@ -1478,7 +1478,7 @@
}, },
{ {
"name": "illuminate/session", "name": "illuminate/session",
"version": "v7.7.1", "version": "v7.9.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/illuminate/session.git", "url": "https://github.com/illuminate/session.git",
@@ -1529,16 +1529,16 @@
}, },
{ {
"name": "illuminate/support", "name": "illuminate/support",
"version": "v7.7.1", "version": "v7.9.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/illuminate/support.git", "url": "https://github.com/illuminate/support.git",
"reference": "7143690b5b718a4a89f8a1ecda79833e75dd138c" "reference": "677a3ad776db92b339a2926927929d0b070642ea"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/illuminate/support/zipball/7143690b5b718a4a89f8a1ecda79833e75dd138c", "url": "https://api.github.com/repos/illuminate/support/zipball/677a3ad776db92b339a2926927929d0b070642ea",
"reference": "7143690b5b718a4a89f8a1ecda79833e75dd138c", "reference": "677a3ad776db92b339a2926927929d0b070642ea",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -1587,20 +1587,20 @@
], ],
"description": "The Illuminate Support package.", "description": "The Illuminate Support package.",
"homepage": "https://laravel.com", "homepage": "https://laravel.com",
"time": "2020-04-21T15:58:25+00:00" "time": "2020-04-28T07:20:41+00:00"
}, },
{ {
"name": "illuminate/testing", "name": "illuminate/testing",
"version": "v7.7.1", "version": "v7.9.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/illuminate/testing.git", "url": "https://github.com/illuminate/testing.git",
"reference": "5ec43e2778a5454b31b886f2ed4f4b2d291419fd" "reference": "8594d186a6a6b9a584043b06d00099b2481f2018"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/illuminate/testing/zipball/5ec43e2778a5454b31b886f2ed4f4b2d291419fd", "url": "https://api.github.com/repos/illuminate/testing/zipball/8594d186a6a6b9a584043b06d00099b2481f2018",
"reference": "5ec43e2778a5454b31b886f2ed4f4b2d291419fd", "reference": "8594d186a6a6b9a584043b06d00099b2481f2018",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -1638,11 +1638,11 @@
], ],
"description": "The Illuminate Testing package.", "description": "The Illuminate Testing package.",
"homepage": "https://laravel.com", "homepage": "https://laravel.com",
"time": "2020-04-16T17:12:54+00:00" "time": "2020-04-27T14:32:07+00:00"
}, },
{ {
"name": "illuminate/translation", "name": "illuminate/translation",
"version": "v7.7.1", "version": "v7.9.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/illuminate/translation.git", "url": "https://github.com/illuminate/translation.git",
@@ -1688,16 +1688,16 @@
}, },
{ {
"name": "illuminate/validation", "name": "illuminate/validation",
"version": "v7.7.1", "version": "v7.9.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/illuminate/validation.git", "url": "https://github.com/illuminate/validation.git",
"reference": "99377aec3b5a2c2184d99de3dd7c8fb675e5a4ef" "reference": "24cf7ff8e4a274a42eb86c94796dc01dec9e5760"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/illuminate/validation/zipball/99377aec3b5a2c2184d99de3dd7c8fb675e5a4ef", "url": "https://api.github.com/repos/illuminate/validation/zipball/24cf7ff8e4a274a42eb86c94796dc01dec9e5760",
"reference": "99377aec3b5a2c2184d99de3dd7c8fb675e5a4ef", "reference": "24cf7ff8e4a274a42eb86c94796dc01dec9e5760",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -1737,7 +1737,7 @@
], ],
"description": "The Illuminate Validation package.", "description": "The Illuminate Validation package.",
"homepage": "https://laravel.com", "homepage": "https://laravel.com",
"time": "2020-04-19T19:55:49+00:00" "time": "2020-04-23T19:11:28+00:00"
}, },
{ {
"name": "jolicode/jolinotif", "name": "jolicode/jolinotif",
@@ -2186,16 +2186,16 @@
}, },
{ {
"name": "laravel-zero/foundation", "name": "laravel-zero/foundation",
"version": "v7.6.1", "version": "v7.8.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/laravel-zero/foundation.git", "url": "https://github.com/laravel-zero/foundation.git",
"reference": "61438f6d9220d2e20f8610ccbe894507d89f8f1a" "reference": "eb9fc2275706bdc150fdcc2ff9ec155fc74f7c65"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/laravel-zero/foundation/zipball/61438f6d9220d2e20f8610ccbe894507d89f8f1a", "url": "https://api.github.com/repos/laravel-zero/foundation/zipball/eb9fc2275706bdc150fdcc2ff9ec155fc74f7c65",
"reference": "61438f6d9220d2e20f8610ccbe894507d89f8f1a", "reference": "eb9fc2275706bdc150fdcc2ff9ec155fc74f7c65",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -2224,7 +2224,7 @@
"framework", "framework",
"laravel" "laravel"
], ],
"time": "2020-04-14T16:39:20+00:00" "time": "2020-04-27T08:21:33+00:00"
}, },
{ {
"name": "laravel-zero/framework", "name": "laravel-zero/framework",
@@ -3140,24 +3140,21 @@
}, },
{ {
"name": "phpdocumentor/reflection-common", "name": "phpdocumentor/reflection-common",
"version": "2.0.0", "version": "2.1.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/phpDocumentor/ReflectionCommon.git", "url": "https://github.com/phpDocumentor/ReflectionCommon.git",
"reference": "63a995caa1ca9e5590304cd845c15ad6d482a62a" "reference": "6568f4687e5b41b054365f9ae03fcb1ed5f2069b"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/63a995caa1ca9e5590304cd845c15ad6d482a62a", "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/6568f4687e5b41b054365f9ae03fcb1ed5f2069b",
"reference": "63a995caa1ca9e5590304cd845c15ad6d482a62a", "reference": "6568f4687e5b41b054365f9ae03fcb1ed5f2069b",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": ">=7.1" "php": ">=7.1"
}, },
"require-dev": {
"phpunit/phpunit": "~6"
},
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
@@ -3188,7 +3185,7 @@
"reflection", "reflection",
"static analysis" "static analysis"
], ],
"time": "2018-08-07T13:53:10+00:00" "time": "2020-04-27T09:25:28+00:00"
}, },
{ {
"name": "phpdocumentor/reflection-docblock", "name": "phpdocumentor/reflection-docblock",
@@ -5542,16 +5539,16 @@
}, },
{ {
"name": "symfony/cache", "name": "symfony/cache",
"version": "v5.0.7", "version": "v5.0.8",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/cache.git", "url": "https://github.com/symfony/cache.git",
"reference": "7c229da093cb0c630e5d16b99fd253e20f979ac2" "reference": "0c5f5b1882dc82b255a4bdead4ed3c7738cddc04"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/cache/zipball/7c229da093cb0c630e5d16b99fd253e20f979ac2", "url": "https://api.github.com/repos/symfony/cache/zipball/0c5f5b1882dc82b255a4bdead4ed3c7738cddc04",
"reference": "7c229da093cb0c630e5d16b99fd253e20f979ac2", "reference": "0c5f5b1882dc82b255a4bdead4ed3c7738cddc04",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -5617,7 +5614,7 @@
"caching", "caching",
"psr6" "psr6"
], ],
"time": "2020-03-27T16:56:45+00:00" "time": "2020-04-28T17:58:55+00:00"
}, },
{ {
"name": "symfony/cache-contracts", "name": "symfony/cache-contracts",
@@ -5679,7 +5676,7 @@
}, },
{ {
"name": "symfony/console", "name": "symfony/console",
"version": "v5.0.7", "version": "v5.0.8",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/console.git", "url": "https://github.com/symfony/console.git",
@@ -5755,7 +5752,7 @@
}, },
{ {
"name": "symfony/error-handler", "name": "symfony/error-handler",
"version": "v5.0.7", "version": "v5.0.8",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/error-handler.git", "url": "https://github.com/symfony/error-handler.git",
@@ -5810,7 +5807,7 @@
}, },
{ {
"name": "symfony/event-dispatcher", "name": "symfony/event-dispatcher",
"version": "v5.0.7", "version": "v5.0.8",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/event-dispatcher.git", "url": "https://github.com/symfony/event-dispatcher.git",
@@ -5938,16 +5935,16 @@
}, },
{ {
"name": "symfony/expression-language", "name": "symfony/expression-language",
"version": "v5.0.7", "version": "v5.0.8",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/expression-language.git", "url": "https://github.com/symfony/expression-language.git",
"reference": "00e044885469d193c3b8dfa62030cd4525576d4e" "reference": "b93755750b9e2a8d240bdf014de5b545105c5178"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/expression-language/zipball/00e044885469d193c3b8dfa62030cd4525576d4e", "url": "https://api.github.com/repos/symfony/expression-language/zipball/b93755750b9e2a8d240bdf014de5b545105c5178",
"reference": "00e044885469d193c3b8dfa62030cd4525576d4e", "reference": "b93755750b9e2a8d240bdf014de5b545105c5178",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -5985,11 +5982,11 @@
], ],
"description": "Symfony ExpressionLanguage Component", "description": "Symfony ExpressionLanguage Component",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"time": "2020-03-27T16:56:45+00:00" "time": "2020-04-15T15:59:10+00:00"
}, },
{ {
"name": "symfony/finder", "name": "symfony/finder",
"version": "v5.0.7", "version": "v5.0.8",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/finder.git", "url": "https://github.com/symfony/finder.git",
@@ -6038,16 +6035,16 @@
}, },
{ {
"name": "symfony/http-foundation", "name": "symfony/http-foundation",
"version": "v5.0.7", "version": "v5.0.8",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/http-foundation.git", "url": "https://github.com/symfony/http-foundation.git",
"reference": "26fb006a2c7b6cdd23d52157b05f8414ffa417b6" "reference": "e47fdf8b24edc12022ba52923150ec6484d7f57d"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/26fb006a2c7b6cdd23d52157b05f8414ffa417b6", "url": "https://api.github.com/repos/symfony/http-foundation/zipball/e47fdf8b24edc12022ba52923150ec6484d7f57d",
"reference": "26fb006a2c7b6cdd23d52157b05f8414ffa417b6", "reference": "e47fdf8b24edc12022ba52923150ec6484d7f57d",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -6089,20 +6086,20 @@
], ],
"description": "Symfony HttpFoundation Component", "description": "Symfony HttpFoundation Component",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"time": "2020-03-30T14:14:32+00:00" "time": "2020-04-18T20:50:06+00:00"
}, },
{ {
"name": "symfony/http-kernel", "name": "symfony/http-kernel",
"version": "v5.0.7", "version": "v5.0.8",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/http-kernel.git", "url": "https://github.com/symfony/http-kernel.git",
"reference": "ad574c55d451127cab1c45b4ac51bf283e340cf0" "reference": "3565e51eecd06106304baba5ccb7ba89db2d7d2b"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/http-kernel/zipball/ad574c55d451127cab1c45b4ac51bf283e340cf0", "url": "https://api.github.com/repos/symfony/http-kernel/zipball/3565e51eecd06106304baba5ccb7ba89db2d7d2b",
"reference": "ad574c55d451127cab1c45b4ac51bf283e340cf0", "reference": "3565e51eecd06106304baba5ccb7ba89db2d7d2b",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -6118,6 +6115,7 @@
"symfony/browser-kit": "<4.4", "symfony/browser-kit": "<4.4",
"symfony/cache": "<5.0", "symfony/cache": "<5.0",
"symfony/config": "<5.0", "symfony/config": "<5.0",
"symfony/console": "<4.4",
"symfony/dependency-injection": "<4.4", "symfony/dependency-injection": "<4.4",
"symfony/doctrine-bridge": "<5.0", "symfony/doctrine-bridge": "<5.0",
"symfony/form": "<5.0", "symfony/form": "<5.0",
@@ -6185,20 +6183,20 @@
], ],
"description": "Symfony HttpKernel Component", "description": "Symfony HttpKernel Component",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"time": "2020-03-30T15:04:59+00:00" "time": "2020-04-28T18:53:25+00:00"
}, },
{ {
"name": "symfony/mime", "name": "symfony/mime",
"version": "v5.0.7", "version": "v5.0.8",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/mime.git", "url": "https://github.com/symfony/mime.git",
"reference": "481b7d6da88922fb1e0d86a943987722b08f3955" "reference": "5d6c81c39225a750f3f43bee15f03093fb9aaa0b"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/mime/zipball/481b7d6da88922fb1e0d86a943987722b08f3955", "url": "https://api.github.com/repos/symfony/mime/zipball/5d6c81c39225a750f3f43bee15f03093fb9aaa0b",
"reference": "481b7d6da88922fb1e0d86a943987722b08f3955", "reference": "5d6c81c39225a750f3f43bee15f03093fb9aaa0b",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -6247,7 +6245,7 @@
"mime", "mime",
"mime-type" "mime-type"
], ],
"time": "2020-03-27T16:56:45+00:00" "time": "2020-04-17T03:29:44+00:00"
}, },
{ {
"name": "symfony/polyfill-ctype", "name": "symfony/polyfill-ctype",
@@ -6543,16 +6541,16 @@
}, },
{ {
"name": "symfony/process", "name": "symfony/process",
"version": "v5.0.7", "version": "v5.0.8",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/process.git", "url": "https://github.com/symfony/process.git",
"reference": "c5ca4a0fc16a0c888067d43fbcfe1f8a53d8e70e" "reference": "3179f68dff5bad14d38c4114a1dab98030801fd7"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/process/zipball/c5ca4a0fc16a0c888067d43fbcfe1f8a53d8e70e", "url": "https://api.github.com/repos/symfony/process/zipball/3179f68dff5bad14d38c4114a1dab98030801fd7",
"reference": "c5ca4a0fc16a0c888067d43fbcfe1f8a53d8e70e", "reference": "3179f68dff5bad14d38c4114a1dab98030801fd7",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -6588,7 +6586,7 @@
], ],
"description": "Symfony Process Component", "description": "Symfony Process Component",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"time": "2020-03-27T16:56:45+00:00" "time": "2020-04-15T15:59:10+00:00"
}, },
{ {
"name": "symfony/psr-http-message-bridge", "name": "symfony/psr-http-message-bridge",
@@ -6656,16 +6654,16 @@
}, },
{ {
"name": "symfony/routing", "name": "symfony/routing",
"version": "v5.0.7", "version": "v5.0.8",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/routing.git", "url": "https://github.com/symfony/routing.git",
"reference": "d98a95d0a684caba47a47c1c50c602a669dc973b" "reference": "9b18480a6e101f8d9ab7c483ace7c19441be5111"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/routing/zipball/d98a95d0a684caba47a47c1c50c602a669dc973b", "url": "https://api.github.com/repos/symfony/routing/zipball/9b18480a6e101f8d9ab7c483ace7c19441be5111",
"reference": "d98a95d0a684caba47a47c1c50c602a669dc973b", "reference": "9b18480a6e101f8d9ab7c483ace7c19441be5111",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -6728,7 +6726,7 @@
"uri", "uri",
"url" "url"
], ],
"time": "2020-03-30T11:42:42+00:00" "time": "2020-04-21T21:02:50+00:00"
}, },
{ {
"name": "symfony/service-contracts", "name": "symfony/service-contracts",
@@ -6790,16 +6788,16 @@
}, },
{ {
"name": "symfony/translation", "name": "symfony/translation",
"version": "v5.0.7", "version": "v5.0.8",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/translation.git", "url": "https://github.com/symfony/translation.git",
"reference": "99b831770e10807dca0979518e2c89edffef5978" "reference": "c3879db7a68fe3e12b41263b05879412c87b27fd"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/translation/zipball/99b831770e10807dca0979518e2c89edffef5978", "url": "https://api.github.com/repos/symfony/translation/zipball/c3879db7a68fe3e12b41263b05879412c87b27fd",
"reference": "99b831770e10807dca0979518e2c89edffef5978", "reference": "c3879db7a68fe3e12b41263b05879412c87b27fd",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -6863,7 +6861,7 @@
], ],
"description": "Symfony Translation Component", "description": "Symfony Translation Component",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"time": "2020-03-27T16:56:45+00:00" "time": "2020-04-12T16:45:47+00:00"
}, },
{ {
"name": "symfony/translation-contracts", "name": "symfony/translation-contracts",
@@ -6924,16 +6922,16 @@
}, },
{ {
"name": "symfony/var-dumper", "name": "symfony/var-dumper",
"version": "v5.0.7", "version": "v5.0.8",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/var-dumper.git", "url": "https://github.com/symfony/var-dumper.git",
"reference": "f74a126acd701392eef2492a17228d42552c86b5" "reference": "09de28632f16f81058a85fcf318397218272a07b"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/f74a126acd701392eef2492a17228d42552c86b5", "url": "https://api.github.com/repos/symfony/var-dumper/zipball/09de28632f16f81058a85fcf318397218272a07b",
"reference": "f74a126acd701392eef2492a17228d42552c86b5", "reference": "09de28632f16f81058a85fcf318397218272a07b",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -6995,20 +6993,20 @@
"debug", "debug",
"dump" "dump"
], ],
"time": "2020-03-27T16:56:45+00:00" "time": "2020-04-12T16:45:47+00:00"
}, },
{ {
"name": "symfony/var-exporter", "name": "symfony/var-exporter",
"version": "v5.0.7", "version": "v5.0.8",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/var-exporter.git", "url": "https://github.com/symfony/var-exporter.git",
"reference": "ffd29a70370e466343e33154b5df197a07a13afa" "reference": "5d18811da9e1ae2bb86b0a97fb2d784e27ffd59f"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/var-exporter/zipball/ffd29a70370e466343e33154b5df197a07a13afa", "url": "https://api.github.com/repos/symfony/var-exporter/zipball/5d18811da9e1ae2bb86b0a97fb2d784e27ffd59f",
"reference": "ffd29a70370e466343e33154b5df197a07a13afa", "reference": "5d18811da9e1ae2bb86b0a97fb2d784e27ffd59f",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -7055,7 +7053,7 @@
"instantiate", "instantiate",
"serialize" "serialize"
], ],
"time": "2020-03-27T16:56:45+00:00" "time": "2020-04-15T15:59:10+00:00"
}, },
{ {
"name": "theseer/tokenizer", "name": "theseer/tokenizer",

View File

@@ -0,0 +1,139 @@
<?php
namespace Tests\Feature\Client;
use App\Client\Factory;
use App\Client\Http\HttpClient;
use App\Logger\LoggedRequest;
use App\Logger\RequestLogger;
use Clue\React\Buzz\Browser;
use Clue\React\Buzz\Message\ResponseException;
use GuzzleHttp\Psr7\Request;
use Mockery as m;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use React\EventLoop\LoopInterface;
use Symfony\Component\Console\Output\ConsoleOutput;
use Symfony\Component\Console\Output\ConsoleOutputInterface;
use function GuzzleHttp\Psr7\str;
class DashboardTest extends TestCase
{
/** @var Browser */
protected $browser;
/** @var Factory */
protected $dashboardFactory;
/** @var RequestLogger */
protected $requestLogger;
public function setUp(): void
{
parent::setUp();
$this->browser = new Browser($this->loop);
$this->requestLogger = $this->app->make(RequestLogger::class);
}
public function tearDown(): void
{
parent::tearDown();
$this->dashboardFactory->getApp()->close();
}
/** @test */
public function accessing_the_dashboard_works()
{
$this->startDashboard();
/** @var ResponseInterface $response */
$response = $this->await($this->browser->get('http://127.0.0.1:4040'));
$this->assertSame(200, $response->getStatusCode());
}
/** @test */
public function it_can_replay_requests()
{
$request = new Request('GET', '/example', [
'X-Expose-Request-ID' => 'request-one'
]);
$httpClient = m::mock(HttpClient::class);
$httpClient->shouldReceive('performRequest')
->once()
->with(str($request));
app()->instance(HttpClient::class, $httpClient);
$this->startDashboard();
$this->logRequest($request);
$this->assertSame(200,
$this->await($this->browser->get("http://127.0.0.1:4040/replay/request-one"))
->getStatusCode()
);
}
/** @test */
public function it_returns_404_for_non_existing_replay_logs()
{
$this->startDashboard();
$this->expectException(ResponseException::class);
$this->expectExceptionMessage(404);
$this->await($this->browser->get("http://127.0.0.1:4040/replay/invalid-request"));
}
/** @test */
public function it_can_clear_logs()
{
$this->startDashboard();
$this->logRequest(new Request('GET', '/foo'));
$this->logRequest(new Request('POST', '/bar'));
$this->logRequest(new Request('DELETE', '/baz'));
$this->assertCount(3, $this->requestLogger->getData());
$this->await($this->browser->get("http://127.0.0.1:4040/logs/clear"));
$this->assertCount(0, $this->requestLogger->getData());
}
/** @test */
public function it_can_attach_additional_data_to_requests()
{
$this->startDashboard();
$loggedRequest = $this->logRequest(new Request('GET', '/foo'));
$this->await($this->browser->post("http://127.0.0.1:4040/logs/{$loggedRequest->id()}/data", [
'Content-Type' => 'application/json'
], json_encode([
'data' => [
'foo' => 'bar',
]
])));
$this->assertSame([
'foo' => 'bar'
], $this->requestLogger->findLoggedRequest($loggedRequest->id())->getAdditionalData());
}
protected function logRequest(RequestInterface $request): LoggedRequest
{
return $this->requestLogger->logRequest(str($request), \Laminas\Http\Request::fromString(str($request)));
}
protected function startDashboard()
{
$this->dashboardFactory = (new Factory())
->setLoop($this->loop)
->createHttpServer();
}
}

View File

@@ -0,0 +1,36 @@
<?php
namespace Tests\Feature\Client;
use React\EventLoop\Factory;
use React\EventLoop\LoopInterface;
use React\EventLoop\StreamSelectLoop;
use React\Promise\PromiseInterface;
use Symfony\Component\Console\Output\ConsoleOutput;
use Symfony\Component\Console\Output\ConsoleOutputInterface;
use function Clue\React\Block\await;
abstract class TestCase extends \Tests\TestCase
{
const AWAIT_TIMEOUT = 1.0;
/** @var LoopInterface */
protected $loop;
public function setUp(): void
{
parent::setUp();
$this->app->bind(ConsoleOutputInterface::class, function() {
return new ConsoleOutput();
});
/** @var LoopInterface $loop */
$this->loop = $this->app->make(LoopInterface::class);
}
protected function await(PromiseInterface $promise, LoopInterface $loop = null, $timeout = null)
{
return await($promise, $loop ?? $this->loop, $timeout ?? static::AWAIT_TIMEOUT);
}
}

View File

@@ -1,20 +0,0 @@
<?php
namespace Tests\Feature;
use Tests\TestCase;
class InspiringCommandTest extends TestCase
{
/**
* A basic test example.
*
* @return void
*/
public function testInspiringCommand()
{
$this->artisan('inspiring')
->expectsOutput('Simplicity is the ultimate sophistication.')
->assertExitCode(0);
}
}

View File

@@ -1,18 +0,0 @@
<?php
namespace Tests\Unit;
use seregazhuk\React\PromiseTesting\TestCase;
class ExampleTest extends TestCase
{
/**
* A basic test example.
*
* @return void
*/
public function testBasicTest()
{
$this->assertTrue(true);
}
}

View File

@@ -0,0 +1,48 @@
<?php
namespace Tests\Unit;
use App\Logger\LoggedRequest;
use GuzzleHttp\Psr7\Request;
use Laminas\Http\Request as LaminasRequest;
use Tests\TestCase;
use function GuzzleHttp\Psr7\str;
class LoggedRequestTest extends TestCase
{
/** @test */
public function it_retrieves_the_request_id()
{
$rawRequest = str(new Request(200, '/expose', [
'X-Expose-Request-ID' => 'example-request'
]));
$parsedRequest = LaminasRequest::fromString($rawRequest);
$loggedRequest = new LoggedRequest($rawRequest, $parsedRequest);
$this->assertSame('example-request', $loggedRequest->id());
}
/** @test */
public function it_returns_the_raw_request()
{
$rawRequest = str(new Request(200, '/expose', [
'X-Expose-Request-ID' => 'example-request'
]));
$parsedRequest = LaminasRequest::fromString($rawRequest);
$loggedRequest = new LoggedRequest($rawRequest, $parsedRequest);
$this->assertSame($rawRequest, $loggedRequest->getRequestData());
}
/** @test */
public function it_returns_the_parsed_request()
{
$rawRequest = str(new Request(200, '/expose', [
'X-Expose-Request-ID' => 'example-request'
]));
$parsedRequest = LaminasRequest::fromString($rawRequest);
$loggedRequest = new LoggedRequest($rawRequest, $parsedRequest);
$this->assertSame($parsedRequest, $loggedRequest->getRequest());
}
}

View File

@@ -0,0 +1,122 @@
<?php
namespace Tests\Unit;
use App\Logger\CliRequestLogger;
use App\Logger\RequestLogger;
use Clue\React\Buzz\Browser;
use GuzzleHttp\Psr7\Request;
use GuzzleHttp\Psr7\Response;
use Laminas\Http\Request as LaminasRequest;
use Tests\TestCase;
use function GuzzleHttp\Psr7\str;
use Mockery as m;
class RequestLoggerTest extends TestCase
{
/** @test */
public function it_can_log_requests()
{
$browser = m::mock(Browser::class);
$browser->shouldReceive('post')
->once();
$cliLogger = m::mock(CliRequestLogger::class);
$cliLogger->shouldReceive('logRequest')->once();
$requestString = str(new Request(200, '/example'));
$parsedRequest = LaminasRequest::fromString($requestString);
$logger = new RequestLogger($browser, $cliLogger);
$logger->logRequest($requestString, $parsedRequest);
$this->assertCount(1, $logger->getData());
}
/** @test */
public function it_can_clear_the_requests()
{
$browser = m::mock(Browser::class);
$browser->shouldReceive('post')
->twice();
$cliLogger = m::mock(CliRequestLogger::class);
$cliLogger->shouldReceive('logRequest')->once();
$requestString = str(new Request(200, '/example'));
$parsedRequest = LaminasRequest::fromString($requestString);
$logger = new RequestLogger($browser, $cliLogger);
$logger->logRequest($requestString, $parsedRequest);
$logger->clear();
$this->assertCount(0, $logger->getData());
}
/** @test */
public function it_can_associate_a_response_with_a_request()
{
$browser = m::mock(Browser::class);
$browser->shouldReceive('post')
->twice();
$cliLogger = m::mock(CliRequestLogger::class);
$cliLogger->shouldReceive('logRequest')
->twice();
$requestString = str(new Request(200, '/example'));
$parsedRequest = LaminasRequest::fromString($requestString);
$logger = new RequestLogger($browser, $cliLogger);
$loggedRequest = $logger->logRequest($requestString, $parsedRequest);
$this->assertNull($logger->findLoggedRequest($loggedRequest->id())->getResponse());
$responseString = str(new Response(200, [], 'Hello World!'));
$logger->logResponse($parsedRequest, $responseString);
$this->assertNotNull($logger->findLoggedRequest($loggedRequest->id())->getResponse());
}
/** @test */
public function it_can_find_a_request_by_id()
{
$browser = m::mock(Browser::class);
$browser->shouldReceive('post')
->once();
$cliLogger = m::mock(CliRequestLogger::class);
$cliLogger->shouldReceive('logRequest')->once();
$requestString = str(new Request(200, '/example'));
$parsedRequest = LaminasRequest::fromString($requestString);
$logger = new RequestLogger($browser, $cliLogger);
$loggedRequest = $logger->logRequest($requestString, $parsedRequest);
$this->assertSame($loggedRequest, $logger->findLoggedRequest($loggedRequest->id()));
}
/** @test */
public function it_only_stores_a_limited_amount_of_requests()
{
$browser = m::mock(Browser::class);
$browser->shouldReceive('post');
$cliLogger = m::mock(CliRequestLogger::class);
$cliLogger->shouldReceive('logRequest');
$requestString = str(new Request(200, '/example'));
$parsedRequest = LaminasRequest::fromString($requestString);
$logger = new RequestLogger($browser, $cliLogger);
foreach (range(1, 20) as $i) {
$logger->logRequest($requestString, $parsedRequest);
}
$this->assertCount(RequestLogger::MAX_LOGGED_REQUESTS, $logger->getData());
}
}