3

Whenever I use a form in my website, I need to pass an "action" attribute to it (I don't want to leave it empty because I prefer to have validating markup). Right now it looks like this:

registerPage = dir "test" $ do
    nullDir
    let action = "/test" :: String
    let mkForm = form action
    let prefix = "register"
    eForm <- happstackEitherForm mkForm prefix registerForm

For forms where the action is the same page they are in, I don't like needing to write the URL twice as I am currently doing. Is there a way to get the "current url" instead?

registerPage = dir "test" $ do
    nullDir
    action <- {- ... -}

The best alternative I have so far is turning the action into an explicit parameter / variable

registerUrl :: String
registerUrl = "register"

registerPage = dir registerUrl $ do
    nullDir
    let action = "/" ++ registerUrl

but if I do that then I'll have one extra parameter that I will need to name and pass around to my functions. I also think that needing to do that "/" ++ is a bit ugly.

hugomg
  • 68,213
  • 24
  • 160
  • 246

2 Answers2

0

Do you want this:

import Control.Monad (MonadPlus)
import Happstack.Server.SimpleHTTP (dir, ServerMonad)

dir' :: (MonadPlus m, ServerMonad m) => String -> (String -> m a) -> m a
dir' path handler = dir path (handler ("/" ++ path))

registerPage = dir' "test" $ \action -> do
    nullDir
    ... use action ...

I don't know if dir' already exists in Happstack.

Tom Ellis
  • 9,224
  • 1
  • 29
  • 54
  • This makes declaring the extra variable a little more lightweight and hides the "/" but it won't work with more complicated routes with nested "dirs" and also ignores query parameters, etc. Now that I think of it, I just want to get the URL the user sent me - maybe I can get that from the Request? – hugomg Jan 04 '14 at 16:34
  • I would have a look at `uriRest` for a start. That gets the *remainder* of the URL, not all of it, but you may be able to find some way of getting the full path. I'm not familiar enough with Happstack to know. – Tom Ellis Jan 04 '14 at 16:42
  • I managed to figure what I wanted - it had nothing to do with routing but thanks for helping me realize that. – hugomg Jan 04 '14 at 17:00
0

Now that I think of it, I think what I actually needed was the current URL, as sent by the user and irrespective of what routing filters I used. This will preserve variable path segments and query string parameters.

To do that, I can get the current Request via askRq and get the URL from it via rqUri and rqQuery

rq <- askRq
let action = (rqUri rq) ++ (rqQuery rq)
hugomg
  • 68,213
  • 24
  • 160
  • 246
  • 1
    instead of 'rqURL' use 'rqUri' which does not get modified by the routing combinators. Sorry the names are silly like that -- it happened before I took over Happstack :) – stepcut Jan 05 '14 at 04:09
  • @stepcut: I tried using rqUri before but it doesn't include the query string like askURL does. How do I add it back in? – hugomg Jan 05 '14 at 13:22
  • ah. rqQuery will get the query string -- I believe it includes the ? so you can just append rqUri + rqQuery? – stepcut Jan 06 '14 at 22:11