Skip to content

Commit

Permalink
Merge pull request #18 from edersoares/proxy
Browse files Browse the repository at this point in the history
Proxy
  • Loading branch information
edersoares authored May 29, 2024
2 parents ae079c2 + 29231a3 commit d5d1f16
Show file tree
Hide file tree
Showing 6 changed files with 190 additions and 1 deletion.
10 changes: 10 additions & 0 deletions config/frontier.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,14 @@
],
],

'proxy' => [

'type' => 'proxy',

'host' => env('FRONTIER_PROXY_HOST', ''),

'rules' => array_filter(explode(',', env('FRONTIER_PROXY_RULES', ''))),

],

];
6 changes: 6 additions & 0 deletions routes/frontier.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?php

use Dex\Laravel\Frontier\Frontier;

Frontier::addFromConfig('frontier.frontier');
Frontier::addFromConfig('frontier.proxy');
41 changes: 41 additions & 0 deletions src/FrontendProxyController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

declare(strict_types=1);

namespace Dex\Laravel\Frontier;

use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Http;

class FrontendProxyController
{
public function __construct(protected Request $request)
{
}

public function __invoke($uri, $config): Response
{
$accept = $this->request->header('accept', '*/*');
$url = trim($config['url'], '/') . '/' . trim($uri, '/');

$response = Http::withHeaders([
'Accept' => $accept,
])->get($url);

$content = $response->body();
$contextType = $response->header('content-type');

if ($config['replaces']) {
$content = str_replace(
array_keys($config['replaces']),
array_values($config['replaces']),
$content
);
}

return new Response($content, headers: [
'content-type' => $contextType,
]);
}
}
51 changes: 51 additions & 0 deletions src/Frontier.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public static function add(array $config): void
{
match ($config['type']) {
'http' => self::http($config),
'proxy' => self::proxy($config),
'view' => self::view($config),
};
}
Expand All @@ -27,6 +28,56 @@ private static function http(array $config): void
self::frontend($config);
}

private static function proxy(array $config): void
{
$host = $config['host'] ?? '';
$rules = $config['rules'] ?? [];

foreach ($rules as $rule) {
$segments = explode(':', $rule);

$url = $host;
$uri = $segments[0];
$replaces = [];
$proxyAll = true;

foreach ($segments as $segment) {
if ($segment === 'exact') {
$proxyAll = false;
}

if (str_starts_with($segment, 'replace(') && str_ends_with($segment, ')')) {
$replace = substr($segment, 8, -1);

[$search, $replace] = explode(',', $replace . ',');

if (empty($replace)) {
$replace = $url . $search;
}

$replaces[$search] = $replace;
}
}

if ($proxyAll) {
$url = $url . $uri;
$uri .= '/{uri?}';
}

$uri = str_replace('//', '/', $uri);

Route::get($uri, FrontendProxyController::class)
->where('uri', '.*')
->setDefaults([
'uri' => $uri,
'config' => [
'url' => $url,
'replaces' => $replaces,
],
]);
}
}

private static function view(array $config): void
{
self::frontend($config);
Expand Down
2 changes: 1 addition & 1 deletion src/FrontierServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,6 @@ public function boot(): void
}
}

Frontier::addFromConfig('frontier.frontier');
$this->loadRoutesFrom(__DIR__ . '/../routes/frontier.php');
}
}
81 changes: 81 additions & 0 deletions tests/FrontendProxyControllerTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
<?php

declare(strict_types=1);

namespace Dex\Laravel\Frontier\Tests;

use Dex\Laravel\Frontier\Frontier;
use Illuminate\Support\Facades\Http;

beforeEach(fn () => Frontier::add([
'type' => 'proxy',
'host' => 'frontier.test',
'rules' => [
'/favicon.ico:exact',
'/exact/replace:exact:replace(/exact/replace)',
'/all:replace(Replace,is amazing!)',
'/web',
],
]));

test('proxy exact route', function () {
Http::fake([
'frontier.test/favicon.ico' => Http::response('Frontier Favicon'),
]);

$this->get('favicon.ico')
->assertContent('Frontier Favicon')
->assertOk();

$this->get('favicon.icon')
->assertNotFound();

$this->get('favicon.ico/ico')
->assertNotFound();
});

test('proxy all routes', function () {
Http::fake([
'frontier.test/web/*' => Http::response('Frontier Favicon'),
]);

$this->get('/web')
->assertOk();

$this->get('/web/one')
->assertOk();

$this->get('web/two')
->assertOk();
});

test('proxy exact and replace', function () {
Http::fake([
'frontier.test/exact/replace' => Http::response('Running: /exact/replace'),
]);

$this->get('/exact/replace')
->assertContent('Running: frontier.test/exact/replace')
->assertOk();

$this->get('exact/replace/more')
->assertNotFound();
});

test('proxy all routes and replace', function () {
Http::fake([
'frontier.test/all/*' => Http::response('Frontier Replace'),
]);

$this->get('/all')
->assertContent('Frontier is amazing!')
->assertOk();

$this->get('/all/one')
->assertContent('Frontier is amazing!')
->assertOk();

$this->get('all/two')
->assertContent('Frontier is amazing!')
->assertOk();
});

0 comments on commit d5d1f16

Please sign in to comment.