{-# LANGUAGE OverloadedStrings #-} module Server where import Control.Monad import Crypto.Hash (Context, SHA1) -- cryptonite import qualified Crypto.Hash as CH import Data.ByteString (ByteString) import qualified Data.ByteString as B import Data.ByteString.Builder (byteString) import qualified Data.ByteString.Char8 as C8 import Network.HTTP.Types import Network.HTTP2.Server server :: Server server req _aux sendResponse = case requestMethod req of Just "GET" | requestPath req == Just "/" -> sendResponse responseHello [] Just "POST" -> sendResponse (responseEcho req) [] _ -> sendResponse response404 [] responseHello :: Response responseHello = responseBuilder ok200 header body where header = [("Content-Type", "text/plain")] body = byteString "Hello, world!\n" response404 :: Response response404 = responseBuilder notFound404 header body where header = [("Content-Type", "text/plain")] body = byteString "Not found\n" responseEcho :: Request -> Response responseEcho req = setResponseTrailersMaker h2rsp maker where h2rsp = responseStreaming ok200 header streamingBody header = [("Content-Type", "text/plain")] streamingBody write _flush = loop where loop = do bs <- getRequestBodyChunk req unless (B.null bs) $ do void $ write $ byteString bs loop maker = trailersMaker (CH.hashInit :: Context SHA1) -- Strictness is important for Context. trailersMaker :: Context SHA1 -> Maybe ByteString -> IO NextTrailersMaker trailersMaker ctx Nothing = return $ Trailers [("X-SHA1", sha1)] where sha1 = C8.pack $ show $ CH.hashFinalize ctx trailersMaker ctx (Just bs) = return $ NextTrailersMaker $ trailersMaker ctx' where ctx' = CH.hashUpdate ctx bs