packages feed

heyefi-0.1.1.0: src/HEyefi/Main.hs

{-# LANGUAGE OverloadedStrings #-}

module Main where

import           HEyefi.CommandLineOptions (handleOptionsThenMaybe)
import           HEyefi.Config (monitorConfig, newConfig, runWithConfig)
import           HEyefi.Constant (port, configPath)
import           HEyefi.Log (logInfoIO, logDebug)
import           HEyefi.Soap (handleSoapAction, soapAction)
import           HEyefi.Strings
import           HEyefi.Types (SharedConfig, HEyefiApplication)
import           HEyefi.UploadPhoto (handleUpload)

import           Control.Concurrent (forkIO)
import           Control.Concurrent.STM (
    newTVar
  , atomically
  , writeTVar
  , TVar
  , readTVar )
import           Control.Monad (forever)
import qualified Data.ByteString as B
import           Data.ByteString.Lazy (fromStrict)
import qualified Data.ByteString.Lazy as BL
import           Data.Maybe (isJust, fromJust, isNothing)
import           Network.Wai (
    Application
  , Request
  , pathInfo
  , requestBody
  , requestMethod
  , requestHeaders )
import           Network.Wai.Handler.Warp (run)
import           System.Posix.Signals (installHandler, sigHUP, Handler( Catch ))

handleHup :: TVar (Maybe Int) -> IO ()
handleHup wakeSig = atomically (writeTVar wakeSig (Just 1))

runHeyefi :: IO ()
runHeyefi = do
  wakeSig <- atomically (newTVar Nothing)
  sharedConfig <- newConfig
  _ <- installHandler sigHUP (Catch $ handleHup wakeSig) Nothing

  _ <- forkIO (forever
               (do
                   c <- atomically (readTVar sharedConfig)
                   runWithConfig c (
                     monitorConfig configPath sharedConfig wakeSig)))

  logInfoIO (listeningOnPort (show port))
  run port (app sharedConfig)

main :: IO ()
main = handleOptionsThenMaybe runHeyefi

app :: SharedConfig -> Application
app sharedConfig req f = do
  config <- atomically (readTVar sharedConfig)
  body <- getWholeRequestBody req
  (result, config') <- runWithConfig config (do
                  logDebug (show (pathInfo req))
                  logDebug (show (requestHeaders req))
                  dispatchRequest (fromStrict body) req f)
  atomically (writeTVar sharedConfig config')
  return result

dispatchRequest :: BL.ByteString -> HEyefiApplication
dispatchRequest body req f
  | requestMethod req == "POST" &&
    pathInfo req == ["api","soap","eyefilm","v1","upload"] &&
    isNothing (soapAction req) =
      handleUpload body req f
dispatchRequest body req f
  | requestMethod req == "POST" &&
    isJust (soapAction req) =
      handleSoapAction (fromJust (soapAction req)) body req f
dispatchRequest _ _ _ = error didNotMatchDispatch

getWholeRequestBody :: Request -> IO B.ByteString
getWholeRequestBody request = do
  r <- requestBody request
  if r == B.empty
    then return B.empty
    else do
     rest <- getWholeRequestBody request
     return (B.append r rest)