packages feed

keter 1.8.4 → 1.9

raw patch · 6 files changed

+55/−20 lines, 6 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Keter.Proxy: [psLogException] :: ProxySettings -> Request -> SomeException -> IO ()
+ Keter.Proxy: [psProxyException] :: ProxySettings -> ByteString
+ Keter.Types: ProxyException :: Request -> SomeException -> LogMessage
+ Keter.Types: [kconfigProxyException] :: KeterConfig -> !Maybe FilePath
+ Keter.Types.Common: ProxyException :: Request -> SomeException -> LogMessage
+ Keter.Types.V10: [kconfigProxyException] :: KeterConfig -> !Maybe FilePath
- Keter.Proxy: MkProxySettings :: (ByteString -> IO (Maybe (ProxyAction, Credentials))) -> !Manager -> !KeterConfig -> (ByteString -> ByteString) -> ByteString -> ProxySettings
+ Keter.Proxy: MkProxySettings :: (ByteString -> IO (Maybe (ProxyAction, Credentials))) -> !Manager -> !KeterConfig -> (ByteString -> ByteString) -> ByteString -> ByteString -> (Request -> SomeException -> IO ()) -> ProxySettings
- Keter.Proxy: makeSettings :: KeterConfig -> HostManager -> IO ProxySettings
+ Keter.Proxy: makeSettings :: (LogMessage -> IO ()) -> KeterConfig -> HostManager -> IO ProxySettings
- Keter.Types: KeterConfig :: FilePath -> PortSettings -> !NonEmptyVector ListeningPort -> Maybe Text -> !Vector (Stanza ()) -> Bool -> !Int -> !Int -> !Map Text Text -> !Int -> !Maybe Port -> !Maybe FilePath -> !Maybe FilePath -> KeterConfig
+ Keter.Types: KeterConfig :: FilePath -> PortSettings -> !NonEmptyVector ListeningPort -> Maybe Text -> !Vector (Stanza ()) -> Bool -> !Int -> !Int -> !Map Text Text -> !Int -> !Maybe Port -> !Maybe FilePath -> !Maybe FilePath -> !Maybe FilePath -> KeterConfig
- Keter.Types.V10: KeterConfig :: FilePath -> PortSettings -> !NonEmptyVector ListeningPort -> Maybe Text -> !Vector (Stanza ()) -> Bool -> !Int -> !Int -> !Map Text Text -> !Int -> !Maybe Port -> !Maybe FilePath -> !Maybe FilePath -> KeterConfig
+ Keter.Types.V10: KeterConfig :: FilePath -> PortSettings -> !NonEmptyVector ListeningPort -> Maybe Text -> !Vector (Stanza ()) -> Bool -> !Int -> !Int -> !Map Text Text -> !Int -> !Maybe Port -> !Maybe FilePath -> !Maybe FilePath -> !Maybe FilePath -> KeterConfig

Files

ChangeLog.md view
@@ -1,6 +1,18 @@+## 1.9+++ Update status code of missing host responses.+  They now emit a 502 on missing host, and 404 on host not found++ Always restart keter in the nix config for systemd.+  It turns out that keter may exit with exit code 0 under load testing.+  Changing from on-failure to always in systemd should bring it back up.++ Squash proxy exceptions if they occur and serve a default or custom error+  response.+  Emits the exception to the log.++ Add incoming folder to the CI build.+ ## 1.8.4 -+ Get rid of ominious warning at the top, "Hackage documentation generation is not reliable.."++ Get rid of ominious warning at the top.   Thanks to /u/Opposite-Platypus-99   for pointing this out. 
Keter/Main.hs view
@@ -70,7 +70,7 @@     log StartWatching     startWatching kc appMan log     log StartListening-    startListening kc hostman+    startListening log kc hostman  -- | Load up Keter config. withConfig :: FilePath@@ -217,9 +217,9 @@              return [fp1]            ) (filter (\x -> x /= "." && x /= "..") dir) -startListening :: KeterConfig -> HostMan.HostManager -> IO ()-startListening config hostman = do-    settings <- Proxy.makeSettings config hostman+startListening :: (LogMessage -> IO ()) -> KeterConfig -> HostMan.HostManager -> IO ()+startListening log config hostman = do+    settings <- Proxy.makeSettings log config hostman     runAndBlock (kconfigListeners config) $ Proxy.reverseProxy settings  runAndBlock :: NonEmptyVector a
Keter/Proxy.hs view
@@ -48,12 +48,13 @@                                                     setLpsTimeBound,                                                     waiProxyToSettings,                                                     wpsSetIpHeader,+                                                    wpsOnExc,                                                     wpsGetDest) import qualified Network.HTTP.ReverseProxy.Rewrite as Rewrite import           Network.HTTP.Types                (mkStatus, status200,                                                     status301, status302,                                                     status303, status307,-                                                    status404)+                                                    status404, status502) import qualified Network.Wai                       as Wai import           Network.Wai.Application.Static    (defaultFileServerSettings,                                                     ssListing, staticApp)@@ -77,15 +78,17 @@  data ProxySettings = MkProxySettings   { -- | Mapping from virtual hostname to port number.-    psHostLookup  :: ByteString -> IO (Maybe (ProxyAction, TLS.Credentials))-  , psManager     :: !Manager-  , psConfig      :: !KeterConfig-  , psUnkownHost  :: ByteString -> ByteString-  , psMissingHost :: ByteString+    psHostLookup     :: ByteString -> IO (Maybe (ProxyAction, TLS.Credentials))+  , psManager        :: !Manager+  , psConfig         :: !KeterConfig+  , psUnkownHost     :: ByteString -> ByteString+  , psMissingHost    :: ByteString+  , psProxyException :: ByteString+  , psLogException   :: Wai.Request -> SomeException -> IO ()   } -makeSettings :: KeterConfig -> HostMan.HostManager -> IO ProxySettings-makeSettings psConfig@KeterConfig {..} hostman = do+makeSettings :: (LogMessage -> IO ()) -> KeterConfig -> HostMan.HostManager -> IO ProxySettings+makeSettings log psConfig@KeterConfig {..} hostman = do     psManager <- HTTP.newManager HTTP.tlsManagerSettings     psMissingHost <- case kconfigMissingHostResponse of       Nothing -> pure defaultMissingHostBody@@ -93,8 +96,12 @@     psUnkownHost <- case kconfigUnknownHostResponse  of                 Nothing -> pure defaultUnknownHostBody                 Just x -> const <$> taggedReadFile "missing-host-response-file" x+    psProxyException <- case kconfigProxyException of+                Nothing -> pure defaultProxyException+                Just x -> taggedReadFile "proxy-exception-response-file" x     pure $ MkProxySettings{..}     where+        psLogException a b = log $ ProxyException a b         psHostLookup = HostMan.lookupAction hostman . CI.mk  taggedReadFile :: String -> FilePath -> IO ByteString@@ -132,6 +139,8 @@         s { WarpTLS.tlsServerHooks = newHooks{TLS.onServerNameIndication = newOnServerNameIndication}           , WarpTLS.tlsSessionManagerConfig = if session then (Just TLSSession.defaultConfig) else Nothing } ++ withClient :: Bool -- ^ is secure?            -> ProxySettings            -> Wai.Application@@ -144,6 +153,7 @@                 then SIHFromHeader                 else SIHFromSocket         ,  wpsGetDest = Just getDest+        ,  wpsOnExc = handleProxyException psLogException psProxyException         } psManager   where     useHeader :: Bool@@ -273,12 +283,20 @@         , Wai.rawQueryString req         ] +handleProxyException :: (Wai.Request -> SomeException -> IO ()) -> ByteString -> SomeException -> Wai.Application+handleProxyException handleException onexceptBody except req respond = do+  handleException req except+  respond $ missingHostResponse onexceptBody++defaultProxyException :: ByteString+defaultProxyException = "<!DOCTYPE html>\n<html><head><title>Welcome to Keter</title></head><body><h1>Welcome to Keter</h1><p>There was a proxy error, check the keter logs for details.</p></body></html>"+ defaultMissingHostBody :: ByteString defaultMissingHostBody = "<!DOCTYPE html>\n<html><head><title>Welcome to Keter</title></head><body><h1>Welcome to Keter</h1><p>You did not provide a virtual hostname for this request.</p></body></html>"  missingHostResponse :: ByteString -> Wai.Response missingHostResponse missingHost = Wai.responseBuilder-    status200+    status502     [("Content-Type", "text/html; charset=utf-8")]     $ copyByteString missingHost @@ -289,7 +307,7 @@  unknownHostResponse :: ByteString -> ByteString -> Wai.Response unknownHostResponse host body = Wai.responseBuilder-    status200+    status404     [("Content-Type", "text/html; charset=utf-8"),      ("X-Forwarded-Host",       -- if an attacker manages to insert line breaks somehow,
Keter/Types/Common.hs view
@@ -14,6 +14,7 @@     , SomeException     ) where +import qualified Network.Wai                       as Wai import           Control.Exception          (Exception, SomeException) import           Data.Aeson                 (FromJSON, Object, ToJSON,                                              Value (Bool), object, withBool,@@ -94,6 +95,7 @@     | BindCli AddrInfo     | ReceivedCliConnection SockAddr     | KillingApp Port Text+    | ProxyException Wai.Request SomeException  instance Show LogMessage where     show (ProcessCreated f) = "Created process: " ++ f@@ -161,6 +163,7 @@     show StartListening = "Started listening"     show (BindCli addr) = "Bound cli to " <> show addr     show (ReceivedCliConnection peer) = "CLI Connection from " <> show peer+    show (ProxyException req except) = "Got a proxy exception on request " <> show req <> " with exception "  <> show except  data KeterException = CannotParsePostgres FilePath                     | ExitCodeFailure FilePath ExitCode
Keter/Types/V10.hs view
@@ -107,7 +107,8 @@     -- ^ Port for the cli to listen on      , kconfigUnknownHostResponse  :: !(Maybe F.FilePath)-    , kconfigMissingHostResponse :: !(Maybe F.FilePath)+    , kconfigMissingHostResponse  :: !(Maybe F.FilePath)+    , kconfigProxyException       :: !(Maybe F.FilePath)     }  instance ToCurrent KeterConfig where@@ -126,6 +127,7 @@         , kconfigCliPort             = Nothing         , kconfigUnknownHostResponse  = Nothing         , kconfigMissingHostResponse = Nothing+        , kconfigProxyException      = Nothing         }       where         getSSL Nothing = V.empty@@ -152,6 +154,7 @@         , kconfigCliPort             = Nothing         , kconfigUnknownHostResponse  = Nothing         , kconfigMissingHostResponse = Nothing+        , kconfigProxyException      = Nothing         }  instance ParseYamlFile KeterConfig where@@ -175,6 +178,7 @@             <*> o .:? "cli-port"             <*> o .:? "missing-host-response-file"             <*> o .:? "unknown-host-response-file"+            <*> o .:? "proxy-exception-response-file"  -- | Whether we should force redirect to HTTPS routes. type RequiresSecure = Bool
keter.cabal view
@@ -1,6 +1,6 @@ Cabal-version:       >=1.10 Name:                keter-Version:             1.8.4+Version:             1.9 Synopsis:            Web application deployment manager, focusing on Haskell web frameworks Description:     Deployment system for web applications, originally intended for hosting Yesod@@ -9,12 +9,10 @@     * Binds to the main port (usually port 80) and reverse proxies requests to your application based on virtual hostnames.     * Provides SSL support if requested.     * Automatically launches applications, monitors processes, and relaunches any processes which die.-    * Provides graceful redeployment support, by launching a second copy of your application, performing a health check[1], and then switching reverse proxying to the new process.+    * Provides graceful redeployment support, by launching a second copy of your application, performing a health check, and then switching reverse proxying to the new process.     * Management of log files.     .     Keter provides many more advanced features and extension points. It allows configuration of static hosts, redirect rules, management of PostgreSQL databases, and more. It supports a simple bundle format for applications which allows for easy management of your web apps.-    .-    1: The health check happens trough checking if a port is opened. If your app doesn't open a port after 30 seconds it's presumed not healthy and gets a term signal.  Homepage:            http://www.yesodweb.com/ License:             MIT