web: --serve-api disables server-side UI; startup logging cleanups
This commit is contained in:
parent
ff481e88c0
commit
c3da82043b
@ -23,7 +23,7 @@ import Hledger.Web.Handler.UploadR
|
|||||||
import Hledger.Web.Handler.JournalR
|
import Hledger.Web.Handler.JournalR
|
||||||
import Hledger.Web.Handler.RegisterR
|
import Hledger.Web.Handler.RegisterR
|
||||||
import Hledger.Web.Import
|
import Hledger.Web.Import
|
||||||
import Hledger.Web.WebOptions (WebOpts(serve_))
|
import Hledger.Web.WebOptions (WebOpts(serve_,serve_api_))
|
||||||
|
|
||||||
-- This line actually creates our YesodDispatch instance. It is the second half
|
-- This line actually creates our YesodDispatch instance. It is the second half
|
||||||
-- of the call to mkYesodData which occurs in Foundation.hs. Please see the
|
-- of the call to mkYesodData which occurs in Foundation.hs. Please see the
|
||||||
@ -41,7 +41,7 @@ makeApplication opts' j' conf' = do
|
|||||||
logWare <$> toWaiApp foundation
|
logWare <$> toWaiApp foundation
|
||||||
where
|
where
|
||||||
logWare | development = logStdoutDev
|
logWare | development = logStdoutDev
|
||||||
| serve_ opts' = logStdout
|
| serve_ opts' || serve_api_ opts' = logStdout
|
||||||
| otherwise = id
|
| otherwise = id
|
||||||
|
|
||||||
makeFoundation :: AppConfig DefaultEnv Extra -> WebOpts -> IO App
|
makeFoundation :: AppConfig DefaultEnv Extra -> WebOpts -> IO App
|
||||||
|
|||||||
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
module Hledger.Web.Foundation where
|
module Hledger.Web.Foundation where
|
||||||
|
|
||||||
import Control.Monad (join)
|
import Control.Monad (join, when)
|
||||||
import qualified Data.ByteString.Char8 as BC
|
import qualified Data.ByteString.Char8 as BC
|
||||||
import Data.Traversable (for)
|
import Data.Traversable (for)
|
||||||
import Data.IORef (IORef, readIORef, writeIORef)
|
import Data.IORef (IORef, readIORef, writeIORef)
|
||||||
@ -96,7 +96,9 @@ type Form x = Html -> MForm (HandlerT App IO) (FormResult x, Widget)
|
|||||||
instance Yesod App where
|
instance Yesod App where
|
||||||
approot = ApprootMaster $ appRoot . settings
|
approot = ApprootMaster $ appRoot . settings
|
||||||
|
|
||||||
makeSessionBackend _ = Just <$> defaultClientSessionBackend 120 ".hledger-web_client_session_key.aes"
|
makeSessionBackend _ =
|
||||||
|
let sessionexpirysecs = 120
|
||||||
|
in Just <$> defaultClientSessionBackend sessionexpirysecs ".hledger-web_client_session_key.aes"
|
||||||
|
|
||||||
defaultLayout widget = do
|
defaultLayout widget = do
|
||||||
master <- getYesod
|
master <- getYesod
|
||||||
@ -204,6 +206,11 @@ getViewData = do
|
|||||||
Right c -> pure [c]
|
Right c -> pure [c]
|
||||||
return VD {opts, today, j, q, m, qopts, caps}
|
return VD {opts, today, j, q, m, qopts, caps}
|
||||||
|
|
||||||
|
checkServerSideUiEnabled :: Handler ()
|
||||||
|
checkServerSideUiEnabled = do
|
||||||
|
VD{opts=WebOpts{serve_api_}} <- getViewData
|
||||||
|
when serve_api_ $ permissionDenied "server-side UI is disabled due to --serve-api"
|
||||||
|
|
||||||
-- | Find out if the sidebar should be visible. Show it, unless there is a
|
-- | Find out if the sidebar should be visible. Show it, unless there is a
|
||||||
-- showsidebar cookie set to "0", or a ?sidebar=0 query parameter.
|
-- showsidebar cookie set to "0", or a ?sidebar=0 query parameter.
|
||||||
shouldShowSidebar :: Handler Bool
|
shouldShowSidebar :: Handler Bool
|
||||||
|
|||||||
@ -24,10 +24,13 @@ import Hledger.Web.WebOptions (WebOpts(..))
|
|||||||
import Hledger.Web.Widget.AddForm (addForm)
|
import Hledger.Web.Widget.AddForm (addForm)
|
||||||
|
|
||||||
getAddR :: Handler ()
|
getAddR :: Handler ()
|
||||||
getAddR = postAddR
|
getAddR = do
|
||||||
|
checkServerSideUiEnabled
|
||||||
|
postAddR
|
||||||
|
|
||||||
postAddR :: Handler ()
|
postAddR :: Handler ()
|
||||||
postAddR = do
|
postAddR = do
|
||||||
|
checkServerSideUiEnabled
|
||||||
VD{caps, j, today} <- getViewData
|
VD{caps, j, today} <- getViewData
|
||||||
when (CapAdd `notElem` caps) (permissionDenied "Missing the 'add' capability")
|
when (CapAdd `notElem` caps) (permissionDenied "Missing the 'add' capability")
|
||||||
|
|
||||||
@ -58,6 +61,7 @@ postAddR = do
|
|||||||
-- The web form handler above should probably use PUT as well.
|
-- The web form handler above should probably use PUT as well.
|
||||||
putAddR :: Handler RepJson
|
putAddR :: Handler RepJson
|
||||||
putAddR = do
|
putAddR = do
|
||||||
|
checkServerSideUiEnabled
|
||||||
VD{caps, j, opts} <- getViewData
|
VD{caps, j, opts} <- getViewData
|
||||||
when (CapAdd `notElem` caps) (permissionDenied "Missing the 'add' capability")
|
when (CapAdd `notElem` caps) (permissionDenied "Missing the 'add' capability")
|
||||||
|
|
||||||
|
|||||||
@ -23,10 +23,13 @@ editForm f txt =
|
|||||||
fs = FieldSettings "text" mzero mzero mzero [("class", "form-control"), ("rows", "25")]
|
fs = FieldSettings "text" mzero mzero mzero [("class", "form-control"), ("rows", "25")]
|
||||||
|
|
||||||
getEditR :: FilePath -> Handler ()
|
getEditR :: FilePath -> Handler ()
|
||||||
getEditR = postEditR
|
getEditR f = do
|
||||||
|
checkServerSideUiEnabled
|
||||||
|
postEditR f
|
||||||
|
|
||||||
postEditR :: FilePath -> Handler ()
|
postEditR :: FilePath -> Handler ()
|
||||||
postEditR f = do
|
postEditR f = do
|
||||||
|
checkServerSideUiEnabled
|
||||||
VD {caps, j} <- getViewData
|
VD {caps, j} <- getViewData
|
||||||
when (CapManage `notElem` caps) (permissionDenied "Missing the 'manage' capability")
|
when (CapManage `notElem` caps) (permissionDenied "Missing the 'manage' capability")
|
||||||
|
|
||||||
|
|||||||
@ -17,6 +17,7 @@ import Hledger.Web.Widget.Common (accountQuery, mixedAmountAsHtml)
|
|||||||
-- | The formatted journal view, with sidebar.
|
-- | The formatted journal view, with sidebar.
|
||||||
getJournalR :: Handler Html
|
getJournalR :: Handler Html
|
||||||
getJournalR = do
|
getJournalR = do
|
||||||
|
checkServerSideUiEnabled
|
||||||
VD{caps, j, m, opts, qopts, today} <- getViewData
|
VD{caps, j, m, opts, qopts, today} <- getViewData
|
||||||
when (CapView `notElem` caps) (permissionDenied "Missing the 'view' capability")
|
when (CapView `notElem` caps) (permissionDenied "Missing the 'view' capability")
|
||||||
let title = case inAccount qopts of
|
let title = case inAccount qopts of
|
||||||
|
|||||||
@ -30,10 +30,13 @@ import Hledger.Web.Import
|
|||||||
import Hledger.Web.Widget.Common (journalFile404)
|
import Hledger.Web.Widget.Common (journalFile404)
|
||||||
|
|
||||||
getRootR :: Handler Html
|
getRootR :: Handler Html
|
||||||
getRootR = redirect JournalR
|
getRootR = do
|
||||||
|
checkServerSideUiEnabled
|
||||||
|
redirect JournalR
|
||||||
|
|
||||||
getManageR :: Handler Html
|
getManageR :: Handler Html
|
||||||
getManageR = do
|
getManageR = do
|
||||||
|
checkServerSideUiEnabled
|
||||||
VD{caps, j} <- getViewData
|
VD{caps, j} <- getViewData
|
||||||
when (CapManage `notElem` caps) (permissionDenied "Missing the 'manage' capability")
|
when (CapManage `notElem` caps) (permissionDenied "Missing the 'manage' capability")
|
||||||
defaultLayout $ do
|
defaultLayout $ do
|
||||||
@ -42,6 +45,7 @@ getManageR = do
|
|||||||
|
|
||||||
getDownloadR :: FilePath -> Handler TypedContent
|
getDownloadR :: FilePath -> Handler TypedContent
|
||||||
getDownloadR f = do
|
getDownloadR f = do
|
||||||
|
checkServerSideUiEnabled
|
||||||
VD{caps, j} <- getViewData
|
VD{caps, j} <- getViewData
|
||||||
when (CapManage `notElem` caps) (permissionDenied "Missing the 'manage' capability")
|
when (CapManage `notElem` caps) (permissionDenied "Missing the 'manage' capability")
|
||||||
(f', txt) <- journalFile404 f j
|
(f', txt) <- journalFile404 f j
|
||||||
|
|||||||
@ -22,6 +22,7 @@ import Hledger.Web.Widget.Common (accountQuery, mixedAmountAsHtml)
|
|||||||
-- | The main journal/account register view, with accounts sidebar.
|
-- | The main journal/account register view, with accounts sidebar.
|
||||||
getRegisterR :: Handler Html
|
getRegisterR :: Handler Html
|
||||||
getRegisterR = do
|
getRegisterR = do
|
||||||
|
checkServerSideUiEnabled
|
||||||
VD{caps, j, m, opts, qopts, today} <- getViewData
|
VD{caps, j, m, opts, qopts, today} <- getViewData
|
||||||
when (CapView `notElem` caps) (permissionDenied "Missing the 'view' capability")
|
when (CapView `notElem` caps) (permissionDenied "Missing the 'view' capability")
|
||||||
|
|
||||||
|
|||||||
@ -27,10 +27,13 @@ uploadForm f =
|
|||||||
fs = FieldSettings "file" Nothing (Just "file") (Just "file") []
|
fs = FieldSettings "file" Nothing (Just "file") (Just "file") []
|
||||||
|
|
||||||
getUploadR :: FilePath -> Handler ()
|
getUploadR :: FilePath -> Handler ()
|
||||||
getUploadR = postUploadR
|
getUploadR f = do
|
||||||
|
checkServerSideUiEnabled
|
||||||
|
postUploadR f
|
||||||
|
|
||||||
postUploadR :: FilePath -> Handler ()
|
postUploadR :: FilePath -> Handler ()
|
||||||
postUploadR f = do
|
postUploadR f = do
|
||||||
|
checkServerSideUiEnabled
|
||||||
VD {caps, j} <- getViewData
|
VD {caps, j} <- getViewData
|
||||||
when (CapManage `notElem` caps) (permissionDenied "Missing the 'manage' capability")
|
when (CapManage `notElem` caps) (permissionDenied "Missing the 'manage' capability")
|
||||||
|
|
||||||
|
|||||||
@ -69,16 +69,18 @@ web opts j = do
|
|||||||
}
|
}
|
||||||
app <- makeApplication opts j' appconfig
|
app <- makeApplication opts j' appconfig
|
||||||
-- XXX would like to allow a host name not just an IP address here
|
-- XXX would like to allow a host name not just an IP address here
|
||||||
_ <- printf "Starting web app on IP address %s port %d with base url %s\n" h p u
|
_ <- printf "Serving web %s on %s:%d with base url %s\n"
|
||||||
if serve_ opts
|
(if serve_api_ opts then "API" else "UI and API" :: String) h p u
|
||||||
|
if serve_ opts || serve_api_ opts
|
||||||
then do
|
then do
|
||||||
putStrLn "Press ctrl-c to quit"
|
putStrLn "Press ctrl-c to quit"
|
||||||
hFlush stdout
|
hFlush stdout
|
||||||
let warpsettings = setHost (fromString h) (setPort p defaultSettings)
|
let warpsettings = setHost (fromString h) (setPort p defaultSettings)
|
||||||
Network.Wai.Handler.Warp.runSettings warpsettings app
|
Network.Wai.Handler.Warp.runSettings warpsettings app
|
||||||
else do
|
else do
|
||||||
putStrLn "Starting web browser..."
|
putStrLn "This server will exit after 2m with no browser windows open (or press ctrl-c)"
|
||||||
putStrLn "Web app will auto-exit after a few minutes with no browsers (or press ctrl-c)"
|
putStrLn "Opening web browser..."
|
||||||
hFlush stdout
|
hFlush stdout
|
||||||
|
-- exits after 2m of inactivity (hardcoded)
|
||||||
Network.Wai.Handler.Launch.runHostPortUrl h p "" app
|
Network.Wai.Handler.Launch.runHostPortUrl h p "" app
|
||||||
|
|
||||||
|
|||||||
@ -31,6 +31,10 @@ webflags =
|
|||||||
["serve", "server"]
|
["serve", "server"]
|
||||||
(setboolopt "serve")
|
(setboolopt "serve")
|
||||||
"serve and log requests, don't browse or auto-exit"
|
"serve and log requests, don't browse or auto-exit"
|
||||||
|
, flagNone
|
||||||
|
["serve-api"]
|
||||||
|
(setboolopt "serve-api")
|
||||||
|
"like --serve, but serve only the JSON web API, without the server-side web UI"
|
||||||
, flagReq
|
, flagReq
|
||||||
["host"]
|
["host"]
|
||||||
(\s opts -> Right $ setopt "host" s opts)
|
(\s opts -> Right $ setopt "host" s opts)
|
||||||
@ -89,6 +93,7 @@ webmode =
|
|||||||
-- hledger-web options, used in hledger-web and above
|
-- hledger-web options, used in hledger-web and above
|
||||||
data WebOpts = WebOpts
|
data WebOpts = WebOpts
|
||||||
{ serve_ :: Bool
|
{ serve_ :: Bool
|
||||||
|
, serve_api_ :: Bool
|
||||||
, host_ :: String
|
, host_ :: String
|
||||||
, port_ :: Int
|
, port_ :: Int
|
||||||
, base_url_ :: String
|
, base_url_ :: String
|
||||||
@ -99,7 +104,7 @@ data WebOpts = WebOpts
|
|||||||
} deriving (Show)
|
} deriving (Show)
|
||||||
|
|
||||||
defwebopts :: WebOpts
|
defwebopts :: WebOpts
|
||||||
defwebopts = WebOpts def def def def def [CapView, CapAdd] Nothing def
|
defwebopts = WebOpts def def def def def def [CapView, CapAdd] Nothing def
|
||||||
|
|
||||||
instance Default WebOpts where def = defwebopts
|
instance Default WebOpts where def = defwebopts
|
||||||
|
|
||||||
@ -120,6 +125,7 @@ rawOptsToWebOpts rawopts =
|
|||||||
return
|
return
|
||||||
defwebopts
|
defwebopts
|
||||||
{ serve_ = boolopt "serve" rawopts
|
{ serve_ = boolopt "serve" rawopts
|
||||||
|
, serve_api_ = boolopt "serve-api" rawopts
|
||||||
, host_ = h
|
, host_ = h
|
||||||
, port_ = p
|
, port_ = p
|
||||||
, base_url_ = b
|
, base_url_ = b
|
||||||
|
|||||||
@ -64,6 +64,9 @@ as shown in the synopsis above.
|
|||||||
`--serve`
|
`--serve`
|
||||||
: serve and log requests, don't browse or auto-exit
|
: serve and log requests, don't browse or auto-exit
|
||||||
|
|
||||||
|
`--serve-api`
|
||||||
|
: like --serve, but serve only the JSON web API, without the server-side web UI
|
||||||
|
|
||||||
`--host=IPADDR`
|
`--host=IPADDR`
|
||||||
: listen on this IP address (default: 127.0.0.1)
|
: listen on this IP address (default: 127.0.0.1)
|
||||||
|
|
||||||
@ -108,6 +111,8 @@ browser window, and will exit after two minutes of inactivity (no
|
|||||||
requests and no browser windows viewing it).
|
requests and no browser windows viewing it).
|
||||||
With `--serve`, it just runs the web app without exiting, and logs
|
With `--serve`, it just runs the web app without exiting, and logs
|
||||||
requests to the console.
|
requests to the console.
|
||||||
|
With `--serve-api`, only the JSON web api (see below) is served,
|
||||||
|
with the usual HTML server-side web UI disabled.
|
||||||
|
|
||||||
By default the server listens on IP address 127.0.0.1, accessible only to local requests.
|
By default the server listens on IP address 127.0.0.1, accessible only to local requests.
|
||||||
You can use `--host` to change this, eg `--host 0.0.0.0` to listen on all configured addresses.
|
You can use `--host` to change this, eg `--host 0.0.0.0` to listen on all configured addresses.
|
||||||
@ -217,6 +222,9 @@ And here's how to test adding that with curl:
|
|||||||
$ curl -s http://127.0.0.1:5000/add -X PUT -H 'Content-Type: application/json' --data-binary @txn.pretty.json; echo
|
$ curl -s http://127.0.0.1:5000/add -X PUT -H 'Content-Type: application/json' --data-binary @txn.pretty.json; echo
|
||||||
```
|
```
|
||||||
|
|
||||||
|
By default, both the server-side HTML UI and the JSON API are served.
|
||||||
|
Running with `--serve-api` disables the former, useful if you only want to serve the API.
|
||||||
|
|
||||||
_man_({{
|
_man_({{
|
||||||
|
|
||||||
# ENVIRONMENT
|
# ENVIRONMENT
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user