fix some bugs
This commit is contained in:
@@ -803,7 +803,8 @@ class ConfigService
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Hostname for WebOTP SMS (@domain #code) and other public links.
|
* Hostname for WebOTP SMS (@domain #code) and other public links.
|
||||||
* Only from the current HTTP request — no settings, no .env.
|
* Prefer settings.app_url (دامنهٔ اپ کاربر) over the API request host —
|
||||||
|
* API often lives on a different subdomain (e.g. *.gholaktala.ir).
|
||||||
*/
|
*/
|
||||||
public function resolvePublicHost(?\Illuminate\Http\Request $request = null): string
|
public function resolvePublicHost(?\Illuminate\Http\Request $request = null): string
|
||||||
{
|
{
|
||||||
@@ -816,9 +817,14 @@ class ConfigService
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Full user-facing site URL, e.g. https://example.ir */
|
/** Full user-facing site URL, e.g. https://example.ir — prefers settings.app_url */
|
||||||
public function resolvePublicSiteUrl(?\Illuminate\Http\Request $request = null): string
|
public function resolvePublicSiteUrl(?\Illuminate\Http\Request $request = null): string
|
||||||
{
|
{
|
||||||
|
$fromAppUrl = $this->normalizedAppUrl();
|
||||||
|
if ($fromAppUrl !== '') {
|
||||||
|
return $fromAppUrl;
|
||||||
|
}
|
||||||
|
|
||||||
if ($request !== null) {
|
if ($request !== null) {
|
||||||
$origin = rtrim(trim((string) $request->getSchemeAndHttpHost()), '/');
|
$origin = rtrim(trim((string) $request->getSchemeAndHttpHost()), '/');
|
||||||
$host = $this->parseHostFromUrl($origin);
|
$host = $this->parseHostFromUrl($origin);
|
||||||
@@ -854,6 +860,11 @@ class ConfigService
|
|||||||
{
|
{
|
||||||
$candidates = [];
|
$candidates = [];
|
||||||
|
|
||||||
|
$appUrlHost = $this->parseHostFromUrl((string) $this->get('app_url', ''));
|
||||||
|
if ($appUrlHost !== '') {
|
||||||
|
$candidates[] = $appUrlHost;
|
||||||
|
}
|
||||||
|
|
||||||
if ($request !== null) {
|
if ($request !== null) {
|
||||||
$candidates[] = trim((string) $request->getHost());
|
$candidates[] = trim((string) $request->getHost());
|
||||||
}
|
}
|
||||||
@@ -865,6 +876,33 @@ class ConfigService
|
|||||||
return $candidates;
|
return $candidates;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** settings.app_url as https://host… without trailing slash; empty if unusable */
|
||||||
|
private function normalizedAppUrl(): string
|
||||||
|
{
|
||||||
|
$raw = trim((string) $this->get('app_url', ''));
|
||||||
|
if ($raw === '') {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! preg_match('#^https?://#i', $raw)) {
|
||||||
|
$raw = 'https://' . ltrim($raw, '/');
|
||||||
|
}
|
||||||
|
|
||||||
|
$host = $this->parseHostFromUrl($raw);
|
||||||
|
if (! $this->isUsableHost($host)) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$scheme = parse_url($raw, PHP_URL_SCHEME) ?: 'https';
|
||||||
|
$port = parse_url($raw, PHP_URL_PORT);
|
||||||
|
$origin = strtolower((string) $scheme) . '://' . $this->normalizeHost($host);
|
||||||
|
if ($port !== null && ! in_array((int) $port, [80, 443], true)) {
|
||||||
|
$origin .= ':' . $port;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $origin;
|
||||||
|
}
|
||||||
|
|
||||||
private function isUsableHost(string $host): bool
|
private function isUsableHost(string $host): bool
|
||||||
{
|
{
|
||||||
$host = strtolower(trim($host));
|
$host = strtolower(trim($host));
|
||||||
|
|||||||
@@ -4,16 +4,38 @@ namespace Tests\Unit;
|
|||||||
|
|
||||||
use App\Services\ConfigService;
|
use App\Services\ConfigService;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
use Mockery;
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
|
|
||||||
class ConfigServiceOtpHostTest extends TestCase
|
class ConfigServiceOtpHostTest extends TestCase
|
||||||
{
|
{
|
||||||
|
protected function tearDown(): void
|
||||||
|
{
|
||||||
|
Mockery::close();
|
||||||
|
parent::tearDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @param mixed $appUrl */
|
||||||
|
private function cfgWithAppUrl($appUrl): ConfigService
|
||||||
|
{
|
||||||
|
$cfg = Mockery::mock(ConfigService::class)->makePartial();
|
||||||
|
$cfg->shouldReceive('get')->andReturnUsing(function (string $key, $default = null) use ($appUrl) {
|
||||||
|
if ($key === 'app_url') {
|
||||||
|
return $appUrl !== null && $appUrl !== '' ? $appUrl : $default;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $default;
|
||||||
|
});
|
||||||
|
|
||||||
|
return $cfg;
|
||||||
|
}
|
||||||
|
|
||||||
public function test_uses_request_host_without_settings(): void
|
public function test_uses_request_host_without_settings(): void
|
||||||
{
|
{
|
||||||
$request = Request::create('https://boursemes.com/server/auth/login', 'POST');
|
$request = Request::create('https://boursemes.com/server/auth/login', 'POST');
|
||||||
$this->app->instance('request', $request);
|
$this->app->instance('request', $request);
|
||||||
|
|
||||||
$host = app(ConfigService::class)->resolvePublicHost($request);
|
$host = $this->cfgWithAppUrl(null)->resolvePublicHost($request);
|
||||||
|
|
||||||
$this->assertSame('boursemes.com', $host);
|
$this->assertSame('boursemes.com', $host);
|
||||||
}
|
}
|
||||||
@@ -22,14 +44,35 @@ class ConfigServiceOtpHostTest extends TestCase
|
|||||||
{
|
{
|
||||||
$request = Request::create('https://boursemes.com/server/auth/login', 'POST');
|
$request = Request::create('https://boursemes.com/server/auth/login', 'POST');
|
||||||
|
|
||||||
$url = app(ConfigService::class)->resolvePublicSiteUrl($request);
|
$url = $this->cfgWithAppUrl(null)->resolvePublicSiteUrl($request);
|
||||||
|
|
||||||
$this->assertSame('https://boursemes.com', $url);
|
$this->assertSame('https://boursemes.com', $url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function test_prefers_app_url_over_api_request_host(): void
|
||||||
|
{
|
||||||
|
$request = Request::create('https://goldarvin.gholaktala.ir/server/customer/order', 'POST');
|
||||||
|
$this->app->instance('request', $request);
|
||||||
|
|
||||||
|
$cfg = $this->cfgWithAppUrl('https://my.goldarvin.ir');
|
||||||
|
|
||||||
|
$this->assertSame('my.goldarvin.ir', $cfg->resolvePublicHost($request));
|
||||||
|
$this->assertSame('https://my.goldarvin.ir', $cfg->resolvePublicSiteUrl($request));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_app_url_without_scheme_gets_https(): void
|
||||||
|
{
|
||||||
|
$request = Request::create('https://goldarvin.gholaktala.ir/server/auth/login', 'POST');
|
||||||
|
|
||||||
|
$this->assertSame(
|
||||||
|
'https://my.goldarvin.ir',
|
||||||
|
$this->cfgWithAppUrl('my.goldarvin.ir')->resolvePublicSiteUrl($request)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public function test_returns_empty_without_request(): void
|
public function test_returns_empty_without_request(): void
|
||||||
{
|
{
|
||||||
$host = app(ConfigService::class)->resolvePublicHost();
|
$host = $this->cfgWithAppUrl(null)->resolvePublicHost();
|
||||||
|
|
||||||
$this->assertSame('', $host);
|
$this->assertSame('', $host);
|
||||||
}
|
}
|
||||||
@@ -38,7 +81,7 @@ class ConfigServiceOtpHostTest extends TestCase
|
|||||||
{
|
{
|
||||||
$request = Request::create('https://www.boursemes.com/server/auth/login', 'POST');
|
$request = Request::create('https://www.boursemes.com/server/auth/login', 'POST');
|
||||||
|
|
||||||
$host = app(ConfigService::class)->resolvePublicHost($request);
|
$host = $this->cfgWithAppUrl(null)->resolvePublicHost($request);
|
||||||
|
|
||||||
$this->assertSame('boursemes.com', $host);
|
$this->assertSame('boursemes.com', $host);
|
||||||
}
|
}
|
||||||
@@ -48,7 +91,7 @@ class ConfigServiceOtpHostTest extends TestCase
|
|||||||
$request = Request::create('http://localhost/server/auth/login', 'POST');
|
$request = Request::create('http://localhost/server/auth/login', 'POST');
|
||||||
$this->app->instance('request', $request);
|
$this->app->instance('request', $request);
|
||||||
|
|
||||||
$host = app(ConfigService::class)->resolvePublicHost($request);
|
$host = $this->cfgWithAppUrl(null)->resolvePublicHost($request);
|
||||||
|
|
||||||
$this->assertSame('', $host);
|
$this->assertSame('', $host);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user