packages feed

minion-wai-extra-0.1.0.0: src/Web/Minion/Examples/Multipart.hs

module Web.Minion.Examples.Multipart (app) where

import Control.Monad.IO.Class (MonadIO (..))
import Control.Monad.Trans.Resource (ResourceT, runResourceT)
import Data.ByteString.Lazy qualified as Bytes.Lazy
import Data.Text (Text)
import Data.Text qualified as Text
import Data.Text.Encoding qualified as Text.Encode
import Data.Void
import Network.Wai.Parse (FileInfo (..))
import System.Environment (getArgs)
import Web.Minion
import Web.Minion.Request.Multipart

app :: IO (ApplicationM IO)
app =
  getArgs >>= \case
    ["tmp"] -> do
      putStrLn "Tmp mode running"
      pure do
        serve apiMem
    ["mem"] -> do
      putStrLn "Mem mode running"
      pure do
        \req resp -> runResourceT (serve apiTmp req resp)
    _ -> error "Mode required"

data ReportMem = ReportMem
  { reporter :: Text
  , report :: Bytes.Lazy.ByteString
  }

data ReportTmp = ReportTmp
  { reporter :: Text
  , report :: FilePath
  }

instance FromMultipart Mem ReportMem where
  fromMultipart =
    ReportMem
      <$> (Text.Encode.decodeUtf8 <$> getParam "reporter")
      <*> (fileContent <$> getFile "report")

instance FromMultipart Tmp ReportTmp where
  fromMultipart =
    ReportTmp
      <$> (Text.Encode.decodeUtf8 <$> getParam "reporter")
      <*> (fileContent <$> getFile "report")

apiMem :: Router Void IO
apiMem =
  "api"
    /> "multipart"
    /> multipartBody @Mem @ReportMem
    .> handle @NoBody POST endpoint
 where
  endpoint ReportMem{..} = do
    putStrLn $ "Reporter: " <> Text.unpack reporter
    putStrLn $ "Report size: " <> show (Bytes.Lazy.length report)
    pure NoBody

-- multipartBody @Tmp requires MonadResource
apiTmp :: Router Void (ResourceT IO)
apiTmp =
  "api"
    /> "multipart"
    /> multipartBody @Tmp @ReportTmp
    .> handle @NoBody POST endpoint
 where
  endpoint ReportTmp{..} = liftIO do
    putStrLn $ "Reporter: " <> Text.unpack reporter
    reportSize <- Bytes.Lazy.length <$> Bytes.Lazy.readFile report
    putStrLn $ "Report size: " <> show reportSize
    pure NoBody