5 -- |The entry point of Lucu httpd.
6 module Network.HTTP.Lucu.Httpd
10 import Control.Concurrent
11 import Control.Exception
13 import Control.Monad.Unicode
17 import Network.HTTP.Lucu.Config
18 import Network.HTTP.Lucu.Dispatcher
19 import Network.HTTP.Lucu.Interaction
20 import Network.HTTP.Lucu.RequestReader
21 import Network.HTTP.Lucu.ResponseWriter
22 import Network.HTTP.Lucu.SocketLike as SL
23 import Prelude.Unicode
25 -- |This is the entry point of Lucu httpd. It listens to a socket and
26 -- waits for clients. 'runHttpd' never stops by itself so the only way
27 -- to stop it is to raise an exception in the thread running it.
31 -- > {-# LANGUAGE OverloadedStrings #-}
32 -- > {-# LANGUAGE QuasiQuotes #-}
33 -- > module Main where
35 -- > import Network.HTTP.Lucu
38 -- > main = let config = defaultConfig
39 -- > resources = mkResTree [ ([], helloWorld) ]
41 -- > withSocketsDo $ runHttpd config resourcees []
43 -- > helloWorld :: Resource
44 -- > helloWorld = emptyResource {
46 -- > = Just $ do setContentType [mimeType| text/plain |]
47 -- > putChunk "Hello, world!"
49 -- FIXME: update the above example
50 runHttpd ∷ Config → SchemeMap → IO ()
54 [ do addr ← cnfServerV4Addr cnf
55 return ( launchListener =≪ listenOn AF_INET addr (cnfServerPort cnf)
57 , do addr ← cnfServerV6Addr cnf
58 return ( launchListener =≪ listenOn AF_INET6 addr (cnfServerPort cnf)
61 , do scnf ← cnfSSLConfig cnf
62 addr ← cnfServerV4Addr cnf
63 return ( do so ← listenOn AF_INET addr (sslServerPort scnf)
64 launchListener (sslContext scnf, so)
66 , do scnf ← cnfSSLConfig cnf
67 addr ← cnfServerV6Addr cnf
68 return ( do so ← listenOn AF_INET6 addr (sslServerPort scnf)
69 launchListener (sslContext scnf, so)
76 launchListener ∷ SocketLike s ⇒ s → IO ()
78 = do p ← SL.socketPort so
79 -- FIXME: Don't throw away the thread ID as we can't
80 -- kill it later then.
81 void ∘ forkIO $ httpLoop p so
83 listenOn ∷ Family → HostName → ServiceName → IO Socket
85 = do proto ← getProtocolNumber "tcp"
86 let hints = defaultHints {
87 addrFlags = [AI_PASSIVE]
89 , addrSocketType = Stream
90 , addrProtocol = proto
92 addrs ← getAddrInfo (Just hints) (Just host) (Just srv)
95 (socket (addrFamily addr)
100 do setSocketOption sock ReuseAddr 1
101 bindSocket sock (addrAddress addr)
102 listen sock maxListenQueue
106 httpLoop ∷ SocketLike s ⇒ PortNumber → s → IO ()
108 = do (h, addr) ← SL.accept so
109 tQueue ← mkInteractionQueue
110 readerTID ← forkIO $ requestReader cnf sm h port addr tQueue
111 _writerTID ← forkIO $ responseWriter cnf h tQueue readerTID
115 waitForever = forever $ threadDelay 1000000