EzDevInfo.com

heist

Scheme in as little Ruby and as much Scheme as possible. Supports macros, continuations, tail recursion and lazy evaluation.

Using values not from the application monad with Heist templates

I'm trying to write an application server using Happstack, Heist, and web-routes, but am having trouble figuring out how to let splices access values that don't originate from my application's monad stack.

There are two situations where this comes up:

  • Parameters extracted from the URL path via web-routes. These come from pattern-matching on a type-safe URL when routing the request to the proper handler.
  • Session information. If the request is for a brand-new session, I can't read the session identifier from a cookie in the request (since no such cookie exists yet), and I can't use the splices to create a new session if needed, since then if more than one splice tries to do it, I wind up creating multiple new sessions for a single request. But if I create the session before entering the web-routes stuff, the session exists outside the application monad.

Consider the following sample program that tries to serve the following URLs:

  • /factorial/n outputs the factorial of n
  • /reverse/str outputs str backwards

Since the parameter appears in the URL path instead of the query string, it gets extracted via web-routes instead of coming from the ServerPartT monad. From there, though, there's no clear way to put the parameter somewhere where the splices can see it, since they only have access to the application monad.

The obvious solution of sticking a ReaderT somewhere on the monad stack has two problems:

  • Having a ReaderT above ServerPartT hides the Happstack parts of the monad stack, since ReaderT doesn't implement ServerMonad, FilterMonad, etc.
  • It assumes that all the pages I'm serving take the same type of parameter, but in this example, /factorial wants an Int but /reverse wants a String. But for both page handlers to use the same TemplateDirectory, the ReaderT would need to be carrying a value of the same type.

From peeking at the Snap documentation, it looks like Snap handles parameters in the URL path by effectively copying them into the query string, which sidesteps the problem. But that's not an option with Happstack and web-routes, and besides, having two different ways for a URL to specify the same value strikes me as being a bad idea security-wise.

So, is there a "proper" way to expose non-application-monad request data to splices, or do I need to abandon Heist and use something like Blaze-HTML instead where this isn't an issue? I feel like I'm missing something obvious, but can't figure out what it might be.

Example code:

