1 -- |The entry point of Lucu httpd.
2 module Network.HTTP.Lucu.Httpd
8 import Control.Concurrent
10 import qualified Network.Socket as So
11 import Network.HTTP.Lucu.Config
12 import Network.HTTP.Lucu.Interaction
13 import Network.HTTP.Lucu.RequestReader
14 import Network.HTTP.Lucu.Resource.Tree
15 import Network.HTTP.Lucu.ResponseWriter
16 import qualified OpenSSL.Session as SSL
18 import System.Posix.Signals
20 -- |This is the entry point of Lucu httpd. It listens to a socket and
21 -- waits for clients. Computation of 'runHttpd' never stops by itself
22 -- so the only way to stop it is to raise an exception in the thread
25 -- Note that 'runHttpd' automatically makes SIGPIPE be ignored by
26 -- computing @'System.Posix.Signals.installHandler'
27 -- 'System.Posix.Signals.sigPIPE' 'System.Posix.Signals.Ignore'
28 -- 'Prelude.Nothing'@. This can hardly cause a problem but it may do.
32 -- > module Main where
33 -- > import Network.HTTP.Lucu
36 -- > main = let config = defaultConfig
37 -- > resources = mkResTree [ ([], helloWorld) ]
39 -- > runHttpd config resourcees []
41 -- > helloWorld :: ResourceDef
42 -- > helloWorld = ResourceDef {
43 -- > resUsesNativeThread = False
44 -- > , resIsGreedy = False
46 -- > = Just $ do setContentType $ read "text/plain"
47 -- > output "Hello, world!"
48 -- > , resHead = Nothing
49 -- > , resPost = Nothing
50 -- > , resPut = Nothing
51 -- > , resDelete = Nothing
53 runHttpd :: Config -> ResTree -> [FallbackHandler] -> IO ()
56 do _ <- installHandler sigPIPE Ignore Nothing
58 case cnfSSLConfig cnf of
62 -> do so <- listenOn (sslServerPort scnf)
63 _loopTID <- forkIO $ httpsLoop (sslContext scnf) so
66 httpLoop =<< listenOn (cnfServerPort cnf)
68 httpLoop :: Socket -> IO ()
70 = do (h, addr) <- acceptHTTP so
71 tQueue <- newInteractionQueue
72 readerTID <- forkIO $ requestReader cnf tree fbs h addr tQueue
73 _writerTID <- forkIO $ responseWriter cnf h tQueue readerTID
76 httpsLoop :: SSL.SSLContext -> Socket -> IO ()
78 = do (ssl, addr) <- acceptHTTPS ctx so
79 tQueue <- newInteractionQueue
80 readerTID <- forkIO $ requestReader cnf tree fbs ssl addr tQueue
81 _writerTID <- forkIO $ responseWriter cnf ssl tQueue readerTID
84 acceptHTTP :: Socket -> IO (Handle, So.SockAddr)
86 = do (soPeer, addr) <- So.accept soSelf
87 hPeer <- So.socketToHandle soPeer ReadWriteMode
90 acceptHTTPS :: SSL.SSLContext -> Socket -> IO (SSL.SSL, So.SockAddr)
92 = do (so', addr) <- So.accept so
93 ssl <- SSL.connection ctx so'