Chinaunix首页 | 论坛 | 博客
  • 博客访问: 336047
  • 博文数量: 105
  • 博客积分: 2730
  • 博客等级: 少校
  • 技术积分: 1110
  • 用 户 组: 普通用户
  • 注册时间: 2007-04-20 12:09
文章分类

全部博文(105)

文章存档

2013年(3)

2012年(2)

2011年(36)

2010年(34)

2009年(6)

2008年(20)

2007年(4)

分类: PHP

2011-10-15 16:25:26

Happstack 是一个比较成熟的haskell的web框架. 其教程也简明易懂, 我用起来感觉很顺手.
目前用到的功能都在Haskell内, 整个应用都是编译的, 只要系统架构相同, 部署起来只要拷贝可执行程序即可, 不用安装Haskell的编译器.
为了方便用浏览器观看本地的Html文档,提供统一的入口, 编写了一个小小的Haskell服务器程序,使用了Happstack 和 blaze-html
配置文件:
配置文件的位置是/etc/fser.conf, 在配置文件中编写所有本地需要映射的目录,以及用来从服务器访问的url路径.格式如下:

haskell-doc=/var/hs-doc
share-files=/home/wuxb/share

启动服务器的时候会自动加载路径配置, 这样访问本地的8000端口就可以看到所有文件夹的入口了,按照规则,一切错误的路径也都会指向入口索引,不会出现没有意义的页面.
编译代码前要cabal install happstack, 我是在ghc-7.2.1下开发的,对于以前的ghc版本应该也没有问题.
多说无益,相关文档写的非常清楚,搜索happstack/blaze-html/monad等关键字就可以找到关于本代码的资料了.


服务器程序的代码:servdir.hs  编译选项:-threaded, 不加也可以,就是会并发时有性能影响而已.

{-# LANGUAGE OverloadedStrings #-}
import Data.Maybe
import Happstack.Server
import Control.Monad (msum)
import Text.Blaze
import qualified Text.Blaze.Html5 as H
import qualified Text.Blaze.Html5.Attributes as A
type PathConf = (String, String) -- ^ url, filepath
main :: IO ()
main = (getConf . lines) `fmap` readFile "/etc/fser.conf" >>= servFileWith
appTemplate :: String -> H.Html -> H.Html
appTemplate title body = H.html $ do
   H.head $ do
     H.title (H.toHtml title)
     H.meta ! A.httpEquiv "Content-Type" ! A.content "text/html;charset=uft-8"
   H.body body
servFileWith :: [PathConf] -> IO ()
servFileWith pcs = do simpleHTTP nullConf $ msum $ withConf ++ [indexPage]
  where
   withConf = map (\(u, p) -> dir u $ serveDirectory EnableBrowsing [] p) pcs
   indexPage = ok $ toResponse $ appTemplate "INDEX" $ sequence_ $ map toA pcs
   toA (u,_) = H.h1 $ H.a ! A.href (toValue u) $ (H.toHtml u) >> H.br
getConf :: [String] -> [PathConf]
getConf ss = catMaybes $ map getConf1 ss
   where
     getConf1 s = case break (== '=') s of
     (u,(_:p)) -> Just (u,p)
     _ -> Nothing


启动脚本的代码: servdir.server, 可以放在/etc/init.d里
#!/usr/local/bin/runghc
import System.Environment
import System.Cmd

cmdmap =
  [ ("stop", "killall servdir")
  , ("start", "nohup /root/servdir &>/dev/null &")
  , ("restart", "killall servdir; nohup /root/servdir &>/dev/null &")
  ]

main :: IO ()
main = do
  args <- getArgs
  this <- getProgName
  case args of
    []    -> putStrLn $ "usage: " ++ this ++ " [start|stop|restart]"
    (cmdname:_) -> case lookup cmdname cmdmap of
        Just cmd -> system cmd >> return ()
        Nothing -> putStrLn $ "usage: " ++ this ++ " [start|stop|restart]"
   

阅读(814) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~