yesod devel displays "app not loaded" message

In order to achieve this, yesod devel listens on port 3000 and reverse
proxies to port 3001. An environment variable is set to tell the app to
listen on port 3001.
This commit is contained in:
Michael Snoyman 2012-10-30 17:02:17 +02:00
parent b961fb8d5f
commit 309d3c0f26
5 changed files with 44 additions and 6 deletions

View File

@ -15,6 +15,9 @@ import Network.Wai.Middleware.Gzip (gzip, GzipFiles (GzipCacheFolder), gzipFiles
import Network.Wai.Middleware.Autohead (autohead) import Network.Wai.Middleware.Autohead (autohead)
import Network.Wai.Middleware.Jsonp (jsonp) import Network.Wai.Middleware.Jsonp (jsonp)
import Control.Monad (when) import Control.Monad (when)
import System.Environment (getEnvironment)
import Data.Maybe (fromMaybe)
import Safe (readMay)
#ifndef WINDOWS #ifndef WINDOWS
import qualified System.Posix.Signals as Signal import qualified System.Posix.Signals as Signal
@ -81,7 +84,9 @@ defaultDevelApp
-> IO (Int, Application) -> IO (Int, Application)
defaultDevelApp load getApp = do defaultDevelApp load getApp = do
conf <- load conf <- load
let p = appPort conf env <- getEnvironment
putStrLn $ "Devel application launched: http://localhost:" ++ show p let p = fromMaybe (appPort conf) $ lookup "PORT" env >>= readMay
pdisplay = fromMaybe p $ lookup "DISPLAY_PORT" env >>= readMay
putStrLn $ "Devel application launched: http://localhost:" ++ show pdisplay
app <- getApp conf app <- getApp conf
return (p, app) return (p, app)

View File

@ -1,5 +1,5 @@
name: yesod-default name: yesod-default
version: 1.1.0.2 version: 1.1.1
license: MIT license: MIT
license-file: LICENSE license-file: LICENSE
author: Patrick Brisbin author: Patrick Brisbin
@ -34,6 +34,7 @@ library
, unordered-containers , unordered-containers
, hamlet >= 1.1 && < 1.2 , hamlet >= 1.1 && < 1.2
, data-default , data-default
, safe
if !os(windows) if !os(windows)
build-depends: unix build-depends: unix

View File

@ -41,6 +41,7 @@ import Data.Maybe (fromMaybe)
import qualified Data.Set as Set import qualified Data.Set as Set
import System.Directory import System.Directory
import System.Environment (getEnvironment)
import System.Exit (ExitCode (..), import System.Exit (ExitCode (..),
exitFailure, exitFailure,
exitSuccess) exitSuccess)
@ -62,7 +63,8 @@ import System.Process (ProcessHandle,
readProcess, readProcess,
runInteractiveProcess, runInteractiveProcess,
system, system,
terminateProcess) terminateProcess,
env)
import System.Timeout (timeout) import System.Timeout (timeout)
import Build (getDeps, isNewerThan, import Build (getDeps, isNewerThan,
@ -72,6 +74,12 @@ import GhcBuild (buildPackage,
import qualified Config as GHC import qualified Config as GHC
import SrcLoc (Located) import SrcLoc (Located)
import Network.HTTP.ReverseProxy (waiProxyTo, ProxyDest (ProxyDest))
import Network (withSocketsDo)
import Network.Wai (responseLBS)
import Network.HTTP.Types (status200)
import Network.Wai.Handler.Warp (run)
import Network.HTTP.Conduit (newManager, def)
lockFile :: DevelOpts -> FilePath lockFile :: DevelOpts -> FilePath
lockFile _opts = "yesod-devel/devel-terminate" lockFile _opts = "yesod-devel/devel-terminate"
@ -108,8 +116,26 @@ cabalCommand opts | isCabalDev opts = "cabal-dev"
defaultDevelOpts :: DevelOpts defaultDevelOpts :: DevelOpts
defaultDevelOpts = DevelOpts False False False (-1) Nothing Nothing Nothing defaultDevelOpts = DevelOpts False False False (-1) Nothing Nothing Nothing
-- | Run a reverse proxy from port 3000 to 3001. If there is no response on
-- 3001, give an appropriate message to the user.
reverseProxy :: IO ()
reverseProxy = withSocketsDo $ do
manager <- newManager def
run 3000 $ waiProxyTo
(const $ return $ Right $ ProxyDest "localhost" 3001)
onExc
manager
where
onExc _ _ = return $ responseLBS
status200
[ ("content-type", "text/html")
, ("Refresh", "1")
]
"<h1>App not ready, please refresh</h1>"
devel :: DevelOpts -> [String] -> IO () devel :: DevelOpts -> [String] -> IO ()
devel opts passThroughArgs = withManager $ \manager -> do devel opts passThroughArgs = withManager $ \manager -> do
_ <- forkIO reverseProxy
checkDevelFile checkDevelFile
writeLock opts writeLock opts
@ -162,7 +188,10 @@ devel opts passThroughArgs = withManager $ \manager -> do
liftIO $ putStrLn liftIO $ putStrLn
$ if verbose opts then "Starting development server: runghc " ++ L.unwords devArgs $ if verbose opts then "Starting development server: runghc " ++ L.unwords devArgs
else "Starting development server..." else "Starting development server..."
(_,_,_,ph) <- liftIO $ createProcess $ proc "runghc" devArgs env0 <- liftIO getEnvironment
(_,_,_,ph) <- liftIO $ createProcess (proc "runghc" devArgs)
{ env = Just $ ("PORT", "3001") : ("DISPLAY_PORT", "3000") : env0
}
derefMap <- get derefMap <- get
watchTid <- liftIO . forkIO . try_ $ flip evalStateT derefMap $ do watchTid <- liftIO . forkIO . try_ $ flip evalStateT derefMap $ do
loop list loop list

View File

@ -55,7 +55,7 @@ library
, yesod-core >= 1.1.2 && < 1.2 , yesod-core >= 1.1.2 && < 1.2
, yesod-auth >= 1.1 && < 1.2 , yesod-auth >= 1.1 && < 1.2
, yesod-static >= 1.1 && < 1.2 , yesod-static >= 1.1 && < 1.2
, yesod-default >= 1.1 && < 1.2 , yesod-default >= 1.1.1 && < 1.2
, yesod-form >= 1.1 && < 1.2 , yesod-form >= 1.1 && < 1.2
, yesod-test >= 0.3 && < 0.4 , yesod-test >= 0.3 && < 0.4
, clientsession >= 0.8 && < 0.9 , clientsession >= 0.8 && < 0.9

View File

@ -138,6 +138,9 @@ executable yesod
, fsnotify >= 0.0 && < 0.1 , fsnotify >= 0.0 && < 0.1
, split >= 0.2 && < 0.3 , split >= 0.2 && < 0.3
, lifted-base , lifted-base
, http-reverse-proxy >= 0.1.0.4
, network
, http-conduit
ghc-options: -Wall -threaded ghc-options: -Wall -threaded
main-is: main.hs main-is: main.hs