mirror of
https://github.com/archtechx/tenancy.git
synced 2025-12-12 13:54: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;
|
||||
|
||||
use Closure;
|
||||
use Exception;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Support\Str;
|
||||
use Stancl\Tenancy\Exceptions\NotASubdomainException;
|
||||
|
||||
class InitializeTenancyBySubdomain extends InitializeTenancyByDomain
|
||||
{
|
||||
/** @var callable|null */
|
||||
public static $onInvalidSubdomain;
|
||||
|
||||
/**
|
||||
* The index of the subdomain fragment in the hostname
|
||||
* split by `.`. 0 for first fragment, 1 if you prefix
|
||||
|
|
@ -37,19 +35,27 @@ class InitializeTenancyBySubdomain extends InitializeTenancyByDomain
|
|||
{
|
||||
$subdomain = $this->makeSubdomain($request->getHost());
|
||||
|
||||
// If a non-string, like a Response instance was returned
|
||||
// from makeSubdomain() - due to NotASubDomainException
|
||||
// being thrown, we abort by returning the value now.
|
||||
if (! is_string($subdomain)) {
|
||||
if (is_object($subdomain) && $subdomain instanceof Exception) {
|
||||
$onFail = static::$onFail ?? function ($e) {
|
||||
throw $e;
|
||||
};
|
||||
|
||||
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 $this->initializeTenancy(
|
||||
$request, $next, $subdomain
|
||||
$request,
|
||||
$next,
|
||||
$subdomain
|
||||
);
|
||||
}
|
||||
|
||||
/** @return string|Response|mixed */
|
||||
/** @return string|Response|Exception|mixed */
|
||||
protected function makeSubdomain(string $hostname)
|
||||
{
|
||||
$parts = explode('.', $hostname);
|
||||
|
|
@ -58,15 +64,12 @@ class InitializeTenancyBySubdomain extends InitializeTenancyByDomain
|
|||
$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.
|
||||
$isACentralDomain = in_array($hostname, config('tenancy.central_domains'), true);
|
||||
$notADomain = $isLocalhost || $isIpAddress;
|
||||
$thirdPartyDomain = ! Str::endsWith($hostname, config('tenancy.central_domains'));
|
||||
$thirdPartyDomain = !Str::endsWith($hostname, config('tenancy.central_domains'));
|
||||
|
||||
if ($notADomain || $thirdPartyDomain) {
|
||||
$handle = static::$onInvalidSubdomain ?? function ($e) {
|
||||
throw $e;
|
||||
};
|
||||
|
||||
return $handle(new NotASubdomainException($hostname));
|
||||
if ($isACentralDomain || $notADomain || $thirdPartyDomain) {
|
||||
return new NotASubdomainException($hostname);
|
||||
}
|
||||
|
||||
return $parts[static::$subdomainIndex];
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ class SubdomainTest extends TestCase
|
|||
parent::setUp();
|
||||
|
||||
// Global state cleanup after some tests
|
||||
InitializeTenancyBySubdomain::$onInvalidSubdomain = null;
|
||||
InitializeTenancyBySubdomain::$onFail = null;
|
||||
|
||||
Route::group([
|
||||
'middleware' => InitializeTenancyBySubdomain::class,
|
||||
|
|
@ -88,8 +88,12 @@ class SubdomainTest extends TestCase
|
|||
{
|
||||
// in this case, we need to return a response instance
|
||||
// since a string would be treated as the subdomain
|
||||
InitializeTenancyBySubdomain::$onInvalidSubdomain = function () {
|
||||
return response('foo custom invalid subdomain handler');
|
||||
InitializeTenancyBySubdomain::$onFail = function ($e) {
|
||||
if ($e instanceof NotASubdomainException) {
|
||||
return response('foo custom invalid subdomain handler');
|
||||
}
|
||||
|
||||
throw $e;
|
||||
};
|
||||
|
||||
$this
|
||||
|
|
@ -120,6 +124,28 @@ class SubdomainTest extends TestCase
|
|||
->withoutExceptionHandling()
|
||||
->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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue