Jezen Thomas

Jezen Thomas

CTO & Co-Founder at Supercede.

HTTP Verbs in Yesod Forms

The main function provided by the yesod-form library for processing form submissions is runFormPost.

As the name implies, this function processes POST requests. But what if you want to use a different verb, like PUT? The library is a little confusing in this way, because the post in runFormPost doesn’t actually refer to the HTTP method that triggered the execution of the handler code.

The point of runFormPost is actually just about running the parser against the request body, rather than the query string as would happen with runFormGet.

Conceptually, this makes some sense as a design decision when you remember that web browsers natively only support GET and POST as values of the method attribute in HTML forms. The difference between those two values is perfectly reflected in the design of the library — the values in the form are transferred in either the query string or the request body respectively.

While HTML forms only support GET and POST natively, a typical Yesod project will also support request method overriding, by applying a value for the _method parameter in the query string.

In Hamlet, this looks something like this.

<form  method=post action=@?{(ExampleR, [("_method", "PUT")])}>

This form submission would then be routed to the appropriate handler.

putExampleR :: Handler Html
putExampleR = do
  ((result, form), enctype) <- runFormPost exampleForm
  -- …

So, the browser sends a POST request, but the application actually interprets this as a PUT request and routes it to the appropriate handler. We then process the form in that handler with runFormPost, because the data is still transferred in the request body.