Flash zprávičky bez _fid v URL
- Ondřej Mirtes
- Člen | 1536
Ahoj,
došli jsme v práci k závěru, že přidávání _fid parametru do URL je
ošklivá vlastnost Nette a způsobuje to problémy – generuje to duplicity
pro vyhledávače a znepřehledňuje statistiky. Udělali jsme tedy nový
namespace a do něj bez jakéhokoli idenfitikátoru ukládáme rovnou ty flash
zprávičky.
Překrývající metody v BasePresenteru:
public function hasFlashSession()
{
return $this->getSession()
->hasNamespace('Medio.Application.Flash');
}
public function getFlashSession()
{
return $this->getSession('Medio.Application.Flash');
}
A namísto nastavování nějaké expirace (jak to probíhá v Presenter::run()) promazáváme session objekt těsně po vytvoření a naplnění šablony (kdy si jsme de facto jisti, že dojde k vykreslení stránky, potažmo flash zprávičky):
protected function createTemplate()
{
$template = parent::createTemplate();
// renderer flash messages deleting
if ($this->hasFlashSession()) {
unset($this->getFlashSession()->{$this->getParamId('flash')});
}
return $template;
}
Neušili jsme si tím na sebe nějakou boudu? Proč to takhle nefunguje v Nette?
Jediné dva případy, co mě napadají, kdy může nastat nějaký zádrhel:
- Programátor nenásleduje best practices a plní šablonu v action*
metodě: Při prvním volání $this->template->cokoli se zavolá
createTemplate(), jenže po action* metodě může nastat nějaký redirect
v handle fázi. V tu chvíli se flash zprávička ztratí a nikdy se
nezobrazí.
- Z našeho hlediska to nepovažuji za problém, protože programátory, kteří plní šablonu v action*, mlátíme přes prsty :))
- Uživatel nějakým způsobem dokáže zobrazit dva requesty v ± stejnou
chvíli a tehdy se může stát, že se mu zobrazí flash zprávička v jiném,
nesouvisejícím tabu prohlížeče.
- Nenapadá mě, kdy by to mohlo v praxi nastat, maximálně na nějakém pomalém připojení.
Brání něco tomu, aby se tento fix dostal do Nette, zamezuje předávání _fid v URL nějakým dalším problémům, které si neuvědomujeme? Díky.
- redhead
- Člen | 1313
Podle mě tím důvodem byl bod 2).
A podle mě to takhle kdysi dávno i bylo, ale právě kvůli tomu bodu 2 se to přenáší v URL. Navíc se mi nezdá, že to by to mělo mást vyhledávače. Já teda dávám flashmessages po nějaké velké akci, jako smazání příspěvku nebo odeslání formuláře. A v tom si myslím, že problém pro vyhledávače není, nebo jo?
Ale víc ti řekne někdo zkušenější..
- Ondřej Mirtes
- Člen | 1536
Sice dáváš flash message po akci, co mění server, ale tu URL s _fid můžeš třeba nevědomky použít jako nějaký zpětný odkaz a může se začít šířit – a duplicita je na světě.
- Honza Marek
- Člen | 1664
Ondřej Mirtes napsal(a):
Ahoj,
došli jsme v práci k závěru, že přidávání _fid parametru do URL je ošklivá vlastnost Nette a způsobuje to problémy – generuje to duplicity pro vyhledávače a znepřehledňuje statistiky.
Tady souhlas.
Programátor nenásleduje best practices a plní šablonu v action* metodě: Při prvním volání $this->template->cokoli se zavolá createTemplate(), jenže po action* metodě může nastat nějaký redirect v handle fázi. V tu chvíli se flash zprávička ztratí a nikdy se nezobrazí.
IMHO to problém je a represe v podobě rozmlácených programátorských rukou tomu nepomůže :) Přece když vydoluju něco z modelu a chci to použít jak na rozhodnutí o přesměrování, tak v šabloně, tak to nebudu sosat zbytečně ve dvou metodách.
- Jan Tvrdík
- Nette guru | 2595
Doplním: Starší, ale předpokládám stále platné vysvětlení od Davida.
Jak vznikají ty duplicity pro vyhledávače? Používám to akorát po odeslání formuláře a roboti, pokud vím, formuláře neodesílají. Dobrý analytický systém by měl umět vybrané parametry ignorovat.
- Honza Kuchař
- Člen | 1662
Podle mě:
- Nechat _fid v url z výše uvedeného důvodu.
- Pokud _fid nebude při dotazu nalezeno v session a zároveň to nebude POST požadavek, tak bych to přesměroval na adresu bez _fid. Tím se vyřeší problém s vyhledávači.
- Honza Kuchař
- Člen | 1662
Yrwein napsal(a):
Honza Kuchař napsal(a):
- Pokud _fid nebude při dotazu nalezeno v session a zároveň to nebude POST požadavek, tak bych to přesměroval na adresu bez _fid. Tím se vyřeší problém s vyhledávači.
→ Nevznikne tak problém při akci s GET?
Proč myslíš? Nějak nevidím, kde by mohl být problém. Píšu tam, pokud už to v session není, tzn. po uplynutí těch tří sekund. Tzn. i pokud se to _fid dostane do nějakého odkazu, budeš třistajedničkou přesměrován na adresu bez _fid → je prakticky nulová možnost, že by se to zaindexovalo, musel by se tam dostat robot do těch tří sekund od odeslání flash zprávičky.
- PetrP
- Člen | 587
Odstraněním fid z url není dobře.
Víče requestů najednou může vznikat poměrně často.
V createTemplate odstraníte zprávy z session takže když omylem během vykreslovaní refreshnu tak message ztratím.
Lepší je řešit zkutečnej problém a to jsou duplicity. Takže jak tady píšou jiný kdyz fid v session neexistuje tak kanonizovat url. Podle mě by se o to měl postarat už framework.
- Honza Marek
- Člen | 1664
Přiznejte se, kdo odesíláte ve dvou tabech dva formuláře naráz? Já jsem to teda ještě nikdy neudělal. Naprosto nechápu proč bych to měl, natožpak často.
I když je pravda, že _fid si v adrese těžko vyrobí sám vyhledávač, snadno se taková adresa může zveřejnit, pokud ji někam zkopíruje sám uživatel.
- mlady
- Člen | 24
Honza Marek napsal(a):
Přiznejte se, kdo odesíláte ve dvou tabech dva formuláře naráz? Já jsem to teda ještě nikdy neudělal. Naprosto nechápu proč bych to měl, natožpak často.
Napríklad v administrácií domén active24 som si v taboch otvoril niekoľko formulárov na pridanie záznamov a potom som ich postupne posielal. Ak by mi to nefungovalo, dosť by mi to vadilo.
- Ondřej Brejla
- Člen | 746
Ať tak, či tak, nejlepší by asi bylo, pokud by šlo stávající
(bezpečné) chování vypnout a tím zapnout chování „nebezpečné“, tedy
bez _fid
v url. Jako s escapováním v šabloně…default
bezpečné a escapované, po vypnutí „nebezpečné“ a
neescapované ;-)
- Honza Marek
- Člen | 1664
mlady napsal(a):
Napríklad v administrácií domén active24 som si v taboch otvoril niekoľko formulárov na pridanie záznamov a potom som ich postupne posielal. Ak by mi to nefungovalo, dosť by mi to vadilo.
Vidíš, dělal jsi to postupně. Čili ne najednou :)
- Ondřej Mirtes
- Člen | 1536
Že se zobrazí flash zprávička v jiném tabu, než může, je pořád hodně nepravděpodobné. Návštěvník by se musel strefit načítáním webu ve druhém tabu do momentu, který tady zkusím rozepsat (na posloupnosti zpracování prvního tabu):
- Vyplňuji formulář
- Klikám na submit
- Formulář se odesílá (upload hodnot a souborů na server)
- Formulář se zpracovává na serveru, ukládá do databáze, provádí se cokoli, co je třeba
- Až do tohoto momentu se v ostatních tabech webu nemůže zobrazit žádná flash zprávička.
- Nastavení flash zprávičky
- Nyní je ta riziková část, kdy je v session nastavená flash zprávička a tudíž se může vykreslit na kterémkoli tabu webu.
- Redirect.
- Čekání na odezvu serveru.
- Na serveru se spouští Presenter a za chvíli se volá createTemplate, který flash zprávičku odstraní.
- Končí riziková část, nyní se flash zprávička zobrazí, pokud ji neukradl jiný tab.
Takže jde o to, trefit se do toho redirectu a čekání na odezvu serveru. A neumím si představit, že bych se do toho trefil, leda, že by server měl na tu odezvu na redirect velký timeout anebo bych byl na pomalém připojení. Ale zase když jsem na pomalém připojení, tak ty další otevřený taby se vykreslí ještě později, než ten první po redirectu.
- Honza Kuchař
- Člen | 1662
Ale podle mě je uživatelovi úplně jedno co je v url. //EDIT: Jde o vyhledávače.
Editoval Honza Kuchař (21. 5. 2010 15:41)
- Honza Kuchař
- Člen | 1662
PetrP napsal(a):
Odstraněním fid z url není dobře.
Víče requestů najednou může vznikat poměrně často.
V createTemplate odstraníte zprávy z session takže když omylem během vykreslovaní refreshnu tak message ztratím.
Lepší je řešit zkutečnej problém a to jsou duplicity. Takže jak tady píšou jiný kdyz fid v session neexistuje tak kanonizovat url. Podle mě by se o to měl postarat už framework.
100% souhlasím.
- veena
- Člen | 98
Ondřej Mirtes napsal(a):
Že se zobrazí flash zprávička v jiném tabu, než může, je pořád hodně nepravděpodobné. Návštěvník by se musel strefit načítáním webu ve druhém tabu do momentu, který tady zkusím rozepsat (na posloupnosti zpracování prvního tabu):
- Vyplňuji formulář
- Klikám na submit
- Formulář se odesílá (upload hodnot a souborů na server)
- Formulář se zpracovává na serveru, ukládá do databáze, provádí se cokoli, co je třeba
- Až do tohoto momentu se v ostatních tabech webu nemůže zobrazit žádná flash zprávička.
- Nastavení flash zprávičky
- Nyní je ta riziková část, kdy je v session nastavená flash zprávička a tudíž se může vykreslit na kterémkoli tabu webu.
- Redirect.
- Čekání na odezvu serveru.
- Na serveru se spouští Presenter a za chvíli se volá createTemplate, který flash zprávičku odstraní.
- Končí riziková část, nyní se flash zprávička zobrazí, pokud ji neukradl jiný tab.
Takže jde o to, trefit se do toho redirectu a čekání na odezvu serveru. A neumím si představit, že bych se do toho trefil, leda, že by server měl na tu odezvu na redirect velký timeout anebo bych byl na pomalém připojení. Ale zase když jsem na pomalém připojení, tak ty další otevřený taby se vykreslí ještě později, než ten první po redirectu.
Mě se to stávalo pravidelně. Ne sice na Nette ale v administraci Django. Server v Americe, ping cca 170ms.
- mlady
- Člen | 24
Honza Marek napsal(a):
Vidíš, dělal jsi to postupně. Čili ne najednou :)
Ako sa to vezme. Pri pomalšom pripojení by to mohlo byť „naraz“. V práci s tým občas problémy máme. Okrem toho „flash zprávičky“ sa môžu využívať aj mimo formulárov. Alebo nie? Súhlasím s príspevkami vyššie, že je potrebné vyriešiť duplicitu a nie formát URL.
- David Grudl
- Nette Core | 8227
_fid v žádném případě rušit nebudu, být teď v Simpsonových, pustili by instruktážní video s Troy McClurem (možná si ho pamatujete ze snímků jako Malomocný za čárou, Dnes zabij a zítra zemři, Mami co to ten pán má s obličejem, nebo Maso a My).
Přesměrování při neexistujícím _fid: měl jsem za to, že to tam dávno je :-) Podívám se.
- David Grudl
- Nette Core | 8227
Honza Kuchař napsal(a):
Podle mě:
- Pokud _fid nebude při dotazu nalezeno v session a zároveň to nebude POST požadavek, tak bych to přesměroval na adresu bez _fid. Tím se vyřeší problém s vyhledávači.
Po přesměrování to zcela jistě nebude POST požadavek.
- Honza Kuchař
- Člen | 1662
Pokud to bude POST, tak nepřesměrovávat! Přesměrovávat pouze, pokud je to GET a už _fid není v SESSION. Tzn. vyhledáváč se dostanen na kanonikalizovanou url.
EDIT:
Přesměrování při neexistujícím _fid: měl jsem za to, že to tam dávno je :-) Podívám se.
Opravdu je to tak: https://componette.org/search/?…
Editoval Honza Kuchař (21. 5. 2010 21:09)
- Honza Kuchař
- Člen | 1662
Přemýšlím, jak udělat tu identifikaci okna nějak obecně. Taková vlastnost by byla naprosto klíčová při tvorbě live-aplikací. Ale nenapadá mě žádné obecné řešení, aby to bylo zároveň bez duplicitních stránek. //EDIT: Facebook to musí určitě taky nějak řešit.
Editoval Honza Kuchař (21. 5. 2010 21:10)
- ic
- Člen | 430
Možná by bylo dobře při adrese s ?fid=XXX
přidat taky
rel="canonical"
s odkazem na verzi bez _fid
aby
vyhledávač (alespoň google, nevím jak jsou na tom ostatní) věděl
o kterou stránku se má zajímat… teoreticky by tohle mohly pochopit
i prohlížeče… že web.cz/stranka/?fid=XXX
je to samé jako
web.cz/stranka/
a zobrazit ji jako už navštívenou, pokud by na
první adrese našly canonical směřující právě na tu druhou, ale to už je
v kompetencích někoho jiného.
- JakubJarabica
- Gold Partner | 184
K čomu sa teda dospelo? Bude Nette natívne podporovať 301 na kanonickú verziu v prípade, že flash session bude prázdna? Najviac sa mi ľúbi riešenie v tomto poste: p32806, avšak neviem si predstaviť, kde už v tej fázi začať plniť šablónu nejakou kanonickou URL v prípade výpisu flashMessage a taktiež kde presmerovávať v prípade prázdnej session.
- JakubJarabica
- Gold Partner | 184
Vďaka, narval som to do startupu BasePresenteru a funguje to. Ešte nejako efektívne vymyslieť link rel=„canonical“ a bude to dokonalé :)
Edit:
Tak ešte som pridal do redirectu ako prvý parameter 301tku, pre prípad, keď
nejaký používateľ skopíruje link s _fid a prilinkuje.
Editoval JAM3SoN (5. 6. 2010 15:52)
- Majkl578
- Moderator | 1364
Pushl jsem tu automatickou kanonizaci na github (upraveno 30.6. na základě doporučení Honzy Tvrdíka) a poslal pull request.
Editoval Majkl578 (30. 6. 2010 3:41)
- ic
- Člen | 430
Majkl578 napsal(a):
Pushl jsem tu automatickou kanonizaci na github a poslal pull request.
doufám že to dopadne XD
- ic
- Člen | 430
V návaznosti na tento tweet http://twitter.com/…425037574145 a hlavně na jeho
odpovědi mě napadlo že by možná šlo ty ?_fid=XXXX
skrýt
odebráním z URI adresy javascriptem. A vono jo!
tohle
if(window.history.replaceState){l=window.location.toString();u=l.indexOf('_fid=');if(u!=-1){u=l.substr(0,u)+l.substr(u+10);if(u.substr(u.length-1)=='?'||u.substr(u.length-1)=='&')u=u.substr(0,u.length-1);window.history.replaceState('',document.title,u)}}
nebo čitelněji tohle:
if(window.history.replaceState) {
l = window.location.toString();
uri = l.indexOf('_fid=');
if(uri != -1) {
uri = l.substr(0, uri)+l.substr(uri+10);
if( (uri.substr(uri.length-1) == '?') || (uri.substr(uri.length-1) == '&') ) {
uri = uri.substr(0, uri.length-1);
}
window.history.replaceState('', document.title, uri);
}
}
k tomu dopomůže… podle working draft html5 ( http://dev.w3.org/…history.html#… ) by to v budoucnu mělo fungovat. Zatím to funguje pouze na Chrome 7 , jinde to sice nedělá nic, ale snad neuškodí.
EDIT: Skutečná adresa tam na několik málo ms problikne, záleží podle toho jak rychle se script vykoná, takže je nejlepší ho umístit na začátek head. V kombinaci s řešeními z předchozích příspěvků se dá taky tento javascript vkládat jen do stránek s aktivní flash zprávičkou.
Editoval ic (10. 11. 2010 20:42)
- romiix.org
- Člen | 343
Nemalo by toto riešiť samotné Nette?
Majkl578 napsal(a):
Já prozatím řeším kanonizaci při neexistující zprávičce takto:
//Presenter::startup() if (!$this->hasFlashSession() && !empty($this->params[self::FLASH_KEY])) { unset($this->params[self::FLASH_KEY]); $this->redirect('this'); }
- mcmatak
- Člen | 504
Mohl by mi někdo vysvětlit ty duplicity?
Resp.
- různá url (včetně _fid), stejný obsah = špatně,
- stejná url, různý obsah = super cool,
tak to bychom měli, to víme.
Kde jsou ty duplicity? Resp. jak se vyhledávač dostane na _fid? Vy třeba kliknutím na detail článku z výpisu článku oznamujete uživateli pomocí flashmsg že se dostal na detail článku?
Určitě znáte Czechcomputer tam, když se stane nějaká akce tak jste o tom informování textem na bílém pozadí uprostřed obrazovky, což je alternativa k flashmsg, nebylo by rozumnější vyhledávači zakázat indexovat tuto stránku?
- Majkl578
- Moderator | 1364
mcmatak napsal(a):
Kde jsou ty duplicity? Resp. jak se vyhledávač dostane na _fid?
- Uživatel A napíše do diskuze, příspěvek se přidá a uživatel je přesměrován na výpis diskuze (s flash zprávičkou o přidání).
- Uživatel A veme odkaz z adresového řádku prohlížeče a postne ho někam jinam, třeba na blog.
- Uživatel B udělá totéž co uživatel A.
- Uživatel C udělá totéž co uživatelé A a B.
Voila! Máme tu 3 duplicity. A zrovna tenhle příklad mi nepřijde nereálný.
- David Grudl
- Nette Core | 8227
romiix.org napsal(a):
Nemalo by toto riešiť samotné Nette?
Je to v plánu
- Dr.Diesel
- Člen | 53
Nette pokud vim v pripade pouziti fid parametru nema jednorazovou povahu, ale ma to expiraci na par sekund (1 nebo vic, ted z hlavy nevim). Prave kvuli ruznym presmerovani nebo (nepravdepodobne) refreshi uzivatele kratce po zobrazeni stranky (1s?)
Ondrovo reseni toto ztrati a zobrazeni ma jednorazovou povahu, jestli se nemylim.
Editoval Dr.Diesel (8. 12. 2010 10:50)
- JakubJarabica
- Gold Partner | 184
Tak práve som to akútnejšie riešil v jednom projekte a skončil som
s týmto:
BasePresenter.php
<?php
// kód myslím, že od Majkla, ktorý po refreshi odstráni _fid z URL
if (!$this->hasFlashSession() && !empty($this->params[self::FLASH_KEY])) {
unset($this->params[self::FLASH_KEY]);
$this->redirect(301, 'this');
}
?>
FrontModule\BasePresenter.php
<?php
public function beforeRender() {
parent::beforeRender();
$fid = $this->getParam(self::FLASH_KEY);
if ($fid !== NULL) { // ak máme FID, vygeneruj kanonický odkaz na samého seba
$this->template->canonical = $this->link('//this');
}
}
?>
.. a príslušný @layout.latte
<?php
<link rel="canonical" n:ifset="$canonical" href="{$canonical}" />
?>
Napadá niekoho elegantnejšie a lepšie riešenie z pohľadu SEO?