{-# LANGUAGE TemplateHaskell #-}

import Prelude hiding ((.))

import Control.Category ((.))
import Happstack.Server (Response, ServerPartT, nullConf, ok, simpleHTTP)
import Happstack.Server.Heist (render)
import Text.Boomerang.TH (derivePrinterParsers)
import Text.Templating.Heist (Splice, bindSplices, emptyTemplateState, getParamNode)
import Text.Templating.Heist.TemplateDirectory (TemplateDirectory, newTemplateDirectory')
import Web.Routes (RouteT, Site, runRouteT)
import Web.Routes.Boomerang (Router, anyString, boomerangSite, int, lit, (<>), (</>))
import Web.Routes.Happstack (implSite)

import qualified Data.ByteString.Char8 as C
import qualified Data.Text as T
import qualified Text.XmlHtml as X

data Sitemap = Factorial Int
             | Reverse String

$(derivePrinterParsers ''Sitemap)

-- Conversion between type-safe URLs and URL strings.
sitemap :: Router Sitemap
sitemap = rFactorial . (lit "factorial" </> int)
       <> rReverse . (lit "reverse" </> anyString)

-- Serve a page for each type-safe URL.
route :: TemplateDirectory (RouteT Sitemap (ServerPartT IO)) -> Sitemap -> RouteT Sitemap (ServerPartT IO) Response
route templates url = case url of
                        Factorial _num -> render templates (C.pack "factorial") >>= ok
                        Reverse _str   -> render templates (C.pack "reverse") >>= ok

site :: TemplateDirectory (RouteT Sitemap (ServerPartT IO)) -> Site Sitemap (ServerPartT IO Response)
site templates = boomerangSite (runRouteT $ route templates) sitemap

-- <factorial>n</factorial> --> n!
factorialSplice :: (Monad m) => Splice m
factorialSplice = do input <- getParamNode
                     let n = read . T.unpack $ X.nodeText input :: Int
                     return [X.TextNode . T.pack . show $ product [1 .. n]]

-- <reverse>text</reverse> --> reversed text
reverseSplice :: (Monad m) => Splice m
reverseSplice = do input <- getParamNode
                   return [X.TextNode . T.reverse $ X.nodeText input]

main :: IO ()
main = do templates <- newTemplateDirectory' path . bindSplices splices $ emptyTemplateState path
          simpleHTTP nullConf $ implSite "http://localhost:8000" "" $ site templates
    where splices = [(T.pack "factorial", factorialSplice), (T.pack "reverse", reverseSplice)]
          path = "."

factorial.tpl:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8"/>
        <title>Factorial</title>
    </head>
    <body>
        <p>The factorial of 6 is <factorial>6</factorial>.</p>
        <p>The factorial of ??? is ???.</p>
    </body>
</html>

reverse.tpl:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8"/>
        <title>Reverse</title>
    </head>
    <body>
        <p>The reverse of "<tt>hello world</tt>" is "<tt><reverse>hello world</reverse></tt>".</p>
        <p>The reverse of "<tt>???</tt>" is "<tt>???</tt>".</p>
    </body>
</html>

Source: (StackOverflow)

Heist: How do I insert a dynamic list of sub-templates into a template?

I am writing a site for online surveys. I have a list of questions that all go on one html page and the list is of unknown length. Each question has the form stored in template qu1.tpl and the page is qu.tpl. Now I want to:

  1. replace some names in qu1.tpl for each question

  2. replace some things in qu.tpl once

  3. and stick all instantiations of qu1.tpl into qu.tpl

Using what I learned in the tutorial, I tried to recursively replace a tag <qulist/> with <apply template="qu1.tpl"><qulist/> in qu.tpl using localHeist and bindString but this cannot work because qu.tpl is already rendered so the newly inserted apply tag doesn't resolve.

what should I do instead?

(I guess this is a more general question. If you can think of other applications the answer applies to, please add text and tags for the search engines.)


Source: (StackOverflow)

Advertisements

Snap-Heist: why my template is not rendered?

I'm trying to render a template using Snap and Heist.

I'm sure my handler function is called correctly(if I replace handler function's content with undefined, it fails as expected. Debug.Trace.trace also works as expected).

This handler function consists of one line: render "template". But for some reason I'm getting No handler accepted <url> error instead of a template not found or something like that.

I think the problem here is that I'm placing my template in wrong directory, but there's no way to know where are searched for templates. So my question is:

  1. Isn't this error message misleading? It should have been something like template not found: template.tpl
  2. Where can I know which directories are searched for templates?

Thanks.


EDIT: For some reason I still can't render templates in my snaplet.

Think the snap application created by snap init. I only made slight modifications on it:

  • I added one more field to App record: _myapp :: Snaplet Myapp
  • In app initializer function, I added: n <- embedSnaplet "myapp" myapp myappInit and then passed n to record.
  • I created new file src/Myapp.hs.

Here are relevant parts in Myapp.hs:

myappInit = do
    ...
    h <- nestSnaplet "" heist $ hesitInit "myapp_templates"
    addRoutes routes
    ...

routes = [ ("/submit", submitHandler) ]

submitHandler = trace "rendering submit" $ render "submit"

but for some reason even though I see rendering submit printed to console when I go to http://0.0.0.0:8000/myapp/submit, I get No handler accepted "/hsnews/submit" message as HTTP response(instead of rendered template). I have submit.tpl and _submit.tpl in snaplets/heist/myapp_templates.

Can anyone help me with this?


EDIT2: I solved my problem, I'll add an answer shortly.


Source: (StackOverflow)

Static files in a Snaplet

I'd like to serve some static files from a Snaplet in the Snap framework. How do I do that? The documentation is not exactly clear.

I know how to add routes and stuff, but I'm stuck at two problems:

  1. What would I need to pass to serveDirectory to serve files from the snaplet directory?
  2. How would I reference these static files in Heist templates of my snaplet? I obviously can't use absolute URLs, since I don't know the URL prefix my snaplet is eventually installed in the final application. In other words, how do I get an URL relative to the snaplet root URL in a Heist template?

Source: (StackOverflow)

Bind splice to tag in Heist

I want to use a website as a working example in order to help learn Haskell. I'm trying to follow the Heist tutorial from the Snap website, and display the result of a factorial function in a web page.

I can get the example function defined "server side" without the compiler complaining, but I cannot figure out how to bind the function to a tag which I can then place into the HTML. Specifically, this part works fine (in, say, Site.hs):

factSplice :: Splice Snap
factSplice = do
    input <- getParamNode
    let text = T.unpack $ X.nodeText input
        n = read text :: Int
    return [X.TextNode $ T.pack $ show $ product [1..n]]

But the really important part - how to evaluate this function as part of a web page (such as how to bind it to a tag like < fact />) - is cryptic. The instructions say to drop:

bindSplice "fact" factSplice templateState

somewhere in the code. But this alone is not sufficient. This statement is not an expression (stuff = bindSplice...), so it is not clear how or where to put it in the code. Moreover, it is not at all clear where "templateState" is supposed to come from. It almost seems like "templateState" is supposed to be a placeholder for default values like emptyTemplateState or defaultHeistState, but these both appear to have been deprecated years ago, and the latest version of Heist (0.14) does not recognize them.

MightyByte has commented on this kind of question several times in 2011, but the answers all gloss over exactly the confusing part, i.e. how to actually get data into a web page. Can anyone help?

-- UPDATE --

Thank you very much, mightybyte! Your explanation and some cursory poking around in the source code cleared up a lot of confusion, and I was able to get the factorial example from the Snap website tutorial working. Here is my solution - I'm a complete n00b, so apologies if the explanation seems pedantic or obvious.

I more or less used the addConfig approach that mightybyte suggested, simply copying the implementation of addAuthSplices from SpliceHelpers.hs. I started with the default project via "snap init", and defined a function addMySplices in Site.hs

addMySplices :: HasHeist b => Snaplet (Heist b) -> Initializer b v ()
addMySplices h = addConfig h sc
    where
      sc = mempty & scInterpretedSplices .~ is
      is = do
           "fact" ## factSplice

This uses lenses to access the fields of the SpliceConfig neutral element mempty, so I had to add Control.Lens to the dependencies in Site.hs, as well as Data.Monoid to put mempty in scope. I also changed the type signature of the factorial splice to factSplice :: Monad n => I.Splice n, but the function is otherwise unchanged from its form in the Heist tutorial. Then I put a call to addMySplices in the application initializer, right next to addAuthSplices in Site.hs

app :: SnapletInit App App
...
addAuthSplices h auth
addMySplices h
...

which results in factSplice being bound to the tag <fact>. Dropping <fact>8</fact> into one of the default templates renders 40320 on the page, as advertised.

This question from about a year ago contains a superficially similar solution, but does not work with the latest version of Heist; the difference is that some fields were made accessible through lenses instead of directly, which is explained on the Snap project blog in the announcement of Heist 0.14. In particular, hcCompliedSplices has been completely redefined - there's even a friendly warning about it in Types.hs.


Source: (StackOverflow)

Adding OnLoad hooks for Heist templates using the Snap Web Framework

I wish to add some hooks for pre-processing Heist templates in a web application using Snap. My naïve approach so far has been to use the following code in my application initializer:

app :: SnapletInit App App
app = makeSnaplet "app" "The main web application" Nothing $ do
    -- ...
    h <- nestSnaplet "heist" heist $ heistInit "resources/templates"
    -- ...
    modifyHeistTS . addOnLoadHook $ myTemplateHook

This code does of course not work, since the hook is added after the templates are loaded from "resources/templates"

How would one go about modifying the Heist template state before the initial templates are loaded, in order to add OnLoad hooks?


Source: (StackOverflow)

How to preserve javascript in heist template from escaping?

I'm using Snap framework with Heist templating engine. The problem is that Heist corrupts javascript code inlined into html:

<script type="text/javascript">alert('hello');</script> 

Transformed into:

<script type="text/javascript">alert(&apos;hello&apos;);</script>

How can I tell Heist to preserve contents of the script tag?

Edit: I just implemented such splice:

verbatimSplice :: MonadIO m => Splice m
verbatimSplice = do
    node <- getParamNode       -- get <script> node
    stopRecursion              -- stop recursive processing of splices
    lift $ liftIO $ print node -- show me the node
    return [node]              -- return <script> as is

But binding this splice to script tag does not help. It prints

Element "script" [("type","text/javascript")] [Text "alert('hello');"]

so, I think, html entity substitution takes place after running all splices.


Source: (StackOverflow)

Type names prefixed with package name and version

I'm pretty new to Haskell, and I'm trying to follow along with the Happstack Crash Course. I've done some of the examples, but when I tried the happstack-heist example, I got a strange compilation error. The file that I'm compiling looks like this:

module Main where

import Control.Applicative    ((<$>))
import Control.Monad          (msum)
import qualified Data.Text    as T
import Happstack.Server       ( dir, nullConf, nullDir, simpleHTTP
                              , seeOther, toResponse
                              )
import Happstack.Server.Heist (heistServe, initHeistCompiled)
import Heist                  (Splices, (##), getParamNode, noSplices)
import Heist.Compiled         (Splice, yieldRuntimeText)
import qualified Text.XmlHtml as X

-- | factorial splice
factSplice :: (Monad m) => Splice m
factSplice = do
  intStr <- T.unpack . X.nodeText <$> getParamNode
  let res = yieldRuntimeText $ do
        case reads intStr of
          [(n,[])] ->
            return (T.pack $ show $ product [1..(n :: Integer)])
          _ ->
            return (T.pack $ "Unable to parse " ++
                    intStr ++ " as an Integer.")
  return $ res

main :: IO ()
main = do
  heistState <- do
    r <- initHeistCompiled (T.pack "fact" ## factSplice) noSplices "."
    case r of
      (Left e) -> error $ unlines e
      (Right heistState) -> return $ heistState
  simpleHTTP nullConf $ msum
    [ dir "heist" $ heistServe heistState
    , nullDir >>
      seeOther "/heist/factorial" (toResponse "/heist/factorial")
    ]

The error is:

test.hs:37:36:
    Couldn't match expected type `happstack-server-7.3.9:Happstack.Server.Internal.Types.Response'
                with actual type `Happstack.Server.Internal.Types.Response'
    In the return type of a call of `toResponse'
    In the second argument of `seeOther', namely
      `(toResponse "/heist/factorial")'
    In the second argument of `(>>)', namely
      `seeOther "/heist/factorial" (toResponse "/heist/factorial")'

It seems as though something wants types that are prefixed with the package name and version number, which I don't understand. Both happstack-server and happstack-heist were installed with cabal install.


Source: (StackOverflow)

Use results from postgresql-simple in a Heist template

I am trying to combine this Heist tutorial and this postgresql-simple tutorial.

I tried doing different variations of this.

splice :: C.Splice IO  
splice =  do  
  projects <- query_ "SELECT * FROM projects"  
  C.manyWithSplices C.runChildren projectSplice $ return (projects :: [Project])  
  where  
    projectSplice = do  
      "title" ## (C.pureSplice . C.textSplice $ title)  
      "description" ## (C.pureSplice . C.textSplice $ description)  

But I kept getting this error.

No instance for (HasPostgres (HeistT IO IO))
  arising from a use of 'query_'
Possible fix:
  add an instance declaration for (HasPostgres (HeistT IO IO))
In a stmt of a 'do' block:
  projects <- query_ "SELECT * FROM projects"
In the expression:
  do { projects <- query_ "SELECT * FROM projects";
       C.manyWithSplices C.runChildren projectSplice 
       $ return (projects :: [Project]) }

I don't know how to implement that instance declaration and I still don't completely grasp monads. I am not sure if I am even on the right track.

EDIT: Thanks to @mightybyte for his answer, I came up with this.

projectSplice = do
  "title" ## (C.pureSplice . C.textSplice $ title)
  "description" ## (C.pureSplice . C.textSplice $ description)

splice :: C.Splice (Handler App App)
splice =  C.manyWithSplices C.runChildren projectSplice $ lift $ query_ "SELECT * FROM projects"

getHeistState heistConfig = liftIO $ either (error "Heist Init failed") id <$> (runEitherT $ initHeist heistConfig)

getBuilder heistState = maybe (error "Render template failed") fst $ C.renderTemplate heistState "database"

getAllProjectsHeist :: Handler App App ()
getAllProjectsHeist = do
  let heistConfig = HeistConfig defaultInterpretedSplices defaultLoadTimeSplices ("project" ## splice) noSplices [loadTemplates "templates"]
  heistState <- getHeistState heistConfig
  builder <- getBuilder heistState
  writeBS $ toByteString builder

Source: (StackOverflow)

How can I use the Text.RSS module in an application already using Text.XmlHtml without also importing Text.XML.HaXml?

I have an pretty stereotypical weblogging application that I've been working on for practice. The top level of my application is a Happstack layer using pretty standard routing. I have gotten to the point where I want to add an XML feed to the code.

Here's the part that bothers me. Since I used Heist for templating, I have already brought in the Text.XmlHtml module as part of working with Heist. Using Text.RSS requires that I bring in Text.XML.HaXml, too. It seems excessive to me to need to use two different XML modules in the same application.

So, short of writing my own RSS feed (and probably doing it wrong/in violation of spec/investing a ton of excessive time), is there any way to stick with just a single XML library in my application? Also, is there any serious drawback or code bloat to having two different XML modules present?


Source: (StackOverflow)

Integrating a runtime splice with a Snap/Heist app

I'm putting together a simple Snap app using Heist templates. I want to print the request url into the page. However, instead of running my splice, the output just has the splice tag. I feel like I've overlooked something simple, because I can't find any difference between my app and the tutorials I've found.

Site.hs:

{-# LANGUAGE OverloadedStrings #-}

module Site
  ( app
  ) where

import           Data.Monoid
import           Snap.Core
import           Snap.Snaplet
import           Snap.Snaplet.Heist
import           Heist
import           Application
import           Control.Monad.Trans.Class (lift)
import           Data.Text.Encoding        (decodeUtf8)
import qualified Text.XmlHtml              as X

currentPath :: SnapletISplice App
currentPath = do
  requestPath <- lift $ withRequest (return . rqURI)
  return [X.TextNode $ decodeUtf8 requestPath]

app :: SnapletInit App App
app = makeSnaplet "andrewlorente" "My wubsite" Nothing $ do
    let config = mempty {
        hcInterpretedSplices = "currentPath" ## currentPath
      }
    h <- nestSnaplet "heist" heist $ heistInit' "templates" config
    return $ App h

index.tpl:

<currentPath />

As far as I can tell, the rendered output from visiting the root path / should be something like

/

But in fact it is

<currentPath></currentPath>

I'm at my wits' end trying to figure out why my splice isn't run.


Source: (StackOverflow)

Embedding a Heist tag inside of a javascript

Due to some library incompatibilities, I'm not able to use both Pandoc and Heist in the same application. As such, I decided to go with Markdown.JS to handle converting from Markdown format data into HTML in the client's browser. This could have some nice extra benefits in the long run, but in the short run, it is just because Pandoc depends on Blaze-HTML 0.4 and Heist depends on Blaze-HTML 0.5.

So, in a weblog-like application, I have a template that is used to fill out each entry, but then the content of each entry needs to get converted into HTML after the page has been loaded. So, I created a template that looks like this:

<h2> <a rel='nofollow' href="wiki/${target}"><entryTitle /></a> </h2>
<p class="entryDate"> <entryDate /> </p>
<div id="body_${entryDate}">
<entryBody />
</div>

<script type="text/javascript">
renderDiv("body_" + <entryDate />)
</script>

Unfortunately, the renderDiv call ultimately renders like this:

<script type='text/javascript'>
renderDiv("body_" + <entryDate />)
</script>

I have also tried using the string-embedded form (like I did for the div id in the template):

<script type="text/javascript">
renderDiv("body_${entryDate}")
</script>

Again, it renders verbatim.

How do I convince Heist to splice in the entryDate inside of the javascript?

Alternately, I'm using Prototype.JS as a Javascript library. Is there a way for me to put the script inside of the div and call the script basically with "self"?

<div id="body_${entryDate}">
<entryBody />
<script type="text/javascript">
renderDiv($(self))
</script>
</div>

Source: (StackOverflow)

What is the default AttrSplices for Heist-0.13?

I am working on a project using Heist, and since it recently upgrade to 0.13 version, I tried it out and find the original HeistConfig changed a lot.

data HeistConfig m = HeistConfig
    { hcInterpretedSplices :: Splices (I.Splice m)
        -- ^ Interpreted splices are the splices that Heist has always had.  They
        -- return a list of nodes and are processed at runtime.
    , hcLoadTimeSplices    :: Splices (I.Splice IO)
        -- ^ Load time splices are like interpreted splices because they return a
        -- list of nodes.  But they are like compiled splices because they are
        -- processed once at load time.  All of Heist's built-in splices should be
        -- used as load time splices.
    , hcCompiledSplices    :: Splices (C.Splice m)
        -- ^ Compiled splices return a DList of Chunks and are processed at load
        -- time to generate a runtime monad action that will be used to render the
        -- template.
    , hcAttributeSplices   :: Splices (AttrSplice m)
        -- ^ Attribute splices are bound to attribute names and return a list of
        -- attributes.
    , hcTemplateLocations  :: [TemplateLocation]
        -- ^ A list of all the locations that Heist should get its templates
    }

So now I could no longer use [] as default Splices, since there are defaultInterpretedSplices and defaultLoadTimeSplices, I find the defaultAttrSplices just missed, so how shoud I define it?


Source: (StackOverflow)

cabal install errors-1.3.1 fails

I'm trying to install the newest version of Heist, but errors-1.3.1 which is a dependency fails to install. Any suggestions for how to get past this?

$ cabal install errors-1.3.1
Resolving dependencies...
Configuring errors-1.3.1...
Building errors-1.3.1...
Preprocessing library errors-1.3.1...
[1 of 5] Compiling Data.EitherR     ( Data/EitherR.hs, dist/build/Data/EitherR.o )
[2 of 5] Compiling Control.Error.Util ( Control/Error/Util.hs, dist/build/Control/Error/Util.o )

Control/Error/Util.hs:74:10:
    Could not deduce (Monad m) arising from a use of `fmap'
    from the context (Functor m)
      bound by the type signature for
                 fmapRT :: Functor m => (a -> b) -> EitherT l m a -> EitherT l m b
      at Control/Error/Util.hs:74:1-13
    Possible fix:
      add (Monad m) to the context of
        the type signature for
          fmapRT :: Functor m => (a -> b) -> EitherT l m a -> EitherT l m b
    In the expression: fmap
    In an equation for `fmapRT': fmapRT = fmap
cabal: Error: some packages failed to install:
errors-1.3.1 failed during the building phase. The exception was:
ExitFailure 1

Source: (StackOverflow)

Snap: compiled splice dependent on runtime decision and URL variable

I have a situation where I have to construct compiled splices and feed data into them which depends on the URL variable. I struggle to solve the problem.

So there is simple file name list that needs to be rendered in a table. Simple. Files belong to a group or category so you can list all files or related to a particular category. I pull data using this function:

getFilesList :: Maybe ByteString -> AppHandler [Document]
getFilesList cat = do
  let selection = maybe [] (\c -> ["category" =: T.decodeUtf8 c]) cat
  r <- eitherWithDB $ rest =<< find (select selection "files") {project = ["blob" =: 0]}
  return $ either (const []) id r

If it gets Nothing it pulls the whole list if it gets Just category it pulls files that belongs to that category. Easy so far.

I call the above function from within a handler so that I can feed an argument into it.

listFiles :: AppHandler [Document]
listFiles = do
  cat <- getParam "cat"
  let r = maybe Nothing (\c -> if c == "all" then Nothing else Just c) cat
  render "files/list-files"
  getFilesList r

If I get "all" or Nothing on the URL - I get the full list. Anything other then that - I get a category filtered list.

The URL root looks like this

("/files/:cat",           method GET    listFiles)

But now I have a problem because the "method" function will only accept Handler App App () signature. My handler returns data to be fed into the splices.

I construct my splices like so:

listFilesS :: Splices (Splice (Handler App App))
listFilesS = "files" ## files
  where
    files = manyWithSplices runChildren file $ lift listFiles -- Feed data here
    file = do
      "file-name"     ## (pureSplice . textSplice $ at "name")
      "file-oid"      ## (pureSplice . textSplice $ id)
      "file-date"     ## (pureSplice . textSplice $ dateFromDoc)
      "file-size"     ## (pureSplice . textSplice $ fsize)
      "file-type"     ## (pureSplice . textSplice $ at "type")
      "file-auth"     ## (pureSplice . textSplice $ const "admin")
      "file-link"     ## (pureSplice . textSplice $ flink)
      "file-category" ## (pureSplice . textSplice $ at "category")
      where id = T.pack . show . valueAt "_id"
        fsize = T.pack . show . round . (flip (/) 1024) . (at "size")
        flink = T.append "/files/" . id

I cannot find a way around it. Probably just missing something stupid. Any ideas what I am doing wrong?

In any case, my handler function looks incorrect since I render the template first and then pull the data. If I fix the handler then I cant feed the data based on the URL parameter.

Confused.


Source: (StackOverflow)