Zákaz použití určité routy

gizer
Člen | 67
+
0
-

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 | 1180
+
0
-

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
+
0
-

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 | 8082
+
+1
-

Je potřeba na to nastavit hosting, viz https://doc.nette.org/…ubleshooting#…

gizer
Člen | 67
+
0
-

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 | 8082
+
+4
-

Vypadá to že ne. To je dost tristní omezení, pokud se nedohodneš s podporou, běž určitě jinam.

gizer
Člen | 67
+
0
-

Díky Davide. Takže podpora poradila buď úpravy v .htaccess nebo jiný webhosting :-(

Editoval gizer (5. 1. 2023 13:40)

netteman
Člen | 122
+
0
-

Stejný problém jsem měl kdysi na Wedosu. Přešel jsem na jiný hosting, kde si můžu root složku nastavit v administraci hostingu, a hned bylo o starost míň.

m.brecher
Generous Backer | 715
+
0
-

@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
+
0
-

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 | 8082
+
0
-

@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 | 715
+
0
-

@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 | 715
+
0
-

@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 | 8082
+
+1
-

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?

m.brecher
Generous Backer | 715
+
0
-

@DavidGrudl

Máš pravdu, ani mě se nelíbí, když klíčová věc pro bezpečnost visí na tom, že se nesmí/musí nahrát nějaký soubor.