10 Commits

Author SHA1 Message Date
René Preuß
763b45a77e Remove rewrite header 2021-01-01 20:13:08 +01:00
René Preuß
f137ea298b Fix prepare method to generate a valid dsn 2021-01-01 20:07:18 +01:00
René Preuß
2f457352c5 Undo test rename 2021-01-01 17:28:10 +01:00
René Preuß
c5cdd8c352 Fix style ci 2021-01-01 16:55:52 +01:00
René Preuß
6f72d719bf Fix http/s protocol headers
Improve request ids
2021-01-01 16:06:59 +01:00
Siebe Vanden Eynden
f6d04777e1 Allow custom config file path (#145)
* allow custom config file path

* Update configuration.md
2020-12-04 22:45:29 +01:00
Tii
bded9f754e Added command line options for server-host and server-port (#147)
* Added server options

* Restored box.json

* Reverted build and versioning...

* Please the style gods
2020-12-04 22:44:25 +01:00
Tii
c92d4b258c Removed fixed IP address for DNS (#148) 2020-12-04 22:39:57 +01:00
Marcel Pociot
eb8d1f4f91 Merge pull request #154 from beyondcode/analysis-5ZodwW
Apply fixes from StyleCI
2020-11-01 20:34:40 +01:00
Marcel Pociot
da39fb8ad8 Apply fixes from StyleCI 2020-11-01 19:34:33 +00:00
8 changed files with 51 additions and 50 deletions

View File

@@ -45,13 +45,13 @@ class Client
$sharedUrl = $this->prepareSharedUrl($sharedUrl); $sharedUrl = $this->prepareSharedUrl($sharedUrl);
foreach ($subdomains as $subdomain) { foreach ($subdomains as $subdomain) {
$this->connectToServer($sharedUrl, $subdomain, config('expose.auth_token')); $this->connectToServer($sharedUrl, $subdomain, $this->configuration->auth());
} }
} }
public function sharePort(int $port) public function sharePort(int $port)
{ {
$this->connectToServerAndShareTcp($port, config('expose.auth_token')); $this->connectToServerAndShareTcp($port, $this->configuration->auth());
} }
protected function prepareSharedUrl(string $sharedUrl): string protected function prepareSharedUrl(string $sharedUrl): string
@@ -60,16 +60,11 @@ class Client
return $sharedUrl; return $sharedUrl;
} }
$url = Arr::get($parsedUrl, 'host', Arr::get($parsedUrl, 'path')); $host = Arr::get($parsedUrl, 'host', Arr::get($parsedUrl, 'path', 'localhost'));
$scheme = Arr::get($parsedUrl, 'scheme', 'http');
$port = Arr::get($parsedUrl, 'port', $scheme === 'https' ? 443 : 80);
if (Arr::get($parsedUrl, 'scheme') === 'https') { return sprintf('%s://%s:%s', $scheme, $host, $port);
$url .= ':443';
}
if (! is_null($port = Arr::get($parsedUrl, 'port'))) {
$url .= ":{$port}";
}
return $url;
} }
public function connectToServer(string $sharedUrl, $subdomain, $authToken = ''): PromiseInterface public function connectToServer(string $sharedUrl, $subdomain, $authToken = ''): PromiseInterface

View File

