Richard Šerý
17.5.2012

Odesíláte formulář? Nezapomeňte na redirect!



Pokaždé, když odešlete formulář metodou POST, musíte na serveru udělat redirect. Možná je to pro vás samozřejmost, ale stále se setkávám se spoustou lidí, kteří to buď neznají nebo v tom dělají chyby.

Proč?

Poté co prohlížeč přijme data z formuláře, vygeneruje novou stránku. Pokud by na ní uživatel stisknul v prohlížeči tlačítko “refresh”, pokusil by se prohlížeč znovu odeslat jednou už odeslaná data. Protože to je nestandardní operace, browser se uživatele zeptá, jestli si to opravdu přeje, ale řekněme si upřímně – kolik uživatelů si to vůbec přečte? A kolik z nich chápe, o co se jedná? Jestliže místo vygenerování stránky uděláte redirect na REST URL (tzv. “POST / Redirect / GET pattern”), nemusíte se o tlačítka jako je “back” nebo “refresh” více starat – alespoň v souvislosti s odesíláním formulářů.

Jak?

Udělat serverový redirect je triviální, ale často se chybuje v HTTP kódu. Jediný správný HTTP kód pro tento redirect je 303 “See Other”. Bohužel, jak praví dokumentace, “Many pre-HTTP/1.1 user agents do not understand the 303 status. When interoperability with such clients is a concern, the 302 status code may be used instead, since most user agents react to a 302 response as described here for 303.” Pokud tedy počítáte i se staršími browsery (např. Netscape 4), použijte kód 302 a doufejte, že ho někdo v budoucnu nenaimplementuje správně – pak by totiž kód 302 nepřešel na GET, ale zopakoval by POST, což by byla docela katastrofa. Všechny současné browsery by však 303 měly umět, takže pokud zrovna neděláte stránky pro muzeum prohlížečů, můžete ho s klidem a bez rizika používat.

Platí to vždy?

Každé pravidlo má svoje výjimky. Určitě se může vyskytnout situace, v jaké by mohlo být opakované odeslání POSTu výhodné, ale v praxi jsem se s takovou situací zatím nesetkal. Jestli jste se s takovým případem setkali, napište o něm v komentářích.

Vaše emailová adresa nebude zveřejněna

Komentáře

Děkujeme za váš komentář
Další
  • Max

    Redirect nepouzivam, ulozim si SESSION promennou jeji hodnotu si predam v POST pro overeni po odeslani, po uspesnem odeslani SESSION vymazu. Pri pokusu o reload dojde sice k znovu odeslani POST, ale akce se neprovede protoze SESSION[test]!=POST[test]

  • Jen bych zdůraznil, že ten redirect se týká _jen_ formuláře, který byl úspěšně vykonán. Pokud jsou data z nějakého důvodu špatná, a uživatel se má tímto formulářem opět zabývat, tak redirect je naopak chybou. IMHO.

  • Max: To má jednu nevýhodu: při reloadu se zobrazí ten ošklivý popup. Taco: To je pravda, díky za doplnění. Úplně chyba by to asi nebyla, ale hned bychom narazili na problém, jak dostat zadaná nevalidní data přes redirect do další obrazovky, aby se uživateli neztratily.

  • Petr F.

    Asi většina MVC toto má podpořeno přímo v kontroloru. To co psal MAX se ve STRUTS MVC jmenuje "tokens". Jinak metoda redirectu nám nešla použít u portletů, protože se jedná vždy jen o fragment fragment stránky, kterou řídí portál a redirect vede mimo kontext portálové stránky.

  • To by mě zajímalo (zcela bez ironie), kdo v dnešní době počítá s Netscape 4. Přijde mi to jako takový akademický argument.

    1. Taky mi taková argumentace připadá absurdní. Z nepochopitelných důvodů takovéhle věci vždycky nějaký potížista vytáhne, takže je lepší být na to připraven a promptně ho s tím odeslat do patřičných míst.