@@ -78,8 +78,9 @@ defaultResponse = Response { responseVersion = B.pack "HTTP/1.1"
79-- | Create a response for a given HTTP request.
79-- | Create a response for a given HTTP request.
80createResponse :: Request -> Server Response
80createResponse :: Request -> Server Response
81+createResponse request
81−createResponse request | requestMethod request == B.pack "GET" = createGetResponse request
82+ | requestMethod request == B.pack "GET" = createGetResponse request
82− | otherwise = return $ createErrorResponse 501 (B.pack "Not Implemented")
83+ | otherwise = return $ createErrorResponse 501 (B.pack "Not Implemented")
84-- | Create a simple error response.
85-- | Create a simple error response.
85createErrorResponse :: Int -- ^ Error code.
86createErrorResponse :: Int -- ^ Error code.
@@ -89,9 +90,10 @@ createErrorResponse statusCode phrase = defaultResponse
89 { responseStatusCode = statusCode
90 { responseStatusCode = statusCode
90 , responsePhrase = phrase
91 , responsePhrase = phrase
91 , responseHeaders = M.singleton (B.pack "Content-Type") (B.pack "text/html")
92 , responseHeaders = M.singleton (B.pack "Content-Type") (B.pack "text/html")
93+ , responseBody = B.pack $
92− , responseBody = B.pack $ "<html> <head> <title>" ++ show statusCode ++ "</title> </head>"
94+ "<html> <head> <title>" ++ show statusCode ++ "</title> </head>"
93− ++ "<body> <h1>" ++ show statusCode ++ "</h1>\n"
95+ ++ "<body> <h1>" ++ show statusCode ++ "</h1>\n"
94− ++ "<p>" ++ (B.unpack phrase) ++ "</p> </body> </html>"
96+ ++ "<p>" ++ (B.unpack phrase) ++ "</p> </body> </html>"
97-- | Create a simple get response.
99-- | Create a simple get response.
@@ -100,48 +102,56 @@ createGetResponse request = do
100 -- Construct the complete fileName of the requested resource.
102 -- Construct the complete fileName of the requested resource.
101 config <- ask
103 config <- ask
102 let uri = B.unpack (requestURI request)
104 let uri = B.unpack (requestURI request)
105+ log' = writeChan (logChannel config)
103 isDirectory <- liftIO $ doesDirectoryExist $ documentRoot config ++ uri
106 isDirectory <- liftIO $ doesDirectoryExist $ documentRoot config ++ uri
104− let fileName = (documentRoot config) ++ if isDirectory then uri ++ "/index.html"
108+ (documentRoot config) ++ if isDirectory then uri ++ "/index.html"
105− else uri
109+ else uri
107 create200 = do
111 create200 = do
108 body <- B.readFile fileName
112 body <- B.readFile fileName
109− let headers = [ (B.pack "Content-Length", B.pack $ show $ B.length body)
114+ [ (B.pack "Content-Length", B.pack $ show $ B.length body)
110− ] ++ getMIMEHeader fileName
115+ ] ++ getMIMEHeader fileName
111− return $ defaultResponse { responseStatusCode = 200
116+ return $ defaultResponse
117+ { responseStatusCode = 200
112− , responsePhrase = B.pack "OK"
118+ , responsePhrase = B.pack "OK"
113− , responseHeaders = (responseHeaders defaultResponse)
119+ , responseHeaders = (responseHeaders defaultResponse)
114− `M.union` M.fromList headers
120+ `M.union` M.fromList headers
115− , responseBody = body
121+ , responseBody = body
118 -- Called when an error occurs during the creation of a 200 response.
124 -- Called when an error occurs during the creation of a 200 response.
119− create500 e = do writeChan (logChannel config) $ "Internal Error: " ++ show e
126+ log' $ "Internal Error: " ++ show e
120− return $ createErrorResponse 500 (B.pack "Internal Server Error")
127+ return $ createErrorResponse 500 (B.pack "Internal Server Error")
122 -- Send back the page if found.
129 -- Send back the page if found.
123 exists <- liftIO $ doesFileExist fileName
130 exists <- liftIO $ doesFileExist fileName
124− if exists then do response <- liftIO $ catch create200 create500
132+ then do response <- liftIO $ catch create200 create500
125− return response
133+ return response
126− else do liftIO $ writeChan (logChannel config) $ "Not Found: " ++ fileName
134+ else do liftIO $ log' $ "Not Found: " ++ fileName
127− return $ createErrorResponse 404 (B.pack "Not Found")
135+ return $ createErrorResponse 404 (B.pack "Not Found")
129-- | Get the mime header for a certain filename. This is based on the extension
137-- | Get the mime header for a certain filename. This is based on the extension
130-- of the given 'FilePath'.
138-- of the given 'FilePath'.
131getMIMEHeader :: FilePath -> [(B.ByteString, B.ByteString)]
139getMIMEHeader :: FilePath -> [(B.ByteString, B.ByteString)]
140+getMIMEHeader fileName =
132−getMIMEHeader fileName = case result of (Just x) -> [(B.pack "Content-Type", B.pack x)]
141+ case result of (Just x) -> [(B.pack "Content-Type", B.pack x)]
133− Nothing -> []
142+ Nothing -> []
134− where result = lookup (takeExtension fileName) [ (".css", "text/css")
144+ result = lookup (takeExtension fileName) [ (".css", "text/css")
135− , (".gif", "image/gif")
145+ , (".gif", "image/gif")
136− , (".htm", "text/html")
146+ , (".htm", "text/html")
137− , (".html", "text/html")
147+ , (".html", "text/html")
138− , (".jpeg", "image/jpeg")
148+ , (".jpeg", "image/jpeg")
139− , (".jpg", "image/jpeg")
149+ , (".jpg", "image/jpeg")
140− , (".js", "text/javascript")
150+ , (".js", "text/javascript")
141− , (".png", "image/png")
151+ , (".png", "image/png")
142− , (".txt", "text/plain")
152+ , (".txt", "text/plain")
143− , (".xml", "text/xml")
153+ , (".xml", "text/xml")
146-- | Respond to an incoming request.
156-- | Respond to an incoming request.
147respond :: Handle -> Server ()
157respond :: Handle -> Server ()
@@ -152,24 +162,28 @@ respond handle = do
153 -- Generate some output.
163 -- Generate some output.
154 config <- ask
164 config <- ask
155− liftIO $ writeChan (logChannel config) $ show request ++ " => " ++ show response
165+ liftIO $ writeChan (logChannel config)
166+ $ show request ++ " => " ++ show response
157 -- Send the response back to the handle.
168 -- Send the response back to the handle.
158 liftIO $ putResponse response
169 liftIO $ putResponse response
159− where putResponse response = do B.hPutStr handle $ B.intercalate (B.pack " ")
171+ putResponse response = do B.hPutStr handle $ B.intercalate (B.pack " ")
160− [ responseVersion response
172+ [ responseVersion response
161− , B.pack $ show $ responseStatusCode response
173+ , B.pack $ show $ responseStatusCode response
162− , responsePhrase response
174+ , responsePhrase response
164− hPutStr handle "\r\n"
176+ hPutStr handle "\r\n"
165− mapM_ putHeader (M.toList $ responseHeaders response)
178+ (M.toList $ responseHeaders response)
166− hPutStr handle "\r\n"
179+ hPutStr handle "\r\n"
167− B.hPutStr handle $ responseBody response
180+ B.hPutStr handle $ responseBody response
168− hPutStr handle "\r\n"
181+ hPutStr handle "\r\n"
169− hClose handle
182+ hClose handle
184+ putHeader (key, value) =
171− putHeader (key, value) = B.hPutStr handle $ key `B.append` B.pack ": "
185+ B.hPutStr handle $ key `B.append` B.pack ": "
172− `B.append` value `B.append` B.pack "\r\n"
186+ `B.append` value `B.append` B.pack "\r\n"
174-- | Start a simple http server on the given 'PortNumber', serving the given
188-- | Start a simple http server on the given 'PortNumber', serving the given
175-- directory.
189-- directory.
@@ -194,5 +208,3 @@ simpleServer port root = do
194 writeChan logChan $ "Starting hakyll server on port " ++ show port ++ "..."
208 writeChan logChan $ "Starting hakyll server on port " ++ show port ++ "..."
195 socket <- listenOn (PortNumber port)
209 socket <- listenOn (PortNumber port)
196 forever (listen socket)
210 forever (listen socket)