Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Yesod forms with page flow

Certain forms are too complicated to have them fit on one page. If, for example, a form involves large amounts of structured data, such as picking locations on a map, scheduling events in a calendar widget, or having certain parts of a form change depending on earlier input, it is of value to be able to break up a certain form over multiple pages.

This is easy to do with dynamic web pages and Javascript, as one would simply create a tab widget with different pages, and the actual submitted form would contain the whole tab widget and all of its input fields, yielding a single POST request for the entire operation.

Sometimes, however, it takes a long time to generate certain input fields; they might even be computationally intensive even after the page has been generated, taxing the low-end computer user's browser. Additionally, it becomes difficult or impossible to create forms that adapt themselves based on earlier input.

It therefore becomes necessary to split up a certain form over multiple full page requests.

This can prove to be difficult, especially since the first page of a form will POST to /location/a, which will issue a redirect to /location/b and requested as GET by the client. Passing the stored form data from POST /location/a to GET /location/b is where the difficulty lies.

Erwin Vervaet, the creator of Spring Web Flow (A subproject of the Spring framework, mostly known for its dependency injection capabilities) once wrote a blog article demonstrating this functionality in said framework, and also comparing it to the Lift Web Framework which implemented similar functionality. He then presents a challenge to other web frameworks, which is further described in a later article.

How would Yesod face this problem, especially considering its stateless REST-based nature?

like image 657
dflemstr Avatar asked Jul 22 '12 11:07

dflemstr


1 Answers

Firstly, there's no pre-built solution to this in existence yet (that I'm aware of at least). And I'm not familiar with how the other frameworks mentioned solve the problem. So what I say here is pretty much conjecture. I'm fairly certain it would work, however.

The crux of the issue here is encoding page A's POST parameters into the GET request for page B. The simplest way to do that would be to stick page A's POST parameters into a session variable. However, doing so would break navigation pretty thoroughly: back/forward wouldn't work at all as described.

So we come back to REST: we need to encode the POST parameters into the request itself. That really means putting the information in either the requested path, or the query string. And the query string probably makes the most sense.

I'd be concerned about putting the raw POST parameters into the query string, as that would allow any proxy server to easily snoop the contents. So I'd like to leverage the existing cryptography from clientsession. In other words, we'll stick a signed, encrypted version of the previous form submission in a query string parameter.

To make it a bit more concrete:

  • User goes to page A via GET.
  • User submits page A via POST.
  • Server validates form submission, gets a value, serializes it, encrypts/hashes it.
  • User is redirected to page B as a GET, with a query string parameter containing the encrypted/hashed value from page A.
  • Continue this process as many times as desired.
  • On the final page, you can decrypt the query string parameter and have all of the form submissions.

This looks like it would be a fun add-on package to write if anyone's interested.

like image 146
Michael Snoyman Avatar answered Oct 10 '22 08:10

Michael Snoyman