mirror of
https://github.com/bitinflow/expose.git
synced 2026-03-13 13:35:54 +00:00
Merge branch 'master' of github.com:beyondcode/phunnel
This commit is contained in:
@@ -6,12 +6,11 @@ use App\Client\Connections\ControlConnection;
|
||||
use App\Logger\CliRequestLogger;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Str;
|
||||
use function Ratchet\Client\connect;
|
||||
use Ratchet\Client\WebSocket;
|
||||
use React\EventLoop\LoopInterface;
|
||||
use React\Promise\Deferred;
|
||||
use React\Promise\PromiseInterface;
|
||||
use function Ratchet\Client\connect;
|
||||
|
||||
class Client
|
||||
{
|
||||
@@ -26,7 +25,7 @@ class Client
|
||||
/** @var CliRequestLogger */
|
||||
protected $logger;
|
||||
|
||||
/** @var int */
|
||||
/** @var int */
|
||||
protected $connectionRetries = 0;
|
||||
|
||||
/** @var int */
|
||||
@@ -73,7 +72,7 @@ class Client
|
||||
$deferred = new Deferred();
|
||||
$promise = $deferred->promise();
|
||||
|
||||
$wsProtocol = $this->configuration->port() === 443 ? "wss" : "ws";
|
||||
$wsProtocol = $this->configuration->port() === 443 ? 'wss' : 'ws';
|
||||
|
||||
connect($wsProtocol."://{$this->configuration->host()}:{$this->configuration->port()}/expose/control?authToken={$authToken}", [], [
|
||||
'X-Expose-Control' => 'enabled',
|
||||
@@ -85,7 +84,7 @@ class Client
|
||||
|
||||
$connection->authenticate($sharedUrl, $subdomain);
|
||||
|
||||
$clientConnection->on('close', function() use ($deferred, $sharedUrl, $subdomain, $authToken) {
|
||||
$clientConnection->on('close', function () use ($deferred, $sharedUrl, $subdomain, $authToken) {
|
||||
$this->logger->error('Connection to server closed.');
|
||||
|
||||
$this->retryConnectionOrExit($sharedUrl, $subdomain, $authToken);
|
||||
@@ -106,7 +105,7 @@ class Client
|
||||
$connection->on('setMaximumConnectionLength', function ($data) {
|
||||
$timeoutSection = $this->logger->getOutput()->section();
|
||||
|
||||
$this->loop->addPeriodicTimer(1, function() use ($data, $timeoutSection) {
|
||||
$this->loop->addPeriodicTimer(1, function () use ($data, $timeoutSection) {
|
||||
$this->timeConnected++;
|
||||
|
||||
$carbon = Carbon::createFromFormat('s', str_pad($data->length * 60 - $this->timeConnected, 2, 0, STR_PAD_LEFT));
|
||||
@@ -117,7 +116,7 @@ class Client
|
||||
});
|
||||
|
||||
$connection->on('authenticated', function ($data) use ($deferred, $sharedUrl) {
|
||||
$httpProtocol = $this->configuration->port() === 443 ? "https" : "http";
|
||||
$httpProtocol = $this->configuration->port() === 443 ? 'https' : 'http';
|
||||
$host = $this->configuration->host();
|
||||
|
||||
if ($httpProtocol !== 'https') {
|
||||
@@ -134,13 +133,13 @@ class Client
|
||||
|
||||
$deferred->resolve($data);
|
||||
});
|
||||
|
||||
}, function (\Exception $e) use ($deferred, $sharedUrl, $subdomain, $authToken) {
|
||||
if ($this->connectionRetries > 0) {
|
||||
$this->retryConnectionOrExit($sharedUrl, $subdomain, $authToken);
|
||||
|
||||
return;
|
||||
}
|
||||
$this->logger->error("Could not connect to the server.");
|
||||
$this->logger->error('Could not connect to the server.');
|
||||
$this->logger->error($e->getMessage());
|
||||
|
||||
$this->exit($deferred);
|
||||
@@ -153,7 +152,7 @@ class Client
|
||||
{
|
||||
$deferred->reject();
|
||||
|
||||
$this->loop->futureTick(function(){
|
||||
$this->loop->futureTick(function () {
|
||||
exit(1);
|
||||
});
|
||||
}
|
||||
@@ -163,8 +162,8 @@ class Client
|
||||
$this->connectionRetries++;
|
||||
|
||||
if ($this->connectionRetries <= static::MAX_CONNECTION_RETRIES) {
|
||||
$this->loop->addTimer($this->connectionRetries, function() use ($sharedUrl, $subdomain, $authToken) {
|
||||
$this->logger->info("Retrying connection ({$this->connectionRetries}/".static::MAX_CONNECTION_RETRIES.")");
|
||||
$this->loop->addTimer($this->connectionRetries, function () use ($sharedUrl, $subdomain, $authToken) {
|
||||
$this->logger->info("Retrying connection ({$this->connectionRetries}/".static::MAX_CONNECTION_RETRIES.')');
|
||||
|
||||
$this->connectToServer($sharedUrl, $subdomain, $authToken);
|
||||
});
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
namespace App\Client\Connections;
|
||||
|
||||
use App\Client\ProxyManager;
|
||||
use Evenement\EventEmitterTrait;
|
||||
use Ratchet\Client\WebSocket;
|
||||
use Ratchet\ConnectionInterface;
|
||||
use Evenement\EventEmitterTrait;
|
||||
use Ratchet\RFC6455\Messaging\Message;
|
||||
|
||||
class ControlConnection
|
||||
|
||||
@@ -2,19 +2,19 @@
|
||||
|
||||
namespace App\Client;
|
||||
|
||||
use App\Client\Http\Controllers\AttachDataToLogController;
|
||||
use App\Client\Http\Controllers\ClearLogsController;
|
||||
use App\Client\Http\Controllers\CreateTunnelController;
|
||||
use App\Client\Http\Controllers\PushLogsToDashboardController;
|
||||
use App\Http\App;
|
||||
use App\Client\Http\Controllers\AttachDataToLogController;
|
||||
use App\Client\Http\Controllers\DashboardController;
|
||||
use App\Client\Http\Controllers\LogController;
|
||||
use App\Client\Http\Controllers\PushLogsToDashboardController;
|
||||
use App\Client\Http\Controllers\ReplayLogController;
|
||||
use App\Http\App;
|
||||
use App\Http\RouteGenerator;
|
||||
use App\WebSockets\Socket;
|
||||
use Ratchet\WebSocket\WsServer;
|
||||
use React\EventLoop\LoopInterface;
|
||||
use React\EventLoop\Factory as LoopFactory;
|
||||
use React\EventLoop\LoopInterface;
|
||||
|
||||
class Factory
|
||||
{
|
||||
@@ -158,5 +158,4 @@ class Factory
|
||||
{
|
||||
$this->loop->run();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
namespace App\Client\Http\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use GuzzleHttp\Psr7\Response;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Logger\RequestLogger;
|
||||
use Ratchet\ConnectionInterface;
|
||||
use GuzzleHttp\Psr7\Response;
|
||||
use function GuzzleHttp\Psr7\str;
|
||||
use Illuminate\Http\Request;
|
||||
use Ratchet\ConnectionInterface;
|
||||
|
||||
class AttachDataToLogController extends Controller
|
||||
{
|
||||
@@ -24,11 +24,12 @@ class AttachDataToLogController extends Controller
|
||||
$loggedRequest = $this->requestLogger->findLoggedRequest($request->get('request_id', ''));
|
||||
|
||||
if (! is_null($loggedRequest)) {
|
||||
$loggedRequest->setAdditionalData((array)$request->get('data', []));
|
||||
$loggedRequest->setAdditionalData((array) $request->get('data', []));
|
||||
|
||||
$this->requestLogger->pushLoggedRequest($loggedRequest);
|
||||
|
||||
$httpConnection->send(str(new Response(200)));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,18 +3,13 @@
|
||||
namespace App\Client\Http\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Exception;
|
||||
use App\WebSockets\Socket;
|
||||
use GuzzleHttp\Psr7\Response;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Collection;
|
||||
use Ratchet\ConnectionInterface;
|
||||
use function GuzzleHttp\Psr7\str;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use Illuminate\Http\Request;
|
||||
use Ratchet\ConnectionInterface;
|
||||
|
||||
class CreateTunnelController extends Controller
|
||||
{
|
||||
|
||||
protected $keepConnectionOpen = true;
|
||||
|
||||
public function handle(Request $request, ConnectionInterface $httpConnection)
|
||||
@@ -24,10 +19,9 @@ class CreateTunnelController extends Controller
|
||||
->then(function ($data) use ($httpConnection) {
|
||||
$httpConnection->send(respond_json($data));
|
||||
$httpConnection->close();
|
||||
}, function() use ($httpConnection) {
|
||||
}, function () use ($httpConnection) {
|
||||
$httpConnection->send(str(new Response(500)));
|
||||
$httpConnection->close();
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,15 +4,11 @@ namespace App\Client\Http\Controllers;
|
||||
|
||||
use App\Client\Client;
|
||||
use App\Http\Controllers\Controller;
|
||||
use GuzzleHttp\Psr7\Response;
|
||||
use Illuminate\Http\Request;
|
||||
use function GuzzleHttp\Psr7\str;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use Ratchet\ConnectionInterface;
|
||||
|
||||
class DashboardController extends Controller
|
||||
{
|
||||
|
||||
public function handle(Request $request, ConnectionInterface $httpConnection)
|
||||
{
|
||||
$httpConnection->send(respond_html($this->getView($httpConnection, 'client.dashboard', [
|
||||
|
||||
@@ -4,11 +4,8 @@ namespace App\Client\Http\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Logger\RequestLogger;
|
||||
use GuzzleHttp\Psr7\Response;
|
||||
use Illuminate\Http\Request;
|
||||
use Ratchet\ConnectionInterface;
|
||||
use function GuzzleHttp\Psr7\str;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
|
||||
class LogController extends Controller
|
||||
{
|
||||
|
||||
@@ -3,18 +3,15 @@
|
||||
namespace App\Client\Http\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Exception;
|
||||
use App\WebSockets\Socket;
|
||||
use Exception;
|
||||
use GuzzleHttp\Psr7\Response;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Collection;
|
||||
use Ratchet\ConnectionInterface;
|
||||
use function GuzzleHttp\Psr7\str;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use Illuminate\Http\Request;
|
||||
use Ratchet\ConnectionInterface;
|
||||
|
||||
class PushLogsToDashboardController extends Controller
|
||||
{
|
||||
|
||||
public function handle(Request $request, ConnectionInterface $httpConnection)
|
||||
{
|
||||
try {
|
||||
|
||||
@@ -4,13 +4,11 @@ namespace App\Client\Http\Controllers;
|
||||
|
||||
use App\Client\Http\HttpClient;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\QueryParameters;
|
||||
use App\Logger\RequestLogger;
|
||||
use GuzzleHttp\Psr7\Response;
|
||||
use function GuzzleHttp\Psr7\str;
|
||||
use Illuminate\Http\Request;
|
||||
use Ratchet\ConnectionInterface;
|
||||
use function GuzzleHttp\Psr7\str;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
|
||||
class ReplayLogController extends Controller
|
||||
{
|
||||
@@ -32,6 +30,7 @@ class ReplayLogController extends Controller
|
||||
|
||||
if (is_null($loggedRequest)) {
|
||||
$httpConnection->send(str(new Response(404)));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@ namespace App\Client\Http;
|
||||
use App\Client\Http\Modifiers\CheckBasicAuthentication;
|
||||
use App\Logger\RequestLogger;
|
||||
use Clue\React\Buzz\Browser;
|
||||
use Illuminate\Pipeline\Pipeline;
|
||||
use Illuminate\Support\Arr;
|
||||
use function GuzzleHttp\Psr7\parse_request;
|
||||
use function GuzzleHttp\Psr7\str;
|
||||
use Laminas\Http\Request;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
@@ -14,8 +14,6 @@ use Ratchet\Client\WebSocket;
|
||||
use Ratchet\RFC6455\Messaging\Frame;
|
||||
use React\EventLoop\LoopInterface;
|
||||
use React\Socket\Connector;
|
||||
use function GuzzleHttp\Psr7\parse_request;
|
||||
use function GuzzleHttp\Psr7\str;
|
||||
|
||||
class HttpClient
|
||||
{
|
||||
@@ -67,13 +65,13 @@ class HttpClient
|
||||
|
||||
protected function createConnector(): Connector
|
||||
{
|
||||
return new Connector($this->loop, array(
|
||||
return new Connector($this->loop, [
|
||||
'dns' => '127.0.0.1',
|
||||
'tls' => array(
|
||||
'tls' => [
|
||||
'verify_peer' => false,
|
||||
'verify_peer_name' => false
|
||||
)
|
||||
));
|
||||
'verify_peer_name' => false,
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
protected function sendRequestToApplication(RequestInterface $request, $proxyConnection = null)
|
||||
|
||||
@@ -4,10 +4,10 @@ namespace App\Client\Http\Modifiers;
|
||||
|
||||
use App\Client\Configuration;
|
||||
use GuzzleHttp\Psr7\Response;
|
||||
use function GuzzleHttp\Psr7\str;
|
||||
use Illuminate\Support\Arr;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use Ratchet\Client\WebSocket;
|
||||
use function GuzzleHttp\Psr7\str;
|
||||
|
||||
class CheckBasicAuthentication
|
||||
{
|
||||
@@ -30,10 +30,11 @@ class CheckBasicAuthentication
|
||||
if (is_null($username)) {
|
||||
$proxyConnection->send(
|
||||
str(new Response(401, [
|
||||
'WWW-Authenticate' => 'Basic realm=Expose'
|
||||
'WWW-Authenticate' => 'Basic realm=Expose',
|
||||
], 'Unauthorized'))
|
||||
);
|
||||
$proxyConnection->close();
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -49,7 +50,7 @@ class CheckBasicAuthentication
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!array_key_exists($authorization['username'], $credentials)) {
|
||||
if (! array_key_exists($authorization['username'], $credentials)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -63,13 +64,13 @@ class CheckBasicAuthentication
|
||||
protected function parseAuthorizationHeader(string $header)
|
||||
{
|
||||
if (strpos($header, 'Basic') !== 0) {
|
||||
return null;
|
||||
return;
|
||||
}
|
||||
|
||||
$header = base64_decode(substr($header, 6));
|
||||
|
||||
if ($header === false) {
|
||||
return null;
|
||||
return;
|
||||
}
|
||||
|
||||
$header = explode(':', $header, 2);
|
||||
@@ -82,13 +83,14 @@ class CheckBasicAuthentication
|
||||
|
||||
protected function requiresAuthentication(): bool
|
||||
{
|
||||
return !empty($this->getCredentials());
|
||||
return ! empty($this->getCredentials());
|
||||
}
|
||||
|
||||
protected function getCredentials()
|
||||
{
|
||||
try {
|
||||
$credentials = explode(':', $this->configuration->auth());
|
||||
|
||||
return [
|
||||
$credentials[0] => $credentials[1],
|
||||
];
|
||||
|
||||
@@ -3,10 +3,9 @@
|
||||
namespace App\Client;
|
||||
|
||||
use App\Client\Http\HttpClient;
|
||||
use Ratchet\Client\WebSocket;
|
||||
use Ratchet\ConnectionInterface;
|
||||
use React\EventLoop\LoopInterface;
|
||||
use function Ratchet\Client\connect;
|
||||
use Ratchet\Client\WebSocket;
|
||||
use React\EventLoop\LoopInterface;
|
||||
|
||||
class ProxyManager
|
||||
{
|
||||
@@ -24,14 +23,14 @@ class ProxyManager
|
||||
|
||||
public function createProxy(string $clientId, $connectionData)
|
||||
{
|
||||
$protocol = $this->configuration->port() === 443 ? "wss" : "ws";
|
||||
$protocol = $this->configuration->port() === 443 ? 'wss' : 'ws';
|
||||
|
||||
connect($protocol."://{$this->configuration->host()}:{$this->configuration->port()}/expose/control", [], [
|
||||
'X-Expose-Control' => 'enabled',
|
||||
], $this->loop)
|
||||
->then(function (WebSocket $proxyConnection) use ($clientId, $connectionData) {
|
||||
$proxyConnection->on('message', function ($message) use ($proxyConnection, $connectionData) {
|
||||
$this->performRequest($proxyConnection, $connectionData->request_id, (string)$message);
|
||||
$this->performRequest($proxyConnection, $connectionData->request_id, (string) $message);
|
||||
});
|
||||
|
||||
$proxyConnection->send(json_encode([
|
||||
@@ -46,6 +45,6 @@ class ProxyManager
|
||||
|
||||
protected function performRequest(WebSocket $proxyConnection, $requestId, string $requestData)
|
||||
{
|
||||
app(HttpClient::class)->performRequest((string)$requestData, $proxyConnection, $requestId);
|
||||
app(HttpClient::class)->performRequest((string) $requestData, $proxyConnection, $requestId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,5 @@ class TokenNodeVisitor extends NodeVisitorAbstract
|
||||
|
||||
return $node;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,17 +15,18 @@ class PublishCommand extends Command
|
||||
$configFile = implode(DIRECTORY_SEPARATOR, [
|
||||
$_SERVER['HOME'],
|
||||
'.expose',
|
||||
'config.php'
|
||||
'config.php',
|
||||
]);
|
||||
|
||||
if (! $this->option('force') && file_exists($configFile)) {
|
||||
$this->error('Expose configuration file already exists at '.$configFile);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@mkdir(dirname($configFile), 0755, true);
|
||||
file_put_contents($configFile, file_get_contents(base_path('config/expose.php')));
|
||||
|
||||
$this->info('Published expose configuration file to: ' . $configFile);
|
||||
$this->info('Published expose configuration file to: '.$configFile);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ class ServeCommand extends Command
|
||||
$loop = app(LoopInterface::class);
|
||||
|
||||
$loop->futureTick(function () {
|
||||
$this->info("Expose server running on port ".$this->option('port').".");
|
||||
$this->info('Expose server running on port '.$this->option('port').'.');
|
||||
});
|
||||
|
||||
$validateAuthTokens = config('expose.admin.validate_auth_tokens');
|
||||
|
||||
@@ -4,7 +4,6 @@ namespace App\Commands;
|
||||
|
||||
use App\Client\Factory;
|
||||
use App\Logger\CliRequestLogger;
|
||||
use Illuminate\Console\Scheduling\Schedule;
|
||||
use LaravelZero\Framework\Commands\Command;
|
||||
use React\EventLoop\LoopInterface;
|
||||
use Symfony\Component\Console\Output\ConsoleOutput;
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
namespace App\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
class ShareCurrentWorkingDirectoryCommand extends ShareCommand
|
||||
{
|
||||
protected $signature = 'share-cwd {host?} {--subdomain=} {--auth=}';
|
||||
@@ -21,10 +19,11 @@ class ShareCurrentWorkingDirectoryCommand extends ShareCommand
|
||||
|
||||
protected function detectTld(): string
|
||||
{
|
||||
$valetConfigFile = $_SERVER['HOME'] . DIRECTORY_SEPARATOR . '.config' . DIRECTORY_SEPARATOR . 'valet' . DIRECTORY_SEPARATOR . 'config.json';
|
||||
$valetConfigFile = $_SERVER['HOME'].DIRECTORY_SEPARATOR.'.config'.DIRECTORY_SEPARATOR.'valet'.DIRECTORY_SEPARATOR.'config.json';
|
||||
|
||||
if (file_exists($valetConfigFile)) {
|
||||
$valetConfig = json_decode(file_get_contents($valetConfigFile));
|
||||
|
||||
return $valetConfig->tld;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ use PhpParser\Lexer\Emulative;
|
||||
use PhpParser\NodeTraverser;
|
||||
use PhpParser\NodeVisitor\CloningVisitor;
|
||||
use PhpParser\Parser\Php7;
|
||||
use PhpParser\ParserFactory;
|
||||
use PhpParser\PrettyPrinter\Standard;
|
||||
|
||||
class StoreAuthenticationTokenCommand extends Command
|
||||
@@ -21,13 +20,13 @@ class StoreAuthenticationTokenCommand extends Command
|
||||
{
|
||||
$config = config('expose', []);
|
||||
|
||||
if (!is_null($this->argument('token'))) {
|
||||
$this->info('Setting the expose authentication token to "' . $this->argument('token') . '"');
|
||||
if (! is_null($this->argument('token'))) {
|
||||
$this->info('Setting the expose authentication token to "'.$this->argument('token').'"');
|
||||
|
||||
$configFile = implode(DIRECTORY_SEPARATOR, [
|
||||
$_SERVER['HOME'],
|
||||
'.expose',
|
||||
'config.php'
|
||||
'config.php',
|
||||
]);
|
||||
|
||||
if (! file_exists($configFile)) {
|
||||
@@ -38,13 +37,14 @@ class StoreAuthenticationTokenCommand extends Command
|
||||
}
|
||||
|
||||
file_put_contents($configFile, $updatedConfigFile);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_null($token = config('expose.auth_token'))) {
|
||||
$this->info('There is no authentication token specified.');
|
||||
} else {
|
||||
$this->info('Current authentication token: ' . $token);
|
||||
$this->info('Current authentication token: '.$token);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
|
||||
namespace App\Http\Controllers\Concerns;
|
||||
|
||||
use function GuzzleHttp\Psr7\stream_for;
|
||||
use Ratchet\ConnectionInterface;
|
||||
use Twig\Environment;
|
||||
use Twig\Loader\ArrayLoader;
|
||||
use function GuzzleHttp\Psr7\stream_for;
|
||||
|
||||
trait LoadsViews
|
||||
{
|
||||
|
||||
@@ -14,8 +14,8 @@ trait ParsesIncomingRequest
|
||||
protected function findContentLength(array $headers): int
|
||||
{
|
||||
return Collection::make($headers)->first(function ($values, $header) {
|
||||
return strtolower($header) === 'content-length';
|
||||
})[0] ?? 0;
|
||||
return strtolower($header) === 'content-length';
|
||||
})[0] ?? 0;
|
||||
}
|
||||
|
||||
protected function shouldHandleRequest(Request $request, ConnectionInterface $httpConnection): bool
|
||||
@@ -32,7 +32,7 @@ trait ParsesIncomingRequest
|
||||
$this->handle($connection->laravelRequest, $connection);
|
||||
}
|
||||
|
||||
if (!$this->keepConnectionOpen) {
|
||||
if (! $this->keepConnectionOpen) {
|
||||
$connection->close();
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ trait ParsesIncomingRequest
|
||||
$connection->requestBuffer,
|
||||
$connection->request->getProtocolVersion(),
|
||||
[
|
||||
'REMOTE_ADDR' => $connection->remoteAddress
|
||||
'REMOTE_ADDR' => $connection->remoteAddress,
|
||||
]
|
||||
))
|
||||
->withQueryParams(QueryParameters::create($connection->request)->all())
|
||||
|
||||
@@ -4,12 +4,11 @@ namespace App\Http\Controllers;
|
||||
|
||||
use App\Http\Controllers\Concerns\LoadsViews;
|
||||
use App\Http\Controllers\Concerns\ParsesIncomingRequest;
|
||||
use function GuzzleHttp\Psr7\parse_request;
|
||||
use Illuminate\Http\Request;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use Ratchet\ConnectionInterface;
|
||||
use Ratchet\Http\HttpServerInterface;
|
||||
use React\Promise\PromiseInterface;
|
||||
use function GuzzleHttp\Psr7\parse_request;
|
||||
|
||||
abstract class Controller implements HttpServerInterface
|
||||
{
|
||||
@@ -51,7 +50,7 @@ abstract class Controller implements HttpServerInterface
|
||||
$this->checkContentLength($from);
|
||||
}
|
||||
|
||||
function onError(ConnectionInterface $conn, \Exception $e)
|
||||
public function onError(ConnectionInterface $conn, \Exception $e)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
@@ -2,9 +2,6 @@
|
||||
|
||||
namespace App\Http;
|
||||
|
||||
use Ratchet\WebSocket\MessageComponentInterface;
|
||||
use Ratchet\WebSocket\WsServer;
|
||||
use React\EventLoop\LoopInterface;
|
||||
use Symfony\Component\Routing\Route;
|
||||
use Symfony\Component\Routing\RouteCollection;
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace App\Logger;
|
||||
|
||||
use Illuminate\Console\OutputStyle;
|
||||
use Illuminate\Support\Collection;
|
||||
use Symfony\Component\Console\Helper\Table;
|
||||
use Symfony\Component\Console\Output\ConsoleOutputInterface;
|
||||
@@ -53,8 +52,8 @@ class CliRequestLogger extends Logger
|
||||
return [
|
||||
$loggedRequest->getRequest()->getMethod(),
|
||||
$loggedRequest->getRequest()->getUri(),
|
||||
optional($loggedRequest->getResponse())->getStatusCode() . ' ' . optional($loggedRequest->getResponse())->getReasonPhrase(),
|
||||
$loggedRequest->getDuration().'ms'
|
||||
optional($loggedRequest->getResponse())->getStatusCode().' '.optional($loggedRequest->getResponse())->getReasonPhrase(),
|
||||
$loggedRequest->getDuration().'ms',
|
||||
];
|
||||
})->toArray());
|
||||
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
namespace App\Logger;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use function GuzzleHttp\Psr7\parse_request;
|
||||
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
|
||||
{
|
||||
@@ -49,7 +49,7 @@ class LoggedRequest implements \JsonSerializable
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function jsonSerialize()
|
||||
{
|
||||
@@ -133,7 +133,6 @@ class LoggedRequest implements \JsonSerializable
|
||||
'*javascript*',
|
||||
];
|
||||
|
||||
|
||||
return Str::is($patterns, $contentType);
|
||||
}
|
||||
|
||||
@@ -157,7 +156,7 @@ class LoggedRequest implements \JsonSerializable
|
||||
|
||||
return Str::is(config()->get('expose.skip_body_log.content_type'), $contentType);
|
||||
}
|
||||
|
||||
|
||||
protected function skipByExtension(): bool
|
||||
{
|
||||
if (empty(config()->get('expose.skip_body_log.extension'))) {
|
||||
@@ -185,7 +184,7 @@ class LoggedRequest implements \JsonSerializable
|
||||
{
|
||||
$units = ['B', 'KB', 'MB', 'GB'];
|
||||
$number = substr($size, 0, -2);
|
||||
$suffix = strtoupper(substr($size,-2));
|
||||
$suffix = strtoupper(substr($size, -2));
|
||||
|
||||
// B or no suffix
|
||||
if (is_numeric(substr($suffix, 0, 1))) {
|
||||
@@ -294,7 +293,7 @@ class LoggedRequest implements \JsonSerializable
|
||||
return collect($this->parsedRequest->getHeaders()->toArray())
|
||||
->mapWithKeys(function ($value, $key) {
|
||||
return [strtolower($key) => $value];
|
||||
})->get('x-expose-request-id', (string)Str::uuid());
|
||||
})->get('x-expose-request-id', (string) Str::uuid());
|
||||
}
|
||||
|
||||
public function getDuration()
|
||||
|
||||
@@ -3,10 +3,7 @@
|
||||
namespace App\Logger;
|
||||
|
||||
use Illuminate\Console\Concerns\InteractsWithIO;
|
||||
use Illuminate\Console\OutputStyle;
|
||||
use Symfony\Component\Console\Formatter\OutputFormatterStyle;
|
||||
use Symfony\Component\Console\Output\ConsoleOutputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
class Logger
|
||||
{
|
||||
|
||||
@@ -2,12 +2,9 @@
|
||||
|
||||
namespace App\Logger;
|
||||
|
||||
use App\WebSockets\Socket;
|
||||
use Clue\React\Buzz\Browser;
|
||||
use GuzzleHttp\RequestOptions;
|
||||
use Laminas\Http\Request;
|
||||
use Laminas\Http\Response;
|
||||
use function GuzzleHttp\Psr7\stream_for;
|
||||
|
||||
class RequestLogger
|
||||
{
|
||||
@@ -80,5 +77,4 @@ class RequestLogger
|
||||
json_encode($request, JSON_INVALID_UTF8_IGNORE)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -35,19 +35,19 @@ class AppServiceProvider extends ServiceProvider
|
||||
{
|
||||
$builtInConfig = config('expose');
|
||||
|
||||
$localConfigFile = getcwd() . DIRECTORY_SEPARATOR . '.expose.php';
|
||||
$localConfigFile = getcwd().DIRECTORY_SEPARATOR.'.expose.php';
|
||||
|
||||
if (file_exists($localConfigFile)) {
|
||||
$localConfig = require $localConfigFile;
|
||||
config()->set('expose', array_merge($builtInConfig, $localConfig));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$configFile = implode(DIRECTORY_SEPARATOR, [
|
||||
$_SERVER['HOME'] ?? __DIR__,
|
||||
'.expose',
|
||||
'config.php'
|
||||
'config.php',
|
||||
]);
|
||||
|
||||
if (file_exists($configFile)) {
|
||||
|
||||
@@ -38,7 +38,7 @@ class Configuration implements \JsonSerializable
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function jsonSerialize()
|
||||
{
|
||||
|
||||
@@ -35,14 +35,14 @@ class ConnectionManager implements ConnectionManagerContract
|
||||
|
||||
$connection->setMaximumConnectionLength($maximumConnectionLength);
|
||||
|
||||
$this->loop->addTimer($maximumConnectionLength * 60, function() use ($connection) {
|
||||
$this->loop->addTimer($maximumConnectionLength * 60, function () use ($connection) {
|
||||
$connection->socket->close();
|
||||
});
|
||||
}
|
||||
|
||||
public function storeConnection(string $host, ?string $subdomain, ConnectionInterface $connection): ControlConnection
|
||||
{
|
||||
$clientId = (string)uniqid();
|
||||
$clientId = (string) uniqid();
|
||||
|
||||
$connection->client_id = $clientId;
|
||||
|
||||
|
||||
@@ -3,16 +3,7 @@
|
||||
namespace App\Server\Connections;
|
||||
|
||||
use Evenement\EventEmitterTrait;
|
||||
use GuzzleHttp\Psr7\Request;
|
||||
use Illuminate\Contracts\Support\Arrayable;
|
||||
use Illuminate\Support\Str;
|
||||
use Nyholm\Psr7\Factory\Psr17Factory;
|
||||
use Ratchet\Client\WebSocket;
|
||||
use Ratchet\ConnectionInterface;
|
||||
use Ratchet\RFC6455\Messaging\Frame;
|
||||
use Ratchet\WebSocket\WsConnection;
|
||||
use React\Stream\Util;
|
||||
use Symfony\Bridge\PsrHttpMessage\Factory\PsrHttpFactory;
|
||||
|
||||
class ControlConnection
|
||||
{
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace App\Server;
|
||||
use App\Contracts\ConnectionManager as ConnectionManagerContract;
|
||||
use App\Contracts\SubdomainGenerator;
|
||||
use App\Contracts\UserRepository;
|
||||
use App\Http\RouteGenerator;
|
||||
use App\Http\Server as HttpServer;
|
||||
use App\Server\Connections\ConnectionManager;
|
||||
use App\Server\Http\Controllers\Admin\DeleteUsersController;
|
||||
@@ -15,28 +16,24 @@ use App\Server\Http\Controllers\Admin\GetUsersController;
|
||||
use App\Server\Http\Controllers\Admin\ListSitesController;
|
||||
use App\Server\Http\Controllers\Admin\ListUsersController;
|
||||
use App\Server\Http\Controllers\Admin\RedirectToUsersController;
|
||||
use App\Server\Http\Controllers\Admin\StoreSettingsController;
|
||||
use App\Server\Http\Controllers\Admin\ShowSettingsController;
|
||||
use App\Server\Http\Controllers\Admin\StoreSettingsController;
|
||||
use App\Server\Http\Controllers\Admin\StoreUsersController;
|
||||
use App\Server\Http\Controllers\ControlMessageController;
|
||||
use App\Server\Http\Controllers\TunnelMessageController;
|
||||
use App\Http\RouteGenerator;
|
||||
use App\Server\Http\Router;
|
||||
use App\Server\SubdomainGenerator\RandomSubdomainGenerator;
|
||||
use Clue\React\SQLite\DatabaseInterface;
|
||||
use Phar;
|
||||
use Ratchet\Server\IoServer;
|
||||
use Ratchet\WebSocket\WsServer;
|
||||
use React\Socket\Server;
|
||||
use React\EventLoop\LoopInterface;
|
||||
use React\EventLoop\Factory as LoopFactory;
|
||||
use React\EventLoop\LoopInterface;
|
||||
use React\Socket\Server;
|
||||
use Symfony\Component\Finder\Finder;
|
||||
use Symfony\Component\Finder\SplFileInfo;
|
||||
use Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeFileSessionHandler;
|
||||
use Symfony\Component\Routing\Matcher\UrlMatcher;
|
||||
use Symfony\Component\Routing\RequestContext;
|
||||
use Symfony\Component\Routing\Route;
|
||||
use Symfony\Component\Routing\RouteCollection;
|
||||
|
||||
class Factory
|
||||
{
|
||||
@@ -98,7 +95,7 @@ class Factory
|
||||
new Route('/{__catchall__}', [
|
||||
'_controller' => app(TunnelMessageController::class),
|
||||
], [
|
||||
'__catchall__' => '.*'
|
||||
'__catchall__' => '.*',
|
||||
]));
|
||||
}
|
||||
|
||||
@@ -195,7 +192,7 @@ class Factory
|
||||
|
||||
protected function bindUserRepository()
|
||||
{
|
||||
app()->singleton(UserRepository::class, function() {
|
||||
app()->singleton(UserRepository::class, function () {
|
||||
return app(config('expose.admin.user_repository'));
|
||||
});
|
||||
|
||||
@@ -204,10 +201,10 @@ class Factory
|
||||
|
||||
protected function bindDatabase()
|
||||
{
|
||||
app()->singleton(DatabaseInterface::class, function() {
|
||||
app()->singleton(DatabaseInterface::class, function () {
|
||||
$factory = new \Clue\React\SQLite\Factory($this->loop);
|
||||
|
||||
$options = ['worker_command' => Phar::running(false) ? Phar::running(false) . ' --sqlite-worker' : null];
|
||||
$options = ['worker_command' => Phar::running(false) ? Phar::running(false).' --sqlite-worker' : null];
|
||||
|
||||
return $factory->openLazy(
|
||||
config('expose.admin.database', ':memory:'),
|
||||
@@ -244,5 +241,4 @@ class Factory
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -4,10 +4,10 @@ namespace App\Server\Http\Controllers\Admin;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use GuzzleHttp\Psr7\Response;
|
||||
use function GuzzleHttp\Psr7\str;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Str;
|
||||
use Ratchet\ConnectionInterface;
|
||||
use function GuzzleHttp\Psr7\str;
|
||||
|
||||
abstract class AdminController extends Controller
|
||||
{
|
||||
@@ -16,17 +16,19 @@ abstract class AdminController extends Controller
|
||||
try {
|
||||
$authorization = Str::after($request->header('Authorization'), 'Basic ');
|
||||
$authParts = explode(':', base64_decode($authorization), 2);
|
||||
list($user, $password) = $authParts;
|
||||
[$user, $password] = $authParts;
|
||||
|
||||
if (! $this->credentialsAreAllowed($user, $password)) {
|
||||
throw new \InvalidArgumentException('Invalid Login');
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (\Throwable $e) {
|
||||
$httpConnection->send(str(new Response(401, [
|
||||
'WWW-Authenticate' => 'Basic realm="Expose"'
|
||||
'WWW-Authenticate' => 'Basic realm="Expose"',
|
||||
])));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,16 +3,8 @@
|
||||
namespace App\Server\Http\Controllers\Admin;
|
||||
|
||||
use App\Contracts\UserRepository;
|
||||
use App\Http\Controllers\Controller;
|
||||
use GuzzleHttp\Psr7\Response;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Support\Str;
|
||||
use Ratchet\ConnectionInterface;
|
||||
use Twig\Environment;
|
||||
use Twig\Loader\ArrayLoader;
|
||||
use function GuzzleHttp\Psr7\str;
|
||||
use function GuzzleHttp\Psr7\stream_for;
|
||||
|
||||
class DeleteUsersController extends AdminController
|
||||
{
|
||||
@@ -29,7 +21,7 @@ class DeleteUsersController extends AdminController
|
||||
public function handle(Request $request, ConnectionInterface $httpConnection)
|
||||
{
|
||||
$this->userRepository->deleteUser($request->get('id'))
|
||||
->then(function() use ($httpConnection) {
|
||||
->then(function () use ($httpConnection) {
|
||||
$httpConnection->send(respond_json(['deleted' => true], 200));
|
||||
$httpConnection->close();
|
||||
});
|
||||
|
||||
@@ -3,15 +3,9 @@
|
||||
namespace App\Server\Http\Controllers\Admin;
|
||||
|
||||
use App\Contracts\ConnectionManager;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Server\Configuration;
|
||||
use GuzzleHttp\Psr7\Response;
|
||||
use Illuminate\Http\Request;
|
||||
use Ratchet\ConnectionInterface;
|
||||
use Twig\Environment;
|
||||
use Twig\Loader\ArrayLoader;
|
||||
use function GuzzleHttp\Psr7\str;
|
||||
use function GuzzleHttp\Psr7\stream_for;
|
||||
|
||||
class DisconnectSiteController extends AdminController
|
||||
{
|
||||
@@ -37,7 +31,7 @@ class DisconnectSiteController extends AdminController
|
||||
}
|
||||
|
||||
$httpConnection->send(respond_json([
|
||||
'sites' => $this->connectionManager->getConnections()
|
||||
'sites' => $this->connectionManager->getConnections(),
|
||||
]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,10 +6,6 @@ use App\Contracts\ConnectionManager;
|
||||
use App\Server\Configuration;
|
||||
use Illuminate\Http\Request;
|
||||
use Ratchet\ConnectionInterface;
|
||||
use Twig\Environment;
|
||||
use Twig\Loader\ArrayLoader;
|
||||
use function GuzzleHttp\Psr7\str;
|
||||
use function GuzzleHttp\Psr7\stream_for;
|
||||
|
||||
class GetSettingsController extends AdminController
|
||||
{
|
||||
|
||||
@@ -3,14 +3,9 @@
|
||||
namespace App\Server\Http\Controllers\Admin;
|
||||
|
||||
use App\Contracts\ConnectionManager;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Server\Configuration;
|
||||
use Illuminate\Http\Request;
|
||||
use Ratchet\ConnectionInterface;
|
||||
use Twig\Environment;
|
||||
use Twig\Loader\ArrayLoader;
|
||||
use function GuzzleHttp\Psr7\str;
|
||||
use function GuzzleHttp\Psr7\stream_for;
|
||||
|
||||
class GetSitesController extends AdminController
|
||||
{
|
||||
@@ -33,7 +28,7 @@ class GetSitesController extends AdminController
|
||||
$site['id'] = $siteId;
|
||||
|
||||
return $site;
|
||||
})->values()
|
||||
})->values(),
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3,15 +3,8 @@
|
||||
namespace App\Server\Http\Controllers\Admin;
|
||||
|
||||
use App\Contracts\UserRepository;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Clue\React\SQLite\Result;
|
||||
use GuzzleHttp\Psr7\Response;
|
||||
use Illuminate\Http\Request;
|
||||
use Ratchet\ConnectionInterface;
|
||||
use Twig\Environment;
|
||||
use Twig\Loader\ArrayLoader;
|
||||
use function GuzzleHttp\Psr7\str;
|
||||
use function GuzzleHttp\Psr7\stream_for;
|
||||
|
||||
class GetUsersController extends AdminController
|
||||
{
|
||||
|
||||
@@ -3,14 +3,9 @@
|
||||
namespace App\Server\Http\Controllers\Admin;
|
||||
|
||||
use App\Contracts\ConnectionManager;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Server\Configuration;
|
||||
use Illuminate\Http\Request;
|
||||
use Ratchet\ConnectionInterface;
|
||||
use Twig\Environment;
|
||||
use Twig\Loader\ArrayLoader;
|
||||
use function GuzzleHttp\Psr7\str;
|
||||
use function GuzzleHttp\Psr7\stream_for;
|
||||
|
||||
class ListSitesController extends AdminController
|
||||
{
|
||||
@@ -30,7 +25,7 @@ class ListSitesController extends AdminController
|
||||
$sites = $this->getView($httpConnection, 'server.sites.index', [
|
||||
'scheme' => $this->configuration->port() === 443 ? 'https' : 'http',
|
||||
'configuration' => $this->configuration,
|
||||
'sites' => $this->connectionManager->getConnections()
|
||||
'sites' => $this->connectionManager->getConnections(),
|
||||
]);
|
||||
|
||||
$httpConnection->send(
|
||||
|
||||
@@ -3,15 +3,8 @@
|
||||
namespace App\Server\Http\Controllers\Admin;
|
||||
|
||||
use App\Contracts\UserRepository;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Clue\React\SQLite\Result;
|
||||
use GuzzleHttp\Psr7\Response;
|
||||
use Illuminate\Http\Request;
|
||||
use Ratchet\ConnectionInterface;
|
||||
use Twig\Environment;
|
||||
use Twig\Loader\ArrayLoader;
|
||||
use function GuzzleHttp\Psr7\str;
|
||||
use function GuzzleHttp\Psr7\stream_for;
|
||||
|
||||
class ListUsersController extends AdminController
|
||||
{
|
||||
|
||||
@@ -2,19 +2,18 @@
|
||||
|
||||
namespace App\Server\Http\Controllers\Admin;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use GuzzleHttp\Psr7\Response;
|
||||
use function GuzzleHttp\Psr7\str;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Str;
|
||||
use Ratchet\ConnectionInterface;
|
||||
use function GuzzleHttp\Psr7\str;
|
||||
|
||||
class RedirectToUsersController extends AdminController
|
||||
{
|
||||
public function handle(Request $request, ConnectionInterface $httpConnection)
|
||||
{
|
||||
$httpConnection->send(str(new Response(301, [
|
||||
'Location' => '/sites'
|
||||
'Location' => '/sites',
|
||||
])));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,10 +6,6 @@ use App\Contracts\ConnectionManager;
|
||||
use App\Server\Configuration;
|
||||
use Illuminate\Http\Request;
|
||||
use Ratchet\ConnectionInterface;
|
||||
use Twig\Environment;
|
||||
use Twig\Loader\ArrayLoader;
|
||||
use function GuzzleHttp\Psr7\str;
|
||||
use function GuzzleHttp\Psr7\stream_for;
|
||||
|
||||
class ShowSettingsController extends AdminController
|
||||
{
|
||||
|
||||
@@ -2,18 +2,10 @@
|
||||
|
||||
namespace App\Server\Http\Controllers\Admin;
|
||||
|
||||
use App\Contracts\ConnectionManager;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Server\Configuration;
|
||||
use Clue\React\SQLite\Result;
|
||||
use GuzzleHttp\Psr7\Response;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Arr;
|
||||
use Ratchet\ConnectionInterface;
|
||||
use Twig\Environment;
|
||||
use Twig\Loader\ArrayLoader;
|
||||
use function GuzzleHttp\Psr7\str;
|
||||
use function GuzzleHttp\Psr7\stream_for;
|
||||
|
||||
class StoreSettingsController extends AdminController
|
||||
{
|
||||
@@ -27,7 +19,7 @@ class StoreSettingsController extends AdminController
|
||||
|
||||
public function handle(Request $request, ConnectionInterface $httpConnection)
|
||||
{
|
||||
config()->set('expose.admin.validate_auth_tokens', (bool)$request->get('validate_auth_tokens'));
|
||||
config()->set('expose.admin.validate_auth_tokens', (bool) $request->get('validate_auth_tokens'));
|
||||
|
||||
$messages = $request->get('messages');
|
||||
|
||||
|
||||
@@ -3,17 +3,11 @@
|
||||
namespace App\Server\Http\Controllers\Admin;
|
||||
|
||||
use App\Contracts\UserRepository;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Clue\React\SQLite\Result;
|
||||
use GuzzleHttp\Psr7\Response;
|
||||
use function GuzzleHttp\Psr7\str;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Support\Str;
|
||||
use Ratchet\ConnectionInterface;
|
||||
use Twig\Environment;
|
||||
use Twig\Loader\ArrayLoader;
|
||||
use function GuzzleHttp\Psr7\str;
|
||||
use function GuzzleHttp\Psr7\stream_for;
|
||||
|
||||
class StoreUsersController extends AdminController
|
||||
{
|
||||
@@ -44,7 +38,7 @@ class StoreUsersController extends AdminController
|
||||
|
||||
$insertData = [
|
||||
'name' => $request->get('name'),
|
||||
'auth_token' => (string)Str::uuid()
|
||||
'auth_token' => (string) Str::uuid(),
|
||||
];
|
||||
|
||||
$this->userRepository
|
||||
|
||||
@@ -5,16 +5,15 @@ namespace App\Server\Http\Controllers;
|
||||
use App\Contracts\ConnectionManager;
|
||||
use App\Contracts\UserRepository;
|
||||
use App\Http\QueryParameters;
|
||||
use Ratchet\ConnectionInterface;
|
||||
use Ratchet\WebSocket\MessageComponentInterface;
|
||||
use React\Promise\Deferred;
|
||||
use React\Promise\FulfilledPromise;
|
||||
use React\Promise\PromiseInterface;
|
||||
use stdClass;
|
||||
use Ratchet\ConnectionInterface;
|
||||
|
||||
class ControlMessageController implements MessageComponentInterface
|
||||
{
|
||||
|
||||
/** @var ConnectionManager */
|
||||
protected $connectionManager;
|
||||
|
||||
@@ -28,16 +27,16 @@ class ControlMessageController implements MessageComponentInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function onOpen(ConnectionInterface $connection)
|
||||
public function onOpen(ConnectionInterface $connection)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function onClose(ConnectionInterface $connection)
|
||||
public function onClose(ConnectionInterface $connection)
|
||||
{
|
||||
if (isset($connection->request_id)) {
|
||||
$httpConnection = $this->connectionManager->getHttpConnectionForRequestId($connection->request_id);
|
||||
@@ -48,9 +47,9 @@ class ControlMessageController implements MessageComponentInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function onMessage(ConnectionInterface $connection, $msg)
|
||||
public function onMessage(ConnectionInterface $connection, $msg)
|
||||
{
|
||||
if (isset($connection->request_id)) {
|
||||
return $this->sendResponseToHttpConnection($connection->request_id, $msg);
|
||||
@@ -92,15 +91,15 @@ class ControlMessageController implements MessageComponentInterface
|
||||
'data' => [
|
||||
'message' => config('expose.admin.messages.message_of_the_day'),
|
||||
'subdomain' => $connectionInfo->subdomain,
|
||||
'client_id' => $connectionInfo->client_id
|
||||
'client_id' => $connectionInfo->client_id,
|
||||
],
|
||||
]));
|
||||
}, function () use ($connection) {
|
||||
$connection->send(json_encode([
|
||||
'event' => 'authenticationFailed',
|
||||
'data' => [
|
||||
'message' => config('expose.admin.messages.invalid_auth_token')
|
||||
]
|
||||
'message' => config('expose.admin.messages.invalid_auth_token'),
|
||||
],
|
||||
]));
|
||||
$connection->close();
|
||||
});
|
||||
@@ -112,15 +111,15 @@ class ControlMessageController implements MessageComponentInterface
|
||||
|
||||
$connectionInfo = $this->connectionManager->findControlConnectionForClientId($data->client_id);
|
||||
|
||||
$connectionInfo->emit('proxy_ready_' . $data->request_id, [
|
||||
$connectionInfo->emit('proxy_ready_'.$data->request_id, [
|
||||
$connection,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function onError(ConnectionInterface $conn, \Exception $e)
|
||||
public function onError(ConnectionInterface $conn, \Exception $e)
|
||||
{
|
||||
//
|
||||
}
|
||||
@@ -150,9 +149,9 @@ class ControlMessageController implements MessageComponentInterface
|
||||
|
||||
protected function hasValidSubdomain(ConnectionInterface $connection, ?string $subdomain): bool
|
||||
{
|
||||
if (!is_null($subdomain)) {
|
||||
if (! is_null($subdomain)) {
|
||||
$controlConnection = $this->connectionManager->findControlConnectionForSubdomain($subdomain);
|
||||
if (!is_null($controlConnection) || $subdomain === config('expose.admin.subdomain')) {
|
||||
if (! is_null($controlConnection) || $subdomain === config('expose.admin.subdomain')) {
|
||||
$message = config('expose.admin.messages.subdomain_taken');
|
||||
$message = str_replace(':subdomain', $subdomain, $message);
|
||||
|
||||
@@ -160,7 +159,7 @@ class ControlMessageController implements MessageComponentInterface
|
||||
'event' => 'subdomainTaken',
|
||||
'data' => [
|
||||
'message' => $message,
|
||||
]
|
||||
],
|
||||
]));
|
||||
$connection->close();
|
||||
|
||||
|
||||
@@ -7,16 +7,13 @@ use App\Http\Controllers\Controller;
|
||||
use App\Server\Configuration;
|
||||
use App\Server\Connections\ControlConnection;
|
||||
use App\Server\Connections\HttpConnection;
|
||||
use GuzzleHttp\Psr7\Response;
|
||||
use function GuzzleHttp\Psr7\str;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Pipeline\Pipeline;
|
||||
use Illuminate\Support\Str;
|
||||
use Nyholm\Psr7\Factory\Psr17Factory;
|
||||
use Ratchet\ConnectionInterface;
|
||||
use Ratchet\RFC6455\Messaging\Frame;
|
||||
use React\Promise\Deferred;
|
||||
use Symfony\Bridge\PsrHttpMessage\Factory\PsrHttpFactory;
|
||||
use function GuzzleHttp\Psr7\str;
|
||||
|
||||
class TunnelMessageController extends Controller
|
||||
{
|
||||
@@ -45,6 +42,7 @@ class TunnelMessageController extends Controller
|
||||
respond_html($this->getView($httpConnection, 'server.homepage'), 200)
|
||||
);
|
||||
$httpConnection->close();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -55,6 +53,7 @@ class TunnelMessageController extends Controller
|
||||
respond_html($this->getView($httpConnection, 'server.errors.404', ['subdomain' => $subdomain]), 404)
|
||||
);
|
||||
$httpConnection->close();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -77,7 +76,7 @@ class TunnelMessageController extends Controller
|
||||
$httpConnection = $this->connectionManager->storeHttpConnection($httpConnection, $requestId);
|
||||
|
||||
transform($this->passRequestThroughModifiers($request, $httpConnection), function (Request $request) use ($controlConnection, $httpConnection, $requestId) {
|
||||
$controlConnection->once('proxy_ready_' . $requestId, function (ConnectionInterface $proxy) use ($request) {
|
||||
$controlConnection->once('proxy_ready_'.$requestId, function (ConnectionInterface $proxy) use ($request) {
|
||||
// Convert the Laravel request into a PSR7 request
|
||||
$psr17Factory = new Psr17Factory();
|
||||
$psrHttpFactory = new PsrHttpFactory($psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory);
|
||||
@@ -110,7 +109,7 @@ class TunnelMessageController extends Controller
|
||||
|
||||
$host = $this->configuration->hostname();
|
||||
|
||||
if (!$request->isSecure()) {
|
||||
if (! $request->isSecure()) {
|
||||
$host .= ":{$this->configuration->port()}";
|
||||
}
|
||||
|
||||
@@ -118,7 +117,7 @@ class TunnelMessageController extends Controller
|
||||
$request->headers->set('X-Forwarded-Proto', $request->isSecure() ? 'https' : 'http');
|
||||
$request->headers->set('X-Expose-Request-ID', uniqid());
|
||||
$request->headers->set('Upgrade-Insecure-Requests', 1);
|
||||
$request->headers->set('X-Exposed-By', config('app.name') . ' ' . config('app.version'));
|
||||
$request->headers->set('X-Exposed-By', config('app.name').' '.config('app.version'));
|
||||
$request->headers->set('X-Original-Host', "{$controlConnection->subdomain}.{$host}");
|
||||
|
||||
return $request;
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
namespace App\Server\Http;
|
||||
|
||||
use App\Http\QueryParameters;
|
||||
use function GuzzleHttp\Psr7\build_query;
|
||||
use function GuzzleHttp\Psr7\parse_query;
|
||||
use GuzzleHttp\Psr7\ServerRequest;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use Ratchet\ConnectionInterface;
|
||||
@@ -13,8 +15,6 @@ use Symfony\Bridge\PsrHttpMessage\Factory\HttpFoundationFactory;
|
||||
use Symfony\Component\Routing\Exception\MethodNotAllowedException;
|
||||
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
|
||||
use Symfony\Component\Routing\Matcher\UrlMatcher;
|
||||
use function GuzzleHttp\Psr7\build_query;
|
||||
use function GuzzleHttp\Psr7\parse_query;
|
||||
|
||||
class Router implements HttpServerInterface
|
||||
{
|
||||
@@ -56,7 +56,7 @@ class Router implements HttpServerInterface
|
||||
try {
|
||||
$route = $this->_matcher->matchRequest($symfonyRequest);
|
||||
} catch (MethodNotAllowedException $nae) {
|
||||
return $this->close($conn, 405, array('Allow' => $nae->getAllowedMethods()));
|
||||
return $this->close($conn, 405, ['Allow' => $nae->getAllowedMethods()]);
|
||||
} catch (ResourceNotFoundException $nfe) {
|
||||
return $this->close($conn, 404);
|
||||
}
|
||||
@@ -65,7 +65,7 @@ class Router implements HttpServerInterface
|
||||
$route['_controller'] = new $route['_controller'];
|
||||
}
|
||||
|
||||
if (!($route['_controller'] instanceof HttpServerInterface)) {
|
||||
if (! ($route['_controller'] instanceof HttpServerInterface)) {
|
||||
throw new \UnexpectedValueException('All routes must implement Ratchet\Http\HttpServerInterface');
|
||||
}
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
namespace App\Server\SubdomainGenerator;
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
use App\Contracts\SubdomainGenerator;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class RandomSubdomainGenerator implements SubdomainGenerator
|
||||
{
|
||||
|
||||
@@ -23,7 +23,7 @@ class DatabaseUserRepository implements UserRepository
|
||||
$deferred = new Deferred();
|
||||
|
||||
$this->database
|
||||
->query("SELECT * FROM users ORDER by created_at DESC")
|
||||
->query('SELECT * FROM users ORDER by created_at DESC')
|
||||
->then(function (Result $result) use ($deferred) {
|
||||
$deferred->resolve($result->rows);
|
||||
});
|
||||
@@ -36,7 +36,7 @@ class DatabaseUserRepository implements UserRepository
|
||||
$deferred = new Deferred();
|
||||
|
||||
$this->database
|
||||
->query("SELECT * FROM users WHERE id = :id", ['id' => $id])
|
||||
->query('SELECT * FROM users WHERE id = :id', ['id' => $id])
|
||||
->then(function (Result $result) use ($deferred) {
|
||||
$deferred->resolve($result->rows[0] ?? null);
|
||||
});
|
||||
@@ -49,7 +49,7 @@ class DatabaseUserRepository implements UserRepository
|
||||
$deferred = new Deferred();
|
||||
|
||||
$this->database
|
||||
->query("SELECT * FROM users WHERE auth_token = :token", ['token' => $authToken])
|
||||
->query('SELECT * FROM users WHERE auth_token = :token', ['token' => $authToken])
|
||||
->then(function (Result $result) use ($deferred) {
|
||||
$deferred->resolve($result->rows[0] ?? null);
|
||||
});
|
||||
@@ -66,7 +66,7 @@ class DatabaseUserRepository implements UserRepository
|
||||
VALUES (:name, :auth_token, DATETIME('now'))
|
||||
", $data)
|
||||
->then(function (Result $result) use ($deferred) {
|
||||
$this->database->query("SELECT * FROM users WHERE id = :id", ['id' => $result->insertId])
|
||||
$this->database->query('SELECT * FROM users WHERE id = :id', ['id' => $result->insertId])
|
||||
->then(function (Result $result) use ($deferred) {
|
||||
$deferred->resolve($result->rows[0]);
|
||||
});
|
||||
@@ -79,7 +79,7 @@ class DatabaseUserRepository implements UserRepository
|
||||
{
|
||||
$deferred = new Deferred();
|
||||
|
||||
$this->database->query("DELETE FROM users WHERE id = :id", ['id' => $id])
|
||||
$this->database->query('DELETE FROM users WHERE id = :id', ['id' => $id])
|
||||
->then(function (Result $result) use ($deferred) {
|
||||
$deferred->resolve($result);
|
||||
});
|
||||
|
||||
@@ -93,28 +93,28 @@ return [
|
||||
*/
|
||||
'skip_body_log' => [
|
||||
/**
|
||||
| Skip response logging by HTTP response code. Format: 4*, 5*
|
||||
* | Skip response logging by HTTP response code. Format: 4*, 5*.
|
||||
*/
|
||||
'status' => [
|
||||
// "4*"
|
||||
],
|
||||
/**
|
||||
| Skip response logging by HTTP response content type. Ex: "text/css"
|
||||
* | Skip response logging by HTTP response content type. Ex: "text/css"
|
||||
*/
|
||||
'content_type' => [
|
||||
//
|
||||
],
|
||||
/**
|
||||
| Skip response logging by file extension. Ex: ".js.map", ".min.js", ".min.css"
|
||||
* | Skip response logging by file extension. Ex: ".js.map", ".min.js", ".min.css"
|
||||
*/
|
||||
'extension' => [
|
||||
'.js.map',
|
||||
'.css.map',
|
||||
],
|
||||
/**
|
||||
| Skip response logging if response size is greater than configured value.
|
||||
| Valid suffixes are: B, KB, MB, GB.
|
||||
| Ex: 500B, 1KB, 2MB, 3GB
|
||||
* | Skip response logging if response size is greater than configured value.
|
||||
* | Valid suffixes are: B, KB, MB, GB.
|
||||
* | Ex: 500B, 1KB, 2MB, 3GB
|
||||
*/
|
||||
'size' => '1MB',
|
||||
],
|
||||
@@ -134,7 +134,7 @@ return [
|
||||
'database' => implode(DIRECTORY_SEPARATOR, [
|
||||
$_SERVER['HOME'] ?? __DIR__,
|
||||
'.expose',
|
||||
'expose.db'
|
||||
'expose.db',
|
||||
]),
|
||||
|
||||
/*
|
||||
@@ -199,7 +199,7 @@ return [
|
||||
|
|
||||
*/
|
||||
'users' => [
|
||||
'username' => 'password'
|
||||
'username' => 'password',
|
||||
],
|
||||
|
||||
/*
|
||||
@@ -230,6 +230,6 @@ return [
|
||||
'invalid_auth_token' => 'Authentication failed. Please check your authentication token and try again.',
|
||||
|
||||
'subdomain_taken' => 'The chosen subdomain :subdomain is already taken. Please choose a different subdomain.',
|
||||
]
|
||||
]
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
@@ -9,14 +9,11 @@ use App\Logger\RequestLogger;
|
||||
use Clue\React\Buzz\Browser;
|
||||
use Clue\React\Buzz\Message\ResponseException;
|
||||
use GuzzleHttp\Psr7\Request;
|
||||
use function GuzzleHttp\Psr7\str;
|
||||
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 Tests\Feature\TestCase;
|
||||
use function GuzzleHttp\Psr7\str;
|
||||
|
||||
class DashboardTest extends TestCase
|
||||
{
|
||||
@@ -59,7 +56,7 @@ class DashboardTest extends TestCase
|
||||
public function it_can_replay_requests()
|
||||
{
|
||||
$request = new Request('GET', '/example', [
|
||||
'X-Expose-Request-ID' => 'request-one'
|
||||
'X-Expose-Request-ID' => 'request-one',
|
||||
]);
|
||||
|
||||
$httpClient = m::mock(HttpClient::class);
|
||||
@@ -74,7 +71,7 @@ class DashboardTest extends TestCase
|
||||
$this->logRequest($request);
|
||||
|
||||
$this->assertSame(200,
|
||||
$this->await($this->browser->get("http://127.0.0.1:4040/api/replay/request-one"))
|
||||
$this->await($this->browser->get('http://127.0.0.1:4040/api/replay/request-one'))
|
||||
->getStatusCode()
|
||||
);
|
||||
}
|
||||
@@ -87,7 +84,7 @@ class DashboardTest extends TestCase
|
||||
$this->expectException(ResponseException::class);
|
||||
$this->expectExceptionMessage(404);
|
||||
|
||||
$this->await($this->browser->get("http://127.0.0.1:4040/api/replay/invalid-request"));
|
||||
$this->await($this->browser->get('http://127.0.0.1:4040/api/replay/invalid-request'));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
@@ -101,7 +98,7 @@ class DashboardTest extends TestCase
|
||||
|
||||
$this->assertCount(3, $this->requestLogger->getData());
|
||||
|
||||
$this->await($this->browser->get("http://127.0.0.1:4040/api/logs/clear"));
|
||||
$this->await($this->browser->get('http://127.0.0.1:4040/api/logs/clear'));
|
||||
$this->assertCount(0, $this->requestLogger->getData());
|
||||
}
|
||||
|
||||
@@ -113,15 +110,15 @@ class DashboardTest extends TestCase
|
||||
$loggedRequest = $this->logRequest(new Request('GET', '/foo'));
|
||||
|
||||
$this->await($this->browser->post("http://127.0.0.1:4040/api/logs/{$loggedRequest->id()}/data", [
|
||||
'Content-Type' => 'application/json'
|
||||
'Content-Type' => 'application/json',
|
||||
], json_encode([
|
||||
'data' => [
|
||||
'foo' => 'bar',
|
||||
]
|
||||
],
|
||||
])));
|
||||
|
||||
$this->assertSame([
|
||||
'foo' => 'bar'
|
||||
'foo' => 'bar',
|
||||
], $this->requestLogger->findLoggedRequest($loggedRequest->id())->getAdditionalData());
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
namespace Tests\Feature\Server;
|
||||
|
||||
use App\Contracts\ConnectionManager;
|
||||
use App\Http\Server;
|
||||
use App\Server\Factory;
|
||||
use Clue\React\Buzz\Browser;
|
||||
use Clue\React\Buzz\Message\ResponseException;
|
||||
@@ -11,7 +10,6 @@ use GuzzleHttp\Psr7\Response;
|
||||
use Illuminate\Support\Str;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Ratchet\Server\IoConnection;
|
||||
use React\Socket\Connector;
|
||||
use Tests\Feature\TestCase;
|
||||
|
||||
class AdminTest extends TestCase
|
||||
@@ -19,7 +17,7 @@ class AdminTest extends TestCase
|
||||
/** @var Browser */
|
||||
protected $browser;
|
||||
|
||||
/** @var Factory */
|
||||
/** @var Factory */
|
||||
protected $serverFactory;
|
||||
|
||||
public function setUp(): void
|
||||
@@ -49,7 +47,7 @@ class AdminTest extends TestCase
|
||||
|
||||
/** @var ResponseInterface $response */
|
||||
$this->await($this->browser->get('http://127.0.0.1:8080', [
|
||||
'Host' => 'expose.localhost'
|
||||
'Host' => 'expose.localhost',
|
||||
]));
|
||||
}
|
||||
|
||||
@@ -59,7 +57,7 @@ class AdminTest extends TestCase
|
||||
/** @var ResponseInterface $response */
|
||||
$response = $this->await($this->browser->get('http://127.0.0.1:8080/', [
|
||||
'Host' => 'expose.localhost',
|
||||
'Authorization' => base64_encode("username:secret"),
|
||||
'Authorization' => base64_encode('username:secret'),
|
||||
]));
|
||||
$this->assertSame(301, $response->getStatusCode());
|
||||
}
|
||||
@@ -72,8 +70,8 @@ class AdminTest extends TestCase
|
||||
/** @var ResponseInterface $response */
|
||||
$this->await($this->browser->post('http://127.0.0.1:8080/api/settings', [
|
||||
'Host' => 'expose.localhost',
|
||||
'Authorization' => base64_encode("username:secret"),
|
||||
'Content-Type' => 'application/json'
|
||||
'Authorization' => base64_encode('username:secret'),
|
||||
'Content-Type' => 'application/json',
|
||||
], json_encode([
|
||||
'validate_auth_tokens' => true,
|
||||
])));
|
||||
@@ -87,8 +85,8 @@ class AdminTest extends TestCase
|
||||
/** @var Response $response */
|
||||
$response = $this->await($this->browser->post('http://127.0.0.1:8080/api/users', [
|
||||
'Host' => 'expose.localhost',
|
||||
'Authorization' => base64_encode("username:secret"),
|
||||
'Content-Type' => 'application/json'
|
||||
'Authorization' => base64_encode('username:secret'),
|
||||
'Content-Type' => 'application/json',
|
||||
], json_encode([
|
||||
'name' => 'Marcel',
|
||||
])));
|
||||
@@ -105,17 +103,16 @@ class AdminTest extends TestCase
|
||||
/** @var Response $response */
|
||||
$this->await($this->browser->post('http://127.0.0.1:8080/api/users', [
|
||||
'Host' => 'expose.localhost',
|
||||
'Authorization' => base64_encode("username:secret"),
|
||||
'Content-Type' => 'application/json'
|
||||
'Authorization' => base64_encode('username:secret'),
|
||||
'Content-Type' => 'application/json',
|
||||
], json_encode([
|
||||
'name' => 'Marcel',
|
||||
])));
|
||||
|
||||
|
||||
$this->await($this->browser->delete('http://127.0.0.1:8080/api/users/1', [
|
||||
'Host' => 'expose.localhost',
|
||||
'Authorization' => base64_encode("username:secret"),
|
||||
'Content-Type' => 'application/json'
|
||||
'Authorization' => base64_encode('username:secret'),
|
||||
'Content-Type' => 'application/json',
|
||||
]));
|
||||
|
||||
$this->assertDatabaseHasNoResults('SELECT * FROM users WHERE name = "Marcel"');
|
||||
@@ -127,8 +124,8 @@ class AdminTest extends TestCase
|
||||
/** @var Response $response */
|
||||
$this->await($this->browser->post('http://127.0.0.1:8080/api/users', [
|
||||
'Host' => 'expose.localhost',
|
||||
'Authorization' => base64_encode("username:secret"),
|
||||
'Content-Type' => 'application/json'
|
||||
'Authorization' => base64_encode('username:secret'),
|
||||
'Content-Type' => 'application/json',
|
||||
], json_encode([
|
||||
'name' => 'Marcel',
|
||||
])));
|
||||
@@ -136,8 +133,8 @@ class AdminTest extends TestCase
|
||||
/** @var Response $response */
|
||||
$response = $this->await($this->browser->get('http://127.0.0.1:8080/users', [
|
||||
'Host' => 'expose.localhost',
|
||||
'Authorization' => base64_encode("username:secret"),
|
||||
'Content-Type' => 'application/json'
|
||||
'Authorization' => base64_encode('username:secret'),
|
||||
'Content-Type' => 'application/json',
|
||||
]));
|
||||
|
||||
$body = $response->getBody()->getContents();
|
||||
@@ -157,8 +154,8 @@ class AdminTest extends TestCase
|
||||
/** @var Response $response */
|
||||
$response = $this->await($this->browser->get('http://127.0.0.1:8080/sites', [
|
||||
'Host' => 'expose.localhost',
|
||||
'Authorization' => base64_encode("username:secret"),
|
||||
'Content-Type' => 'application/json'
|
||||
'Authorization' => base64_encode('username:secret'),
|
||||
'Content-Type' => 'application/json',
|
||||
]));
|
||||
|
||||
$body = $response->getBody()->getContents();
|
||||
|
||||
@@ -3,18 +3,13 @@
|
||||
namespace Tests\Feature\Server;
|
||||
|
||||
use App\Client\Client;
|
||||
use App\Contracts\ConnectionManager;
|
||||
use App\Server\Factory;
|
||||
use Clue\React\Buzz\Browser;
|
||||
use Clue\React\Buzz\Message\ResponseException;
|
||||
use GuzzleHttp\Psr7\Response;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Ratchet\Client\WebSocket;
|
||||
use Ratchet\ConnectionInterface;
|
||||
use React\EventLoop\LoopInterface;
|
||||
use React\Http\Server;
|
||||
use Tests\Feature\TestCase;
|
||||
use function Ratchet\Client\connect;
|
||||
|
||||
class TunnelTest extends TestCase
|
||||
{
|
||||
@@ -54,7 +49,7 @@ class TunnelTest extends TestCase
|
||||
$this->expectExceptionMessage(404);
|
||||
|
||||
$response = $this->await($this->browser->get('http://127.0.0.1:8080/', [
|
||||
'Host' => 'tunnel.localhost'
|
||||
'Host' => 'tunnel.localhost',
|
||||
]));
|
||||
}
|
||||
|
||||
@@ -65,7 +60,7 @@ class TunnelTest extends TestCase
|
||||
|
||||
/**
|
||||
* We create an expose client that connects to our server and shares
|
||||
* the created test HTTP server
|
||||
* the created test HTTP server.
|
||||
*/
|
||||
$client = $this->createClient();
|
||||
$this->await($client->connectToServer('127.0.0.1:8085', 'tunnel'));
|
||||
@@ -75,7 +70,7 @@ class TunnelTest extends TestCase
|
||||
* created tunnel.
|
||||
*/
|
||||
$response = $this->await($this->browser->get('http://127.0.0.1:8080/', [
|
||||
'Host' => 'tunnel.localhost'
|
||||
'Host' => 'tunnel.localhost',
|
||||
]));
|
||||
|
||||
$this->assertSame('Hello World!', $response->getBody()->getContents());
|
||||
@@ -92,7 +87,7 @@ class TunnelTest extends TestCase
|
||||
|
||||
/**
|
||||
* We create an expose client that connects to our server and shares
|
||||
* the created test HTTP server
|
||||
* the created test HTTP server.
|
||||
*/
|
||||
$client = $this->createClient();
|
||||
$result = $this->await($client->connectToServer('127.0.0.1:8085', 'tunnel'));
|
||||
@@ -109,7 +104,7 @@ class TunnelTest extends TestCase
|
||||
|
||||
/**
|
||||
* We create an expose client that connects to our server and shares
|
||||
* the created test HTTP server
|
||||
* the created test HTTP server.
|
||||
*/
|
||||
$client = $this->createClient();
|
||||
$this->await($client->connectToServer('127.0.0.1:8085', 'tunnel'));
|
||||
@@ -141,7 +136,7 @@ class TunnelTest extends TestCase
|
||||
protected function createTestHttpServer()
|
||||
{
|
||||
$server = new Server(function (ServerRequestInterface $request) {
|
||||
return new Response(200, ['Content-Type' => 'text/plain'], "Hello World!");
|
||||
return new Response(200, ['Content-Type' => 'text/plain'], 'Hello World!');
|
||||
});
|
||||
|
||||
$this->testHttpServer = new \React\Socket\Server(8085, $this->loop);
|
||||
|
||||
@@ -2,17 +2,12 @@
|
||||
|
||||
namespace Tests\Feature;
|
||||
|
||||
use function Clue\React\Block\await;
|
||||
use Clue\React\SQLite\DatabaseInterface;
|
||||
use GuzzleHttp\Psr7\Response;
|
||||
use Illuminate\Support\Str;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
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
|
||||
{
|
||||
@@ -25,7 +20,7 @@ abstract class TestCase extends \Tests\TestCase
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->app->bind(ConsoleOutputInterface::class, function() {
|
||||
$this->app->bind(ConsoleOutputInterface::class, function () {
|
||||
return new ConsoleOutput();
|
||||
});
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace Tests;
|
||||
|
||||
use Clue\React\SQLite\DatabaseInterface;
|
||||
use LaravelZero\Framework\Testing\TestCase as BaseTestCase;
|
||||
|
||||
abstract class TestCase extends BaseTestCase
|
||||
|
||||
@@ -4,11 +4,9 @@ namespace Tests\Unit;
|
||||
|
||||
use App\Logger\LoggedRequest;
|
||||
use GuzzleHttp\Psr7\Request;
|
||||
use GuzzleHttp\Psr7\Response;
|
||||
use Laminas\Http\Request as LaminasRequest;
|
||||
use Laminas\Http\Response as LaminasResponse;
|
||||
use Tests\TestCase;
|
||||
use function GuzzleHttp\Psr7\str;
|
||||
use Laminas\Http\Request as LaminasRequest;
|
||||
use Tests\TestCase;
|
||||
|
||||
class LoggedRequestTest extends TestCase
|
||||
{
|
||||
@@ -16,7 +14,7 @@ class LoggedRequestTest extends TestCase
|
||||
public function it_retrieves_the_request_id()
|
||||
{
|
||||
$rawRequest = str(new Request(200, '/expose', [
|
||||
'X-Expose-Request-ID' => 'example-request'
|
||||
'X-Expose-Request-ID' => 'example-request',
|
||||
]));
|
||||
$parsedRequest = LaminasRequest::fromString($rawRequest);
|
||||
|
||||
@@ -29,11 +27,11 @@ class LoggedRequestTest extends TestCase
|
||||
{
|
||||
$postData = [
|
||||
'name' => 'Marcel',
|
||||
'project' => 'expose'
|
||||
'project' => 'expose',
|
||||
];
|
||||
|
||||
$rawRequest = str(new Request(200, '/expose', [
|
||||
'Content-Type' => 'application/json'
|
||||
'Content-Type' => 'application/json',
|
||||
], json_encode($postData)));
|
||||
$parsedRequest = LaminasRequest::fromString($rawRequest);
|
||||
|
||||
@@ -42,12 +40,12 @@ class LoggedRequestTest extends TestCase
|
||||
$this->assertSame([
|
||||
[
|
||||
'name' => 'name',
|
||||
'value' => 'Marcel'
|
||||
'value' => 'Marcel',
|
||||
],
|
||||
[
|
||||
'name' => 'project',
|
||||
'value' => 'expose'
|
||||
]
|
||||
'value' => 'expose',
|
||||
],
|
||||
], $loggedRequest->getPostData());
|
||||
}
|
||||
|
||||
@@ -55,7 +53,7 @@ class LoggedRequestTest extends TestCase
|
||||
public function it_returns_the_raw_request()
|
||||
{
|
||||
$rawRequest = str(new Request(200, '/expose', [
|
||||
'X-Expose-Request-ID' => 'example-request'
|
||||
'X-Expose-Request-ID' => 'example-request',
|
||||
]));
|
||||
$parsedRequest = LaminasRequest::fromString($rawRequest);
|
||||
|
||||
@@ -67,7 +65,7 @@ class LoggedRequestTest extends TestCase
|
||||
public function it_returns_the_parsed_request()
|
||||
{
|
||||
$rawRequest = str(new Request(200, '/expose', [
|
||||
'X-Expose-Request-ID' => 'example-request'
|
||||
'X-Expose-Request-ID' => 'example-request',
|
||||
]));
|
||||
$parsedRequest = LaminasRequest::fromString($rawRequest);
|
||||
|
||||
|
||||
@@ -7,10 +7,10 @@ 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 Laminas\Http\Request as LaminasRequest;
|
||||
use Mockery as m;
|
||||
use Tests\TestCase;
|
||||
|
||||
class RequestLoggerTest extends TestCase
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user