@@ -11,10 +11,12 @@ use function GuzzleHttp\Psr7\str;
use Laminas\Http\Request; use Laminas\Http\Request;
use Psr\Http\Message\RequestInterface; use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\UriInterface;
use Ratchet\Client\WebSocket; use Ratchet\Client\WebSocket;
use Ratchet\RFC6455\Messaging\Frame; use Ratchet\RFC6455\Messaging\Frame;
use React\EventLoop\LoopInterface; use React\EventLoop\LoopInterface;
use React\Socket\Connector; use React\Socket\Connector;
use React\Stream\ReadableStreamInterface;
class HttpClient class HttpClient
{ {
@@ -74,7 +76,6 @@ class HttpClient
protected function createConnector(): Connector protected function createConnector(): Connector
{ {
return new Connector($this->loop, [ return new Connector($this->loop, [
'dns' => '127.0.0.1',
'tls' => [ 'tls' => [
'verify_peer' => false, 'verify_peer' => false,
'verify_peer_name' => false, 'verify_peer_name' => false,
@@ -85,22 +86,17 @@ class HttpClient
protected function sendRequestToApplication(RequestInterface $request, $proxyConnection = null) protected function sendRequestToApplication(RequestInterface $request, $proxyConnection = null)
{ {
(new Browser($this->loop, $this->createConnector())) (new Browser($this->loop, $this->createConnector()))
->withOptions([ ->withFollowRedirects(false)
'followRedirects' => false, ->withRejectErrorResponse(false)
'obeySuccessCode' => false, ->requestStreaming($request->getMethod(), $this->getExposeUri($request), $request->getHeaders(), $request->getBody())
'streaming' => true,
])
->send($request)
->then(function (ResponseInterface $response) use ($proxyConnection) { ->then(function (ResponseInterface $response) use ($proxyConnection) {
if (! isset($response->buffer)) { if (! isset($response->buffer)) {
$response = $this->rewriteResponseHeaders($response);
$response->buffer = str($response); $response->buffer = str($response);
} }
$this->sendChunkToServer($response->buffer, $proxyConnection); $this->sendChunkToServer($response->buffer, $proxyConnection);
/* @var $body \React\Stream\ReadableStreamInterface */ /* @var $body ReadableStreamInterface */
$body = $response->getBody(); $body = $response->getBody();
$this->logResponse(str($response)); $this->logResponse(str($response));
@@ -137,24 +133,14 @@ class HttpClient
return Request::fromString($data); return Request::fromString($data);
} }
protected function rewriteResponseHeaders(ResponseInterface $response) private function getExposeUri(RequestInterface $request): UriInterface
{ {
if (!$response->hasHeader('Location')) { $exposeProto = $request->getHeader('x-expose-proto')[0];
return $response; $exposeHost = explode(':', $request->getHeader('x-expose-host')[0]);
}
$location = $response->getHeaderLine('Location'); return $request->getUri()
->withScheme($exposeProto)
if (!strstr($location, $this->connectionData->host)) { ->withHost($exposeHost[0])
return $response; ->withPort($exposeHost[1]);
}
$location = str_replace(
$this->connectionData->host,
$this->configuration->getUrl($this->connectionData->subdomain),
$location
);
return $response->withHeader('Location', $location);
} }
} }

View File

@@ -10,7 +10,7 @@ use Symfony\Component\Console\Output\ConsoleOutput;
class ShareCommand extends Command class ShareCommand extends Command
{ {
protected $signature = 'share {host} {--subdomain=} {--auth=}'; protected $signature = 'share {host} {--subdomain=} {--auth=} {--server-host=} {--server-port=}';
protected $description = 'Share a local url with a remote expose server'; protected $description = 'Share a local url with a remote expose server';
@@ -27,11 +27,15 @@ class ShareCommand extends Command
{ {
$this->configureConnectionLogger(); $this->configureConnectionLogger();
$serverHost = $this->option('server-host') ?? config('expose.host', 'localhost');
$serverPort = $this->option('server-port') ?? config('expose.port', 8080);
$auth = $this->option('auth') ?? config('expose.auth_token', '');
(new Factory()) (new Factory())
->setLoop(app(LoopInterface::class)) ->setLoop(app(LoopInterface::class))
->setHost(config('expose.host', 'localhost')) ->setHost($serverHost)
->setPort(config('expose.port', 8080)) ->setPort($serverPort)
->setAuth($this->option('auth')) ->setAuth($auth)
->createClient() ->createClient()
->share($this->argument('host'), explode(',', $this->option('subdomain'))) ->share($this->argument('host'), explode(',', $this->option('subdomain')))
->createHttpServer() ->createHttpServer()

View File

@@ -4,7 +4,7 @@ namespace App\Commands;
class ShareCurrentWorkingDirectoryCommand extends ShareCommand class ShareCurrentWorkingDirectoryCommand extends ShareCommand
{ {
protected $signature = 'share-cwd {host?} {--subdomain=} {--auth=}'; protected $signature = 'share-cwd {host?} {--subdomain=} {--auth=} {--server-host=} {--server-port=}';
public function handle() public function handle()
{ {

View File

@@ -37,6 +37,14 @@ class AppServiceProvider extends ServiceProvider
{ {
$builtInConfig = config('expose'); $builtInConfig = config('expose');
$keyServerVariable = 'EXPOSE_CONFIG_FILE';
if (array_key_exists($keyServerVariable, $_SERVER) && is_string($_SERVER[$keyServerVariable]) && file_exists($_SERVER[$keyServerVariable])) {
$localConfig = require $_SERVER[$keyServerVariable];
config()->set('expose', array_merge($builtInConfig, $localConfig));
return;
}
$localConfigFile = getcwd().DIRECTORY_SEPARATOR.'.expose.php'; $localConfigFile = getcwd().DIRECTORY_SEPARATOR.'.expose.php';
if (file_exists($localConfigFile)) { if (file_exists($localConfigFile)) {

View File

@@ -45,15 +45,13 @@ class ConnectionManager implements ConnectionManagerContract
public function storeConnection(string $host, ?string $subdomain, ConnectionInterface $connection): ControlConnection public function storeConnection(string $host, ?string $subdomain, ConnectionInterface $connection): ControlConnection
{ {
$clientId = (string) uniqid(); $connection->client_id = sha1(uniqid('', true));
$connection->client_id = $clientId;
$storedConnection = new ControlConnection( $storedConnection = new ControlConnection(
$connection, $connection,
$host, $host,
$subdomain ?? $this->subdomainGenerator->generateSubdomain(), $subdomain ?? $this->subdomainGenerator->generateSubdomain(),
$clientId, $connection->client_id,
$this->getAuthTokenFromConnection($connection) $this->getAuthTokenFromConnection($connection)
); );

View File

@@ -113,9 +113,13 @@ class TunnelMessageController extends Controller
$host .= ":{$this->configuration->port()}"; $host .= ":{$this->configuration->port()}";
} }
$request->headers->set('Host', $controlConnection->host); $exposeUrl = parse_url($controlConnection->host);
$request->headers->set('Host', "{$controlConnection->subdomain}.{$host}");
$request->headers->set('X-Forwarded-Proto', $request->isSecure() ? 'https' : 'http'); $request->headers->set('X-Forwarded-Proto', $request->isSecure() ? 'https' : 'http');
$request->headers->set('X-Expose-Request-ID', uniqid()); $request->headers->set('X-Expose-Request-ID', sha1(uniqid('', true)));
$request->headers->set('X-Expose-Host', sprintf('%s:%s', $exposeUrl['host'], $exposeUrl['port']));
$request->headers->set('X-Expose-Proto', $exposeUrl['scheme']);
$request->headers->set('Upgrade-Insecure-Requests', 1); $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}"); $request->headers->set('X-Original-Host', "{$controlConnection->subdomain}.{$host}");

View File

@@ -17,6 +17,12 @@ The configuration file will be written to your home directory inside a `.expose`
`~/.expose/config.php` `~/.expose/config.php`
You can also provide a custom location of the config file by providing the full path as a server variable.
```bash
EXPOSE_CONFIG_FILE="~/my-custom-config.php" expose share
```
And the default content of the configuration file is this: And the default content of the configuration file is this:
```php ```php