mirror of
https://github.com/archtechx/tenancy.git
synced 2025-12-12 15:34:03 +00:00
Fix subdomain middleware
This commit is contained in:
parent
94abd732ae
commit
d20056b804
2 changed files with 48 additions and 19 deletions
|
|
@ -5,15 +5,13 @@ declare(strict_types=1);
|
||||||
namespace Stancl\Tenancy\Middleware;
|
namespace Stancl\Tenancy\Middleware;
|
||||||
|
|
||||||
use Closure;
|
use Closure;
|
||||||
|
use Exception;
|
||||||
use Illuminate\Http\Response;
|
use Illuminate\Http\Response;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
use Stancl\Tenancy\Exceptions\NotASubdomainException;
|
use Stancl\Tenancy\Exceptions\NotASubdomainException;
|
||||||
|
|
||||||
class InitializeTenancyBySubdomain extends InitializeTenancyByDomain
|
class InitializeTenancyBySubdomain extends InitializeTenancyByDomain
|
||||||
{
|
{
|
||||||
/** @var callable|null */
|
|
||||||
public static $onInvalidSubdomain;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The index of the subdomain fragment in the hostname
|
* The index of the subdomain fragment in the hostname
|
||||||
* split by `.`. 0 for first fragment, 1 if you prefix
|
* split by `.`. 0 for first fragment, 1 if you prefix
|
||||||
|
|
@ -37,19 +35,27 @@ class InitializeTenancyBySubdomain extends InitializeTenancyByDomain
|
||||||
{
|
{
|
||||||
$subdomain = $this->makeSubdomain($request->getHost());
|
$subdomain = $this->makeSubdomain($request->getHost());
|
||||||
|
|
||||||
// If a non-string, like a Response instance was returned
|
if (is_object($subdomain) && $subdomain instanceof Exception) {
|
||||||
// from makeSubdomain() - due to NotASubDomainException
|
$onFail = static::$onFail ?? function ($e) {
|
||||||
// being thrown, we abort by returning the value now.
|
throw $e;
|
||||||
if (! is_string($subdomain)) {
|
};
|
||||||
|
|
||||||
|
return $onFail($subdomain, $request, $next);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If a Response instance was returned, we return it immediately.
|
||||||
|
if (is_object($subdomain) && $subdomain instanceof Response) {
|
||||||
return $subdomain;
|
return $subdomain;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->initializeTenancy(
|
return $this->initializeTenancy(
|
||||||
$request, $next, $subdomain
|
$request,
|
||||||
|
$next,
|
||||||
|
$subdomain
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return string|Response|mixed */
|
/** @return string|Response|Exception|mixed */
|
||||||
protected function makeSubdomain(string $hostname)
|
protected function makeSubdomain(string $hostname)
|
||||||
{
|
{
|
||||||
$parts = explode('.', $hostname);
|
$parts = explode('.', $hostname);
|
||||||
|
|
@ -58,15 +64,12 @@ class InitializeTenancyBySubdomain extends InitializeTenancyByDomain
|
||||||
$isIpAddress = count(array_filter($parts, 'is_numeric')) === count($parts);
|
$isIpAddress = count(array_filter($parts, 'is_numeric')) === count($parts);
|
||||||
|
|
||||||
// If we're on localhost or an IP address, then we're not visiting a subdomain.
|
// If we're on localhost or an IP address, then we're not visiting a subdomain.
|
||||||
|
$isACentralDomain = in_array($hostname, config('tenancy.central_domains'), true);
|
||||||
$notADomain = $isLocalhost || $isIpAddress;
|
$notADomain = $isLocalhost || $isIpAddress;
|
||||||
$thirdPartyDomain = !Str::endsWith($hostname, config('tenancy.central_domains'));
|
$thirdPartyDomain = !Str::endsWith($hostname, config('tenancy.central_domains'));
|
||||||
|
|
||||||
if ($notADomain || $thirdPartyDomain) {
|
if ($isACentralDomain || $notADomain || $thirdPartyDomain) {
|
||||||
$handle = static::$onInvalidSubdomain ?? function ($e) {
|
return new NotASubdomainException($hostname);
|
||||||
throw $e;
|
|
||||||
};
|
|
||||||
|
|
||||||
return $handle(new NotASubdomainException($hostname));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $parts[static::$subdomainIndex];
|
return $parts[static::$subdomainIndex];
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ class SubdomainTest extends TestCase
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
|
|
||||||
// Global state cleanup after some tests
|
// Global state cleanup after some tests
|
||||||
InitializeTenancyBySubdomain::$onInvalidSubdomain = null;
|
InitializeTenancyBySubdomain::$onFail = null;
|
||||||
|
|
||||||
Route::group([
|
Route::group([
|
||||||
'middleware' => InitializeTenancyBySubdomain::class,
|
'middleware' => InitializeTenancyBySubdomain::class,
|
||||||
|
|
@ -88,8 +88,12 @@ class SubdomainTest extends TestCase
|
||||||
{
|
{
|
||||||
// in this case, we need to return a response instance
|
// in this case, we need to return a response instance
|
||||||
// since a string would be treated as the subdomain
|
// since a string would be treated as the subdomain
|
||||||
InitializeTenancyBySubdomain::$onInvalidSubdomain = function () {
|
InitializeTenancyBySubdomain::$onFail = function ($e) {
|
||||||
|
if ($e instanceof NotASubdomainException) {
|
||||||
return response('foo custom invalid subdomain handler');
|
return response('foo custom invalid subdomain handler');
|
||||||
|
}
|
||||||
|
|
||||||
|
throw $e;
|
||||||
};
|
};
|
||||||
|
|
||||||
$this
|
$this
|
||||||
|
|
@ -120,6 +124,28 @@ class SubdomainTest extends TestCase
|
||||||
->withoutExceptionHandling()
|
->withoutExceptionHandling()
|
||||||
->get('http://foo.localhost/foo/abc/xyz');
|
->get('http://foo.localhost/foo/abc/xyz');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @test */
|
||||||
|
public function central_domain_is_not_a_subdomain()
|
||||||
|
{
|
||||||
|
config(['tenancy.central_domains' => [
|
||||||
|
'localhost',
|
||||||
|
]]);
|
||||||
|
|
||||||
|
$tenant = SubdomainTenant::create([
|
||||||
|
'id' => 'acme',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$tenant->domains()->create([
|
||||||
|
'domain' => 'acme',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->expectException(NotASubdomainException::class);
|
||||||
|
|
||||||
|
$this
|
||||||
|
->withoutExceptionHandling()
|
||||||
|
->get('http://localhost/foo/abc/xyz');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SubdomainTenant extends Models\Tenant
|
class SubdomainTenant extends Models\Tenant
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue