module Network.HTTP.Proxy.Server (proxyMain
,Settings (..)
,Cache (..)
,Default(..)) where
import Network.HTTP hiding (port)
import Network.HTTP.Server hiding (Response, Request)
import Network.HTTP.Server.Logger
import Data.Default.Class
import Network.HostName
proxyMain :: forall s. HStream s => Settings s -> IO ()
proxyMain settings =
do hname <- case hostname settings of
Nothing -> getHostName
Just hostn -> return hostn
let config = defaultConfig {srvPort = fromInteger $ portnum settings
,srvHost = hname
,srvLog = mylogger}
putStrLn "Proxy server started on port 3128\n"
serverWith config (proxyHandler settings)
mylogger = stdLogger
proxyHandler :: HStream s => Settings s -> Handler s
proxyHandler settings _ _ request =
isAuthorized settings request >>=
\authorized -> if authorized then processRequest settings request
else errorProxyUnauthorized
processRequest :: HStream s => Settings s -> Request s -> IO (Response s)
processRequest settings request = do
modRequest <- requestModifier settings request
mCachedResponse <- queryCache (cache settings) modRequest
case mCachedResponse of
Just response -> return response
Nothing -> do
response <- fetch request
modResponse <- responseModifier settings request response
recordInCache (cache settings) request modResponse
return modResponse
fetch :: HStream s => Request s -> IO (Response s)
fetch request = do
result <- simpleHTTP request
case result of
Left err -> do putStrLn ("Connection error: " ++ show err)
errorInternalServerError
Right rsp -> return rsp
data Settings s =
Settings {requestModifier :: Request s -> IO (Request s)
,responseModifier :: Request s -> Response s -> IO (Response s)
,cache :: Cache s
,isAuthorized :: Request s -> IO Bool
,logger :: String -> IO ()
,portnum :: Integer
,hostname :: Maybe String
}
instance Default (Settings s) where
def = Settings {requestModifier = return
,responseModifier = \_ -> return
,cache = def
,isAuthorized = return . const True
,logger = \_ -> return ()
,portnum = 3128
,hostname = Nothing}
data Cache s = Cache {queryCache :: Request s -> IO (Maybe (Response s))
,recordInCache :: Request s -> Response s -> IO ()
}
instance Default (Cache s) where
def = Cache {queryCache = return . const Nothing
,recordInCache = \_ -> return . const ()}
errorInternalServerError :: HStream s => IO (Response s)
errorInternalServerError = return $ err_response InternalServerError
errorProxyUnauthorized :: HStream s => IO (Response s)
errorProxyUnauthorized = return $ err_response ProxyAuthenticationRequired
errorBadRequest :: HStream s => IO (Response s)
errorBadRequest = return $ err_response BadRequest