Blogged by Ujihisa. Standard methods of programming and thoughts including Clojure, Vim, LLVM, Haskell, Ruby and Mathematics written by a Japanese programmer. github/ujihisa

Monday, December 13, 2010

How To Write And Show Multibyte Characters With Snap Framework

I'm playing with Snap these days. Snap is a web framework for Haskell.

The default template of application code will be like below

{-# LANGUAGE OverloadedStrings #-}
module Main where

import           Control.Applicative
import           Snap.Types
import           Snap.Util.FileServe
import           Text.Templating.Heist
import           Text.Templating.Heist.TemplateDirectory

import           Glue
import           Server


main :: IO ()
main = do
    td <- newTemplateDirectory' "templates" emptyTemplateState
    quickServer $ templateHandler td defaultReloadHandler $ \ts ->
        ifTop (writeBS "hello") <|>
        route [ ("foo", writeBS "bar")
              , ("echo/:echoparam", echoHandler)
              ] <|>
        templateServe ts <|>
        dir "static" (fileServe ".")


echoHandler :: Snap ()
echoHandler = do
    param <- getParam "echoparam"
    maybe (writeBS "must specify echo/param in URL")
          writeBS param

See the following line in main function:

        ifTop (writeBS "hello") <|>

This just shows a text written in ByteString "hello" to browser.

$ cabal install
$ {your application name} 3000
$ curl http://localhost:3000
hello

You can change the message "hello" to something and show the message on browser, but if the text is non-ascii like utf-8, you have to change other places as well. See the following patch:

diff --git snapfib.cabal snapfib.cabal
index d7a98fe..35b5c92 100644
--- snapfib.cabal
+++ snapfib.cabal
@@ -28,7 +28,8 @@ Executable snapfib
     text,
     containers,
     MonadCatchIO-transformers,
-    filepath >= 1.1 && <1.2
+    filepath >= 1.1 && <1.2,
+    utf8-string

   if impl(ghc >= 6.12.0)
     ghc-options: -threaded -Wall -fwarn-tabs -funbox-strict-fields -O2
diff --git src/Main.hs src/Main.hs
index d5b24c4..036b2db 100644
--- src/Main.hs
+++ src/Main.hs
@@ -9,13 +9,14 @@ import           Text.Templating.Heist.TemplateDirectory

 import           Glue
 import           Server
+import           Data.Text


 main :: IO ()
 main = do
     td <- newTemplateDirectory' "templates" emptyTemplateState
     quickServer $ templateHandler td defaultReloadHandler $ \ts ->
-        ifTop (writeBS "hello") <|>
+        ifTop (writeText $ pack "こんにちはこんにちは!") <|>
         route [ ("foo", writeBS "bar")
               , ("echo/:echoparam", echoHandler)
               ] <|>

The function writeBS in Snap receives ByteString and shows the message to browser as a response. This cannot handle UTF-8 strings for some reason, so instead of using writeBS with ByteString you have to use writeText with Text represented message. You can convert into Text with Data.Text.pack function.

See also:

2 comments:

  1. Under OverloadedStrings, you can omit Data.Text.pack just like ByteString's because Text is also an instance of IsString.

    ReplyDelete

Followers