- Add TunnelRegistry (var/magesail_tunnels.json) and TunnelProcessPaths; migrate legacy magesail_tunnel_store.json and PID/key files - Provision unique store codes per tunnel; website/group selection; stop vs remove; per-tunnel NGINX map, cron, status/logtail - Fix log path: use DirectoryList::LOG (not LOG_DIR) - Ignore missing store codes for MAGE_RUN_* (stale nginx / magesail_tunnel) - Allow duplicate local ports; Admin port presets 443/80/8080 + custom; update docs and system.xml comments
94 lines
3.3 KiB
PHP
94 lines
3.3 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
namespace MageSail\Magesail\Plugin\App\Request;
|
|
|
|
use Magento\Framework\App\Request\Http;
|
|
use Magento\Framework\Exception\NoSuchEntityException;
|
|
use Magento\Store\Api\StoreRepositoryInterface;
|
|
use Magento\Store\Model\ScopeInterface;
|
|
use Magento\Store\Model\StoreManager;
|
|
use MageSail\Magesail\Model\AdminPathDetector;
|
|
use MageSail\Magesail\Model\TunnelRequestDetector;
|
|
|
|
/**
|
|
* When request has X-MageSail-Store-Code header or magesail_store query param (from tunnel proxy),
|
|
* make getServerValue return it for MAGE_RUN_CODE and 'store' for MAGE_RUN_TYPE so Magento serves that store.
|
|
*
|
|
* Admin URLs must not use nginx tunnel map values: StoreResolver is built from MAGE_RUN_* init params; if they
|
|
* stay as the tunnel store, admin can 404. For admin paths we force website scope and empty run code so the
|
|
* default website is used (same as a normal request without per-host map).
|
|
*
|
|
* If NGINX still injects a removed store code (e.g. legacy magesail_tunnel), strip it so StoreResolver
|
|
* falls back instead of throwing NoSuchEntityException (including on error pages).
|
|
*/
|
|
class StoreFromMageSailHeaderPlugin
|
|
{
|
|
public function __construct(
|
|
private readonly AdminPathDetector $adminPathDetector,
|
|
private readonly TunnelRequestDetector $tunnelRequestDetector,
|
|
private readonly StoreRepositoryInterface $storeRepository
|
|
) {
|
|
}
|
|
|
|
/**
|
|
* Around getServerValue: if MageSail store header is set, return it for MAGE_RUN_CODE / MAGE_RUN_TYPE.
|
|
*
|
|
* @param Http $subject
|
|
* @param callable $proceed
|
|
* @param string|null $name
|
|
* @param mixed $default
|
|
* @return mixed
|
|
*/
|
|
public function aroundGetServerValue(Http $subject, callable $proceed, $name = null, $default = null)
|
|
{
|
|
if ($this->adminPathDetector->isAdminPath($subject)) {
|
|
if ($name === StoreManager::PARAM_RUN_TYPE) {
|
|
return ScopeInterface::SCOPE_WEBSITE;
|
|
}
|
|
if ($name === StoreManager::PARAM_RUN_CODE) {
|
|
return '';
|
|
}
|
|
return $proceed($name, $default);
|
|
}
|
|
|
|
$tunnelCode = $this->tunnelRequestDetector->getTunnelStoreCode($subject);
|
|
$nginxCode = trim((string) $subject->getServer(StoreManager::PARAM_RUN_CODE));
|
|
$candidate = ($tunnelCode !== null && $tunnelCode !== '')
|
|
? $tunnelCode
|
|
: $nginxCode;
|
|
|
|
if ($candidate !== '' && !$this->storeCodeExists($candidate)) {
|
|
if ($name === StoreManager::PARAM_RUN_CODE) {
|
|
return '';
|
|
}
|
|
if ($name === StoreManager::PARAM_RUN_TYPE) {
|
|
return ScopeInterface::SCOPE_WEBSITE;
|
|
}
|
|
return $proceed($name, $default);
|
|
}
|
|
|
|
if ($tunnelCode !== null && $tunnelCode !== '') {
|
|
if ($name === StoreManager::PARAM_RUN_CODE) {
|
|
return $tunnelCode;
|
|
}
|
|
if ($name === StoreManager::PARAM_RUN_TYPE) {
|
|
return 'store';
|
|
}
|
|
return $proceed($name, $default);
|
|
}
|
|
|
|
return $proceed($name, $default);
|
|
}
|
|
|
|
private function storeCodeExists(string $code): bool
|
|
{
|
|
try {
|
|
$this->storeRepository->get($code);
|
|
return true;
|
|
} catch (NoSuchEntityException) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|