<div dir="ltr"><br><br><div class="gmail_quote">On Mon, Jul 5, 2010 at 10:01 PM, Michael Snoyman <span dir="ltr">&lt;<a href="mailto:michael@snoyman.com">michael@snoyman.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<div dir="ltr">Hey Simon,<div><br></div><div>Firstly, I&#39;m not sure if your message went through to the rest of the list, but at least they should see this reply.<br><br><div class="gmail_quote"><div class="im">On Mon, Jul 5, 2010 at 8:02 PM, Simon Michael <span dir="ltr">&lt;<a href="mailto:simon@joyful.com" target="_blank">simon@joyful.com</a>&gt;</span> wrote:<br>


<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi Michael.. thanks again for the great real-world-driven updates to Yesod et al. I&#39;m looking forward to trying widgets. Meanwhile...<br>



<br>
I&#39;m having trouble serving a stylesheet that Chrome will recognise, because this:<br>
<br>
getStyleCss :: Handler HledgerWebApp RepPlain<br>
getStyleCss = do<br>
    app &lt;- getYesod<br>
    let dir = appWebdir app<br>
    s &lt;- liftIO $ readFile $ dir &lt;/&gt; &quot;style.css&quot;<br>
    header &quot;Content-Type&quot; &quot;text/css&quot;<br>
    return $ RepPlain $ toContent s<br>
<br>
serves up this:<br>
<br>
$ curl -i <a href="http://localhost:5000/style.css" target="_blank">http://localhost:5000/style.css</a><br>
HTTP/1.1 200 OK<br>
Content-Type: text/plain; charset=utf-8<br>
Set-Cookie: _SESSION=...; path=/; expires=2010-07-05T18:41:35-00:00<br>
Content-Type: text/css<br>
<br>
Note the two content-types. (Also, no content-length header; I don&#39;t know if that matters.)<br>
<br></blockquote></div><div>Let me explain. In general, you don&#39;t need to explicitly set content-type headers in Yesod. Yesod determines the content type automatically based on the return type of the handler function. In particular, a handler must return an instance of HasReps, which allows a handler to specify multiple representations of data if it so desires.</div>

<div><br></div><div>By using a return type of RepPlain, you&#39;re telling Yesod to set a content-type header of &quot;text/plain&quot;. Instead, you probably want to use a different return type. For example, you could use the [(ContentType, Content)] return type.</div>

<div><br></div><div>However, in your case, you have two much better options (in my opinion):</div><div><br></div><div>* Use the Static helper.</div><div>* Use the sendFile function. When using sendFile, you short-circuit the remainder of the handler code and immediately send a file. You get to explicitly state the content type, and also get another bonus: some backends optimize the sending of static files. For example, the SimpleServer backend using a sendfile system call, so you avoid unnecessary data copying.</div>
<div class="im">
<div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

Your examples seem to serve css using Yesod.Helpers.Static. I&#39;m not using that because it seems to require a file path known at compile time, or am I wrong ? I get the path at run-time with cabal&#39;s getDataFilename.<br>



<br></blockquote></div><div>No, the path does not need to be known at compile time, but you&#39;ll need to supply it when constructing the Static data type value. All of this would happen when initializing your site argument; I can put together an example of this if you like.</div>
<div class="im">
<div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
And an unrelated question: what&#39;s the meaning of the type returned by a hamlet template ? I see one of your examples returning something like Hamlet AppRoutes, but my app will accept only Hamlet String for some reason. I wouldn&#39;t worry except hamletToRepHtml seems to require the former.<br>


<font color="#888888">
<font color="#000000"><font color="#888888"><br></font></font></font></blockquote></div><div>type Hamlet url = (url -&gt; String) -&gt; Html ()</div><div><br></div><div>The Html is a datatype taken from Blaze, which is what let&#39;s Hamlet get all of the performance advantages of that library. The url has to do with the type-safe URL feature: every site has a URL datatype associated with it, which defines all valid routes into an application. Of course, we can&#39;t just display Haskell datatypes in our HTML code, so Hamlet takes a &quot;url rendering function&quot; as its first argument.</div>

<div><br></div><div>In general, you shouldn&#39;t need to be bothered with any of these details, as Yesod automates all of the rendering details for you. If you point me to the code in question, I&#39;ll take a look.</div>

<div><br></div><font color="#888888"><div>Michael </div></font></div></div></div>
</blockquote></div><br></div>