Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 25 additions & 6 deletions hledger-web/Hledger/Web/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import Control.Exception (bracket)
import Control.Exception.Backtrace (setBacktraceMechanismState, BacktraceMechanism(..))
#endif
import Control.Monad (when, void)
import Data.Streaming.Network (bindRandomPortTCP)
import Data.String (fromString)
import Data.Text qualified as T
import Network.Socket
Expand All @@ -47,7 +48,7 @@ import Hledger
import Hledger.Cli hiding (progname,prognameandversion)
import Hledger.Cli.Commands.Quickref (showQuickref)
import Hledger.Web.Application (makeApplication)
import Hledger.Web.Settings (Extra(..), parseExtra)
import Hledger.Web.Settings (Extra(..), parseExtra, defbaseurl)
import Hledger.Web.Test (hledgerWebTest)
import Hledger.Web.WebOptions

Expand Down Expand Up @@ -109,9 +110,25 @@ web opts0 j = do
let depthlessinitialq = filterQuery (not . queryIsDepth) . _rsQuery . reportspec_ $ cliopts_ opts
j' = filterJournalTransactions depthlessinitialq j
h = host_ opts
p = port_ opts
u = base_url_ opts
p0 = port_ opts
staticRoot = T.pack <$> file_url_ opts -- XXX not used #2139

-- --port 0 means "let the operating system choose a free port". To learn which
-- port it chose (so we can report it and build the base url), we must bind the
-- listening socket ourselves rather than let warp do it. This isn't supported in
-- --serve-browse mode, which needs a known port up front to open the browser at.
when (p0 == 0 && socket_ opts == Nothing && server_mode_ opts == ServeBrowse) $
error' $ unlines -- PARTIAL:
["--port 0 (let the operating system choose a free port) is not supported with --serve-browse."
,"Please use --serve or --serve-api instead, which will report the chosen port."]
mtcpsock <- if p0 == 0 && socket_ opts == Nothing
then Just <$> bindRandomPortTCP (fromString h)
else return Nothing
let p = maybe p0 fst mtcpsock
-- If the base url is the default one (built from host and port), rebuild it
-- with the chosen port; if the user set --base-url, leave it untouched.
u | base_url_ opts == defbaseurl h p0 = defbaseurl h p
| otherwise = base_url_ opts
appconfig = AppConfig{appEnv = Development
,appHost = fromString h
,appPort = p
Expand Down Expand Up @@ -151,8 +168,8 @@ web opts0 j = do
putStrLn "Press ctrl-c to quit"
hFlush stdout
let warpsettings = setHost (fromString h) (setPort p defaultSettings)
case socket_ opts of
Just s -> do
case (socket_ opts, mtcpsock) of
(Just s, _) -> do
if isUnixDomainSocketAvailable then
bracket
(do
Expand All @@ -172,5 +189,7 @@ web opts0 j = do
,"Please try again without --socket."
]

Nothing -> Network.Wai.Handler.Warp.runSettings warpsettings app
-- --port 0: serve on the socket we already bound to the OS-chosen port.
(Nothing, Just (_, sock)) -> Network.Wai.Handler.Warp.runSettingsSocket warpsettings sock app
(Nothing, Nothing) -> Network.Wai.Handler.Warp.runSettings warpsettings app

2 changes: 1 addition & 1 deletion hledger-web/Hledger/Web/WebOptions.hs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ webflags =
["port"]
(\s opts -> Right $ setopt "port" s opts)
"PORT"
("listen on this TCP port (default: " ++ show defport ++ ")")
("listen on this TCP port (default: " ++ show defport ++ "); 0 means a free port chosen by the OS")
, flagReq
["socket"]
(\s opts -> Right $ setopt "socket" s opts)
Expand Down
1 change: 1 addition & 0 deletions hledger-web/hledger-web.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ library
, network
, safe >=0.3.20
, shakespeare >=2.0.2.2
, streaming-commons
, template-haskell
, text >=1.2.4.1
, time >=1.5
Expand Down
7 changes: 6 additions & 1 deletion hledger-web/hledger-web.m4.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@ Flags:
origin; setting ORIGIN to "*" allows requests from
any origin
--host=IPADDR listen on this IP address (default: 127.0.0.1)
--port=PORT listen on this TCP port (default: 5000)
--port=PORT listen on this TCP port (default: 5000); 0 means
a free port chosen by the OS
--socket=SOCKET listen on the given unix socket instead of an IP
address and port (unix only; implies --serve)
--base-url=BASEURL set the base url (default: http://IPADDR:PORT)
Expand All @@ -97,6 +98,10 @@ The special address `0.0.0.0` causes it to listen on all of this machine's addre

Similarly, you can use `--port` to listen on a TCP port other than 5000.
This is useful if you want to run multiple hledger-web instances on a machine.
`--port 0` makes the operating system choose a free port, which is reported
in the startup message and in the default base url. This can be useful eg
when scripting; it is supported with `--serve` and `--serve-api`, but not
with `--serve-browse`.

When `--socket` is used, hledger-web creates and communicates via a socket file instead of a TCP port.
This can be more secure, respects unix file permissions, and makes certain use cases easier,
Expand Down
1 change: 1 addition & 0 deletions hledger-web/package.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ library:
- network
- safe >=0.3.20
- shakespeare >=2.0.2.2
- streaming-commons
- template-haskell
- text >=1.2.4.1
- time >=1.5
Expand Down