Zákaz použití určité routy
- gizer
- Člen | 67
Dobrý den,
chtěl jsem se zeptat na možnost zakázat konkrétní routu. V aplikaci
jsem upravil https pro webhosting Endora a vše asi dobře funguje.
V některých případech se však zobrazuje URL jako https://nazevdomeny.cz a nebo
také jako https://nazevdomeny.cz/www
Ptám se, možná hloupě, jestli je možné https://nazevdomeny.cz/www
zakázat a jak?
Děkuji moc za odpověď.
- Pavel Kravčík
- Člen | 1196
Pravděpodobně mluvíš o hostingu, budou mít KB, kde bude nějaké info
o nastavení root složky. Tam budou nejpřesnější informace. Často si to
můžeš sám nastavovat pomocí .htaccess
. (např. stackoverflow, KB wedos)
Editoval Pavel Kravčík (4. 1. 2023 8:27)
- gizer
- Člen | 67
Pro úplnost uvádím. V root složce projektu (tedy nad app, www atd.) je nutné vytvořit .htaccess zajišťující přesměrování požadavků do www/
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^$ www/ [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^/www/
RewriteRule ^(.*)$ www/$1
</IfModule>
Soubor .htaccess pro přesměrování z http:// na https://
# use HTTPS
RewriteCond %{HTTPS} !on
RewriteCond %{HTTP:X-Forwarded-Proto} !^https$
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,NE,L]
RewriteRule .? https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
Takže tak to mám nastavené v obou .htaccess
Editoval gizer (4. 1. 2023 9:16)
- David Grudl
- Nette Core | 8239
Je potřeba na to nastavit hosting, viz https://doc.nette.org/…ubleshooting#…
- gizer
- Člen | 67
Tak to na Endoře asi nenastavím. Posílám pro informaci, co radí ohledně instalace nette jejich podpora.
https://www.endora.cz/…na-endora-cz
Radí tam „Ve všech adresářích kromě www vytvořte .htaccess, který
zamezí zobrazení souborů“. Ale každopádně děkuji moc za radu.
Dám ještě dotaz na jejich podporu, jestli to přece jenom nějak
nepůjde.
- David Grudl
- Nette Core | 8239
Vypadá to že ne. To je dost tristní omezení, pokud se nedohodneš s podporou, běž určitě jinam.
- m.brecher
- Generous Backer | 873
@gizer
To co popisuješ je duplicita url adres a tu je ideální řešit vhodným přesměrováním na kanonickou url adresu (nikoliv zákazem). Bohužel tohle je mimo možnosti Nette Routeru, který jinak skvěle kanonizuje a tak si to člověk musí nějak udělat sám.
Já jsem odstranění www z url adresy a to jak na testovací mašině s Apache a Windows tak i na webhostingu s Apache a Linuxem vyřešil takto. Mám dva soubory .htaccess, které interně přesměrují url bez www na url s www a utilitku v BasePresenteru, která případná http request na duplicitní url obsahující nechtěné /www/ přesměruje na kanonickou url bez www:
/.htaccess
Require all granted
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} ^localhost$
RewriteRule (.*) /project-folder/www/$1
RewriteCond %{HTTP_HOST} !^localhost$
RewriteRule (.*) /www/$1
/www/.htaccess
Require all granted
<IfModule mod_autoindex.c>
Options -Indexes
</IfModule>
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} !^localhost$
RewriteCond %{HTTPS} !on
RewriteRule .? https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule /\.|^\.(?!well-known/) - [F]
RewriteCond %{HTTP_HOST} ^localhost$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule !\.(pdf|js|mjs|ico|gif|jpg|jpeg|png|webp|svg|css|rar|zip|7z|tar\.gz|map|eot|ttf|otf|woff|woff2)$ /project-folder/index.php [L]
RewriteCond %{HTTP_HOST} !^localhost$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule !\.(pdf|js|mjs|ico|gif|jpg|jpeg|png|webp|svg|css|rar|zip|7z|tar\.gz|map|eot|ttf|otf|woff|woff2)$ index.php [L]
</IfModule>
<IfModule mod_deflate.c>
<IfModule mod_filter.c>
AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css application/javascript application/json application/xml image/svg+xml
</IfModule>
</IfModule>
Utilitka pro přesměrování na kanonickou adresu
namespace App\Utils;
final class Utils
{
public string $wwwDir;
public function __construct(private Request $httpRequest)
{}
public function getCanonUrl($redirectLocal = false): array
{
$basePath = $this->httpRequest->getUrl()->getBasePath();
if(str_ends_with($basePath, '/')){
$basePath = substr($basePath, 0, strlen($basePath) - 1);
}
if($_SERVER['HTTP_HOST'] === 'localhost'){
$httpCode = 302;
$wwwDirAbs = str_replace('\\', '/', $this->wwwDir ); // normalize windows -> linux
$wwwDir = substr($wwwDirAbs, strrpos($wwwDirAbs, '/')); // gets real wwwDir (/www)
$docRoot = $_SERVER['DOCUMENT_ROOT'];
$baseDirAbs = $docRoot.$basePath;
$needsCanonize = $redirectLocal && $baseDirAbs === $wwwDirAbs;
if($needsCanonize){
$wwwPath = str_starts_with($wwwDirAbs, $docRoot) ? substr($wwwDirAbs, strlen($docRoot)) : $wwwDirAbs;
$newBasePath = substr($basePath, 0, strlen($basePath) - strlen($wwwDir));
$url = $this->httpRequest->getUrl();
$path = $url->getPath();
$newPath = str_starts_with($path, $wwwPath) ? substr($path, strlen($wwwPath)) : $path;
$newPath = $newBasePath.$newPath;
$newUrl = new Url($url->__toString());
$newUrl->setPath($newPath);
return [$newUrl->__toString(), $httpCode];
}
}else{
$httpCode = 301; // 301 must be from seo reasons, 302 just temporarily short time period
$wwwDirAbs = $this->wwwDir; // server expect linux
$wwwDir = substr($wwwDirAbs, strrpos($wwwDirAbs, '/')); // gets real wwwDir (/www)
$needsCanonize = $basePath === $wwwDir;
if($needsCanonize){
$newBasePath = '';
$url = $this->httpRequest->getUrl();
$path = $url->getPath();
$newPath = str_starts_with($path, $wwwDir) ? substr($path, strlen($wwwDir)) : $path;
$newPath = $newBasePath.$newPath;
$newUrl = new Url($url->__toString());
$newUrl->setPath($newPath);
return [$newUrl->__toString(), $httpCode];
}
}
return [null, null];
}
}
Nasazení kanonizační utilitky v BasePresenteru
abstract class BasePresenter extends Presenter
{
#[Inject]
public Utils $utils;
.......
public function startup()
{
parent::startup();
[$canonicalUrl, $httpCode] = $this->utils->getCanonUrl(redirectLocal: true);
if($canonicalUrl){
$this->redirectUrl($canonicalUrl, $httpCode); // fix doc_root duplicity
}
}
.......
}
Při psaní kódu .htaccess jsem narazil na problém, že Apache pro Windows neuměl co by podle dokumentace umět měl a tak se mě nepodařilo napsat kód pro Apache nezávisle na složce projektu na vývojové mašině – v každém projektu se proto musí ručně dopsat do .htaccess konkrétní hodnota /project-folder/ jak je na vývojové mašině.
Pozor na http kód přesměrování kvůli ladění – na produkčním serveru by mělo být 301, ale při ladění dej 302, aby prohlížeč přesměrování necachoval a šlo to otestovat.
Je to bohužel takové těžkopádné řešení, ale problém s ošklivým www v url to řeší. Asi to řeší většinu českých hostingů, protože dnes už hostingové agentury na konfiguraci docroot kašlou a člověk si to musí zmatlat sám v .htaccess.
Budu vděčný i za kritické poznámky k mému řešení a případná vylepšení.
EDIT
Ještě jsem zapomněl, že je potřeba předat wwwDir do utilitky v konfiguraci Nette:
/config/common.neon
decorator:
App\Utils\Utils:
setup:
- $wwwDir = %wwwDir%
Editoval m.brecher (5. 1. 2023 17:18)
- gizer
- Člen | 67
Děkuji za návrh řešení. Připadá mně ale trochu komplikovaný.
ŘEŠENÍ
Vyřešil jsem to jednodušeji změnou webhostingu. Přešel jsem na webglobe,
kde jsem nahrál celý web do jejich root adresáře a následně si od správce
hostingu nechal nastavit www adresář jako veřejný. A problém s www
zmizel.
Editoval gizer (14. 1. 2023 10:47)
- David Grudl
- Nette Core | 8239
@mbrecher Ve chvíli, kdy hosting neumožňuje „jít nad“ veřejný adresář, tak je jediná možnost jej změnit.
To je jako bydlet v bytě, kde nejdou zavřít vstupní dveře a jsou stále dokořán. Jasně, můžeš to nějak kosmeticky řešit, dát tam třeba závěs, nebo cedulku „tohle je soukromý byt, nevstupujte“, a naivně doufat, že lidé to budou respektovat. Ale to prostě nechceš.
- m.brecher
- Generous Backer | 873
@DavidGrudl
Souhlasím, ale je to webhosting Jirky Zralého, kde jsem už minimálně 17 let a po tolika letech odejít to je skoro jako rozvod :).
Máš nějaké solidní informace, že by toto interní přesměrování Apache šlo nějak obejít?
Require all granted
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} ^localhost$
RewriteRule (.*) /project-folder/www/$1
RewriteCond %{HTTP_HOST} !^localhost$
RewriteRule (.*) /www/$1
- m.brecher
- Generous Backer | 873
@gizer
Děkuji za návrh řešení. Připadá mně ale trochu komplikovaný.
Ano, hlavně to přesměrování je příliš složité. Zjednodušil jsem utilitku pro přesměrování:
final class Utils
{
public string $wwwDir;
public string $wwwSubdir;
public function __construct(private Request $httpRequest)
{}
public function getCanonicalUrl(): array
{
$realHomePath = $this->httpRequest->getUrl()->getBasePath(); // expecting that (incorrectly) ends with /
$canonize = str_ends_with($realHomePath, $this->wwwSubdir.'/');
if($canonize){
$newHomePath = substr($realHomePath, 0, strlen($realHomePath) - strlen($this->wwwSubdir));
$newUrl = new Url($this->httpRequest->getUrl()->__toString());
$newUrl->setPath($newHomePath);
$httpCode = $_SERVER['HTTP_HOST'] === 'localhost' ? 302 : 301;
return [$newUrl->__toString(), $httpCode];
}else{
return [null, null];
}
}
}
/config/common.neon:
parameters:
wwwSubdir: '/www'
decorator:
App\Utils\Utils:
setup:
- $wwwDir = %wwwDir%
- $wwwSubdir = %wwwSubdir%
Editoval m.brecher (14. 1. 2023 16:42)
- David Grudl
- Nette Core | 8239
Můžeš si omylem smazat .htaccess, udělat v něm chybu, může ti vypadnout internet zrovna při nahrávání nové verze tohoto souboru atd. Riziko díry do celého webu nesmí přece záviset na takové věci.
Není lepší napsat Jirkovi?