1
1
{-# OPTIONS_GHC -fno-warn-orphans #-}
2
2
module Application
3
- ( makeApplication
4
- , getApplicationDev
3
+ ( getApplicationDev
4
+ , appMain
5
+ , develMain
5
6
, makeFoundation
7
+ -- * for DevelMain
8
+ , getApplicationRepl
9
+ , shutdownApp
10
+ -- * for GHCI
11
+ , handler
12
+ , db
6
13
) where
7
14
15
+ import Control.Monad.Logger (liftLoc , runLoggingT )
16
+ import Database.Persist.Postgresql (createPostgresqlPool , pgConnStr ,
17
+ pgPoolSize , runSqlPool )
8
18
import Import
9
- import Settings
10
- import Yesod.Auth
11
- import Yesod.Default.Config
12
- import Yesod.Default.Main
19
+ import Language.Haskell.TH.Syntax (qLocation )
20
+ import Network.Wai.Handler.Warp (Settings , defaultSettings ,
21
+ defaultShouldDisplayException ,
22
+ runSettings , setHost ,
23
+ setOnException , setPort , getPort )
24
+ import Network.Wai.Middleware.RequestLogger (Destination (Logger ),
25
+ IPAddrSource (.. ),
26
+ OutputFormat (.. ), destination ,
27
+ mkRequestLogger , outputFormat )
28
+ import System.Log.FastLogger (defaultBufSize , newStdoutLoggerSet ,
29
+ toLogStr )
13
30
import Yesod.Default.Handlers
14
- import Network.Wai.Middleware.RequestLogger
15
- ( mkRequestLogger , outputFormat , OutputFormat (.. ), IPAddrSource (.. ), destination
16
- )
17
- import qualified Network.Wai.Middleware.RequestLogger as RequestLogger
18
- import qualified Database.Persist
19
- import Database.Persist.Sql (runMigration )
20
- import Network.HTTP.Conduit (newManager , conduitManagerSettings )
21
- import Control.Monad.Logger (runLoggingT )
22
- import System.Log.FastLogger (newStdoutLoggerSet , defaultBufSize )
23
- import Network.Wai.Logger (clockDateCacher )
24
- import Data.Default (def )
25
- import Yesod.Core.Types (loggerSet , Logger (Logger ))
26
31
27
32
-- Import all relevant handler modules here.
28
33
import Handler.Admin
@@ -38,56 +43,135 @@ import Handler.Sitemap
38
43
-- comments there for more details.
39
44
mkYesodDispatch " App" resourcesApp
40
45
41
- -- This function allocates resources (such as a database connection pool),
42
- -- performs initialization and creates a WAI application . This is also the
43
- -- place to put your migrate statements to have automatic database
46
+ -- | This function allocates resources (such as a database connection pool),
47
+ -- performs initialization and return a foundation datatype value . This is also
48
+ -- the place to put your migrate statements to have automatic database
44
49
-- migrations handled by Yesod.
45
- makeApplication :: AppConfig DefaultEnv Extra -> IO Application
46
- makeApplication conf = do
47
- foundation <- makeFoundation conf
50
+ makeFoundation :: AppSettings -> IO App
51
+ makeFoundation appSettings = do
52
+ -- Some basic initializations: HTTP connection manager, logger, and static
53
+ -- subsite.
54
+ appHttpManager <- newManager
55
+ appLogger <- newStdoutLoggerSet defaultBufSize >>= makeYesodLogger
56
+ appStatic <-
57
+ (if appMutableStatic appSettings then staticDevel else static)
58
+ (appStaticDir appSettings)
48
59
49
- -- Initialize the logging middleware
60
+ -- We need a log function to create a connection pool. We need a connection
61
+ -- pool to create our foundation. And we need our foundation to get a
62
+ -- logging function. To get out of this loop, we initially create a
63
+ -- temporary foundation without a real connection pool, get a log function
64
+ -- from there, and then create the real foundation.
65
+ let mkFoundation appConnPool = App {.. }
66
+ tempFoundation = mkFoundation $ error " connPool forced in tempFoundation"
67
+ logFunc = messageLoggerSource tempFoundation appLogger
68
+
69
+ -- Create the database connection pool
70
+ pool <- flip runLoggingT logFunc $ createPostgresqlPool
71
+ (pgConnStr $ appDatabaseConf appSettings)
72
+ (pgPoolSize $ appDatabaseConf appSettings)
73
+
74
+ -- Perform database migration using our application's logging settings.
75
+ runLoggingT (runSqlPool (runMigration migrateAll) pool) logFunc
76
+
77
+ -- Return the foundation
78
+ return $ mkFoundation pool
79
+
80
+ -- | Convert our foundation to a WAI Application by calling @toWaiAppPlain@ and
81
+ -- applyng some additional middlewares.
82
+ makeApplication :: App -> IO Application
83
+ makeApplication foundation = do
50
84
logWare <- mkRequestLogger def
51
85
{ outputFormat =
52
- if development
86
+ if appDetailedRequestLogging $ appSettings foundation
53
87
then Detailed True
54
- else Apache FromSocket
55
- , destination = RequestLogger. Logger $ loggerSet $ appLogger foundation
88
+ else Apache
89
+ (if appIpFromHeader $ appSettings foundation
90
+ then FromFallback
91
+ else FromSocket )
92
+ , destination = Logger $ loggerSet $ appLogger foundation
56
93
}
57
94
58
95
-- Create the WAI application and apply middlewares
59
- app <- toWaiAppPlain foundation
60
- return $ logWare app
61
-
62
- -- | Loads up any necessary settings, creates your foundation datatype, and
63
- -- performs some initialization.
64
- makeFoundation :: AppConfig DefaultEnv Extra -> IO App
65
- makeFoundation conf = do
66
- manager <- newManager conduitManagerSettings
67
- s <- staticSite
68
- dbconf <- withYamlEnvironment " config/postgresql.yml" (appEnv conf)
69
- Database.Persist. loadConfig >>=
70
- Database.Persist. applyEnv
71
- p <- Database.Persist. createPoolConfig (dbconf :: Settings. PersistConf )
72
-
73
- loggerSet' <- newStdoutLoggerSet defaultBufSize
74
- (getter, _) <- clockDateCacher
75
-
76
- let logger = Yesod.Core.Types. Logger loggerSet' getter
77
- foundation = App conf s p manager dbconf logger
96
+ appPlain <- toWaiAppPlain foundation
97
+ return $ logWare $ defaultMiddlewaresNoLogging appPlain
78
98
79
- -- Perform database migration using our application's logging settings.
80
- runLoggingT
81
- (Database.Persist. runPool dbconf (runMigration migrateAll) p)
82
- (messageLoggerSource foundation logger)
83
-
84
- return foundation
85
-
86
- -- for yesod devel
87
- getApplicationDev :: IO (Int , Application )
88
- getApplicationDev =
89
- defaultDevelApp loader makeApplication
90
- where
91
- loader = Yesod.Default.Config. loadConfig (configSettings Development )
92
- { csParseExtra = parseExtra
93
- }
99
+ -- | Warp settings for the given foundation value.
100
+ warpSettings :: App -> Settings
101
+ warpSettings foundation =
102
+ setPort (appPort $ appSettings foundation)
103
+ $ setHost (appHost $ appSettings foundation)
104
+ $ setOnException (\ _req e ->
105
+ when (defaultShouldDisplayException e) $ messageLoggerSource
106
+ foundation
107
+ (appLogger foundation)
108
+ $ (qLocation >>= liftLoc)
109
+ " yesod"
110
+ LevelError
111
+ (toLogStr $ " Exception from Warp: " ++ show e))
112
+ defaultSettings
113
+
114
+
115
+
116
+ -- | For yesod devel, return the Warp settings and WAI Application.
117
+ getApplicationDev :: IO (Settings , Application )
118
+ getApplicationDev = do
119
+ settings <- getAppSettings
120
+ foundation <- makeFoundation settings
121
+ wsettings <- getDevSettings $ warpSettings foundation
122
+ app <- makeApplication foundation
123
+ return (wsettings, app)
124
+
125
+
126
+ getAppSettings :: IO AppSettings
127
+ getAppSettings = loadAppSettings [configSettingsYml] [] useEnv
128
+
129
+ -- | main function for use by yesod devel
130
+ develMain :: IO ()
131
+ develMain = develMainHelper getApplicationDev
132
+
133
+ -- | The @main@ function for an executable running this site.
134
+ appMain :: IO ()
135
+ appMain = do
136
+ -- Get the settings from all relevant sources
137
+ settings <- loadAppSettingsArgs
138
+ -- fall back to compile-time values, set to [] to require values at runtime
139
+ [configSettingsYmlValue]
140
+
141
+ -- allow environment variables to override
142
+ useEnv
143
+
144
+ -- Generate the foundation from the settings
145
+ foundation <- makeFoundation settings
146
+
147
+ -- Generate a WAI Application from the foundation
148
+ app <- makeApplication foundation
149
+
150
+ -- Run the application with Warp
151
+ runSettings (warpSettings foundation) app
152
+ --------------------------------------------------------------
153
+ -- Functions for DevelMain.hs (a way to run the app from GHCi)
154
+ --------------------------------------------------------------
155
+ getApplicationRepl :: IO (Int , App , Application )
156
+ getApplicationRepl = do
157
+ settings <- getAppSettings
158
+ foundation <- makeFoundation settings
159
+ wsettings <- getDevSettings $ warpSettings foundation
160
+ app1 <- makeApplication foundation
161
+ return (getPort wsettings, foundation, app1)
162
+
163
+ shutdownApp :: App -> IO ()
164
+ shutdownApp _ = return ()
165
+
166
+
167
+ ---------------------------------------------
168
+ -- Functions for use in development with GHCi
169
+ ---------------------------------------------
170
+
171
+ -- | Run a handler
172
+ handler :: Handler a -> IO a
173
+ handler h = getAppSettings >>= makeFoundation >>= flip unsafeHandler h
174
+
175
+ -- | Run DB queries
176
+ db :: ReaderT SqlBackend (HandlerT App IO ) a -> IO a
177
+ db = handler . runDB
0 commit comments