{-# LANGUAGE CPP #-} {-# LANGUAGE OverloadedStrings #-} {-| The Snap HTTP server is a high performance, epoll-enabled, iteratee-based web server library written in Haskell. Together with the @snap-core@ library upon which it depends, it provides a clean and efficient Haskell programming interface to the HTTP protocol. -} module Snap.Http.Server ( simpleHttpServe , httpServe , quickHttpServe , snapServerVersion , setUnicodeLocale , module Snap.Http.Server.Config ) where import Control.Monad import Control.Monad.CatchIO import Data.ByteString (ByteString) import Data.Char import Data.List import Data.Maybe import Prelude hiding (catch) import Snap.Http.Server.Config import qualified Snap.Internal.Http.Server as Int import Snap.Types import Snap.Util.GZip #ifndef PORTABLE import System.Posix.Env #endif import System.IO ------------------------------------------------------------------------------ -- | A short string describing the Snap server version snapServerVersion :: ByteString snapServerVersion = Int.snapServerVersion ------------------------------------------------------------------------------ -- | Starts serving HTTP requests using the given handler. Uses only the basic -- settings from the given config; error handling and compression are ignored. -- This function never returns; to shut down the HTTP server, kill the -- controlling thread. simpleHttpServe :: MonadSnap m => Config m a -> Snap () -> IO () simpleHttpServe config handler = do setUnicodeLocale $ fromJust $ getLocale conf Int.httpServe tout (map listenToInt $ getListen conf) (fmap backendToInt $ getBackend conf) (fromJust $ getHostname conf) (fromJust $ getAccessLog conf) (fromJust $ getErrorLog conf) (runSnap handler) where tout = fromMaybe 60 $ getDefaultTimeout config conf = completeConfig config listenToInt (ListenHttp b p) = Int.HttpPort b p listenToInt (ListenHttps b p c k) = Int.HttpsPort b p c k backendToInt ConfigSimpleBackend = Int.EventLoopSimple backendToInt ConfigLibEvBackend = Int.EventLoopLibEv ------------------------------------------------------------------------------ -- | Starts serving HTTP requests using the given handler, with settings from -- the 'Config' passed in. This function never returns; to shut down the HTTP -- server, kill the controlling thread. httpServe :: Config Snap () -> Snap () -> IO () httpServe config handler = do mapM_ (output . ("Listening on "++) . show) $ getListen conf serve handler `finally` output "\nShutting down..." where conf = completeConfig config output = when (fromJust $ getVerbose conf) . hPutStrLn stderr serve = simpleHttpServe config . compress . catch500 catch500 = flip catch $ fromJust $ getErrorHandler conf compress = if fromJust $ getCompression conf then withCompression else id ------------------------------------------------------------------------------ -- | Starts serving HTTP using the given handler. The configuration is read -- from the options given on the command-line, as returned by -- 'commandLineConfig'. This function never returns; to shut down the HTTP -- server, kill the controlling thread. quickHttpServe :: Snap () -> IO () quickHttpServe m = commandLineConfig emptyConfig >>= \c -> httpServe c m ------------------------------------------------------------------------------ -- | Given a string like \"en_US\", this sets the locale to \"en_US.UTF-8\". -- This doesn't work on Windows. setUnicodeLocale :: String -> IO () setUnicodeLocale lang = #ifndef PORTABLE mapM_ (\k -> setEnv k (lang ++ ".UTF-8") True) [ "LANG" , "LC_CTYPE" , "LC_NUMERIC" , "LC_TIME" , "LC_COLLATE" , "LC_MONETARY" , "LC_MESSAGES" , "LC_PAPER" , "LC_NAME" , "LC_ADDRESS" , "LC_TELEPHONE" , "LC_MEASUREMENT" , "LC_IDENTIFICATION" , "LC_ALL" ] #else return () #endif