summaryrefslogtreecommitdiffhomepage
path: root/commands/server.go
diff options
context:
space:
mode:
authorBjørn Erik Pedersen <[email protected]>2018-04-09 22:28:03 +0200
committerBjørn Erik Pedersen <[email protected]>2018-04-11 09:50:18 +0200
commit2f0d98a19b021d03930003217b0519afaef3a391 (patch)
treed1ffde5a8d2300b1554a6017d74be57cd90f77d9 /commands/server.go
parente0621d207ce3278a82f8a60607e9cdd304149029 (diff)
downloadhugo-2f0d98a19b021d03930003217b0519afaef3a391.tar.gz
hugo-2f0d98a19b021d03930003217b0519afaef3a391.zip
commands: Make the server command non-global
See #4598
Diffstat (limited to 'commands/server.go')
-rw-r--r--commands/server.go125
1 files changed, 72 insertions, 53 deletions
diff --git a/commands/server.go b/commands/server.go
index 8e778875f..ce03eacb7 100644
--- a/commands/server.go
+++ b/commands/server.go
@@ -38,7 +38,9 @@ import (
jww "github.com/spf13/jwalterweatherman"
)
-var (
+var _ cmder = (*serverCmd)(nil)
+
+type serverCmd struct {
disableLiveReload bool
navigateToChanged bool
renderToDisk bool
@@ -50,13 +52,22 @@ var (
noHTTPCache bool
disableFastRender bool
-)
-var serverCmd = &cobra.Command{
- Use: "server",
- Aliases: []string{"serve"},
- Short: "A high performance webserver",
- Long: `Hugo provides its own webserver which builds and serves the site.
+ cmd *cobra.Command
+}
+
+func (c *serverCmd) getCommand() *cobra.Command {
+ return c.cmd
+}
+
+func newServerCmd() *serverCmd {
+ cc := &serverCmd{}
+
+ cc.cmd = &cobra.Command{
+ Use: "server",
+ Aliases: []string{"serve"},
+ Short: "A high performance webserver",
+ Long: `Hugo provides its own webserver which builds and serves the site.
While hugo server is high performance, it is a webserver with limited options.
Many run it in production, but the standard behavior is for people to use it
in development and use a more full featured server such as Nginx or Caddy.
@@ -68,7 +79,27 @@ By default hugo will also watch your files for any changes you make and
automatically rebuild the site. It will then live reload any open browser pages
and push the latest content to them. As most Hugo sites are built in a fraction
of a second, you will be able to save and see your changes nearly instantly.`,
- //RunE: server,
+ RunE: cc.server,
+ }
+
+ initHugoBuilderFlags(cc.cmd)
+
+ // TODO(bep) cli refactor fields vs strings
+ cc.cmd.Flags().IntVarP(&cc.serverPort, "port", "p", 1313, "port on which the server will listen")
+ cc.cmd.Flags().IntVar(&cc.liveReloadPort, "liveReloadPort", -1, "port for live reloading (i.e. 443 in HTTPS proxy situations)")
+ cc.cmd.Flags().StringVarP(&cc.serverInterface, "bind", "", "127.0.0.1", "interface to which the server will bind")
+ cc.cmd.Flags().BoolVarP(&cc.serverWatch, "watch", "w", true, "watch filesystem for changes and recreate as needed")
+ cc.cmd.Flags().BoolVar(&cc.noHTTPCache, "noHTTPCache", false, "prevent HTTP caching")
+ cc.cmd.Flags().BoolVarP(&cc.serverAppend, "appendPort", "", true, "append port to baseURL")
+ cc.cmd.Flags().BoolVar(&cc.disableLiveReload, "disableLiveReload", false, "watch without enabling live browser reload on rebuild")
+ cc.cmd.Flags().BoolVar(&cc.navigateToChanged, "navigateToChanged", false, "navigate to changed content file on live browser reload")
+ cc.cmd.Flags().BoolVar(&cc.renderToDisk, "renderToDisk", false, "render to Destination path (default is render to memory & serve from there)")
+ cc.cmd.Flags().BoolVar(&cc.disableFastRender, "disableFastRender", false, "enables full re-renders on changes")
+
+ cc.cmd.Flags().String("memstats", "", "log memory usage to this file")
+ cc.cmd.Flags().String("meminterval", "100ms", "interval to poll memory usage (requires --memstats), valid time units are \"ns\", \"us\" (or \"µs\"), \"ms\", \"s\", \"m\", \"h\".")
+
+ return cc
}
type filesOnlyFs struct {
@@ -92,49 +123,32 @@ func (f noDirFile) Readdir(count int) ([]os.FileInfo, error) {
}
func init() {
- initHugoBuilderFlags(serverCmd)
-
- serverCmd.Flags().IntVarP(&serverPort, "port", "p", 1313, "port on which the server will listen")
- serverCmd.Flags().IntVar(&liveReloadPort, "liveReloadPort", -1, "port for live reloading (i.e. 443 in HTTPS proxy situations)")
- serverCmd.Flags().StringVarP(&serverInterface, "bind", "", "127.0.0.1", "interface to which the server will bind")
- serverCmd.Flags().BoolVarP(&serverWatch, "watch", "w", true, "watch filesystem for changes and recreate as needed")
- serverCmd.Flags().BoolVar(&noHTTPCache, "noHTTPCache", false, "prevent HTTP caching")
- serverCmd.Flags().BoolVarP(&serverAppend, "appendPort", "", true, "append port to baseURL")
- serverCmd.Flags().BoolVar(&disableLiveReload, "disableLiveReload", false, "watch without enabling live browser reload on rebuild")
- serverCmd.Flags().BoolVar(&navigateToChanged, "navigateToChanged", false, "navigate to changed content file on live browser reload")
- serverCmd.Flags().BoolVar(&renderToDisk, "renderToDisk", false, "render to Destination path (default is render to memory & serve from there)")
- serverCmd.Flags().BoolVar(&disableFastRender, "disableFastRender", false, "enables full re-renders on changes")
-
- serverCmd.Flags().String("memstats", "", "log memory usage to this file")
- serverCmd.Flags().String("meminterval", "100ms", "interval to poll memory usage (requires --memstats), valid time units are \"ns\", \"us\" (or \"µs\"), \"ms\", \"s\", \"m\", \"h\".")
-
- serverCmd.RunE = server
}
var serverPorts []int
-func server(cmd *cobra.Command, args []string) error {
+func (s *serverCmd) server(cmd *cobra.Command, args []string) error {
// If a Destination is provided via flag write to disk
destination, _ := cmd.Flags().GetString("destination")
if destination != "" {
- renderToDisk = true
+ s.renderToDisk = true
}
var serverCfgInit sync.Once
cfgInit := func(c *commandeer) error {
- c.Set("renderToMemory", !renderToDisk)
+ c.Set("renderToMemory", !s.renderToDisk)
if cmd.Flags().Changed("navigateToChanged") {
- c.Set("navigateToChanged", navigateToChanged)
+ c.Set("navigateToChanged", s.navigateToChanged)
}
if cmd.Flags().Changed("disableLiveReload") {
- c.Set("disableLiveReload", disableLiveReload)
+ c.Set("disableLiveReload", s.disableLiveReload)
}
if cmd.Flags().Changed("disableFastRender") {
- c.Set("disableFastRender", disableFastRender)
+ c.Set("disableFastRender", s.disableFastRender)
}
- if serverWatch {
+ if s.serverWatch {
c.Set("watch", true)
}
@@ -150,25 +164,25 @@ func server(cmd *cobra.Command, args []string) error {
serverPorts = make([]int, 1)
if c.languages.IsMultihost() {
- if !serverAppend {
+ if !s.serverAppend {
err = newSystemError("--appendPort=false not supported when in multihost mode")
}
serverPorts = make([]int, len(c.languages))
}
- currentServerPort := serverPort
+ currentServerPort := s.serverPort
for i := 0; i < len(serverPorts); i++ {
- l, err := net.Listen("tcp", net.JoinHostPort(serverInterface, strconv.Itoa(currentServerPort)))
+ l, err := net.Listen("tcp", net.JoinHostPort(s.serverInterface, strconv.Itoa(currentServerPort)))
if err == nil {
l.Close()
serverPorts[i] = currentServerPort
} else {
- if i == 0 && serverCmd.Flags().Changed("port") {
+ if i == 0 && s.cmd.Flags().Changed("port") {
// port set explicitly by user -- he/she probably meant it!
err = newSystemErrorF("Server startup failed: %s", err)
}
- jww.ERROR.Println("port", serverPort, "already in use, attempting to use an available port")
+ jww.ERROR.Println("port", s.serverPort, "already in use, attempting to use an available port")
sp, err := helpers.FindAvailablePort()
if err != nil {
err = newSystemError("Unable to find alternative port to use:", err)
@@ -182,9 +196,9 @@ func server(cmd *cobra.Command, args []string) error {
c.serverPorts = serverPorts
- c.Set("port", serverPort)
- if liveReloadPort != -1 {
- c.Set("liveReloadPort", liveReloadPort)
+ c.Set("port", s.serverPort)
+ if s.liveReloadPort != -1 {
+ c.Set("liveReloadPort", s.liveReloadPort)
} else {
c.Set("liveReloadPort", serverPorts[0])
}
@@ -198,7 +212,7 @@ func server(cmd *cobra.Command, args []string) error {
serverPort = serverPorts[0]
}
- baseURL, err := fixURL(language, baseURL, serverPort)
+ baseURL, err := s.fixURL(language, baseURL, serverPort)
if err != nil {
return nil
}
@@ -218,7 +232,8 @@ func server(cmd *cobra.Command, args []string) error {
jww.ERROR.Println("memstats error:", err)
}
- c, err := InitializeConfig(true, cfgInit, serverCmd)
+ c, err := InitializeConfig(true, cfgInit, s.cmd)
+ // TODO(bep) cli refactor
if err != nil {
return err
}
@@ -232,7 +247,7 @@ func server(cmd *cobra.Command, args []string) error {
}
// Watch runs its own server as part of the routine
- if serverWatch {
+ if s.serverWatch {
watchDirs, err := c.getDirList()
if err != nil {
@@ -258,7 +273,7 @@ func server(cmd *cobra.Command, args []string) error {
}
- return c.serve()
+ return c.serve(s)
}
@@ -266,6 +281,7 @@ type fileServer struct {
baseURLs []string
roots []string
c *commandeer
+ s *serverCmd
}
func (f *fileServer) createEndpoint(i int) (*http.ServeMux, string, string, error) {
@@ -282,7 +298,7 @@ func (f *fileServer) createEndpoint(i int) (*http.ServeMux, string, string, erro
absPublishDir := f.c.PathSpec().AbsPathify(publishDir)
if i == 0 {
- if renderToDisk {
+ if f.s.renderToDisk {
jww.FEEDBACK.Println("Serving pages from " + absPublishDir)
} else {
jww.FEEDBACK.Println("Serving pages from memory")
@@ -307,7 +323,7 @@ func (f *fileServer) createEndpoint(i int) (*http.ServeMux, string, string, erro
decorate := func(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- if noHTTPCache {
+ if f.s.noHTTPCache {
w.Header().Set("Cache-Control", "no-store, no-cache, must-revalidate, max-age=0")
w.Header().Set("Pragma", "no-cache")
}
@@ -331,12 +347,13 @@ func (f *fileServer) createEndpoint(i int) (*http.ServeMux, string, string, erro
mu.Handle(u.Path, http.StripPrefix(u.Path, fileserver))
}
- endpoint := net.JoinHostPort(serverInterface, strconv.Itoa(port))
+ endpoint := net.JoinHostPort(f.s.serverInterface, strconv.Itoa(port))
return mu, u.String(), endpoint, nil
}
-func (c *commandeer) serve() error {
+// TODO(bep) cli refactor
+func (c *commandeer) serve(s *serverCmd) error {
isMultiHost := Hugo.IsMultihost()
@@ -360,6 +377,7 @@ func (c *commandeer) serve() error {
baseURLs: baseURLs,
roots: roots,
c: c,
+ s: s,
}
doLiveReload := !c.Cfg.GetBool("disableLiveReload")
@@ -378,7 +396,7 @@ func (c *commandeer) serve() error {
mu.HandleFunc("/livereload.js", livereload.ServeJS)
mu.HandleFunc("/livereload", livereload.Handler)
}
- jww.FEEDBACK.Printf("Web Server is available at %s (bind address %s)\n", serverURL, serverInterface)
+ jww.FEEDBACK.Printf("Web Server is available at %s (bind address %s)\n", serverURL, s.serverInterface)
go func() {
err = http.ListenAndServe(endpoint, mu)
if err != nil {
@@ -397,7 +415,7 @@ func (c *commandeer) serve() error {
// fixURL massages the baseURL into a form needed for serving
// all pages correctly.
-func fixURL(cfg config.Provider, s string, port int) (string, error) {
+func (sc *serverCmd) fixURL(cfg config.Provider, s string, port int) (string, error) {
useLocalhost := false
if s == "" {
s = cfg.GetString("baseURL")
@@ -432,7 +450,7 @@ func fixURL(cfg config.Provider, s string, port int) (string, error) {
u.Host = "localhost"
}
- if serverAppend {
+ if sc.serverAppend {
if strings.Contains(u.Host, ":") {
u.Host, _, err = net.SplitHostPort(u.Host)
if err != nil {
@@ -446,9 +464,10 @@ func fixURL(cfg config.Provider, s string, port int) (string, error) {
}
func memStats() error {
- memstats := serverCmd.Flags().Lookup("memstats").Value.String()
+ sc := newServerCmd().getCommand()
+ memstats := sc.Flags().Lookup("memstats").Value.String()
if memstats != "" {
- interval, err := time.ParseDuration(serverCmd.Flags().Lookup("meminterval").Value.String())
+ interval, err := time.ParseDuration(sc.Flags().Lookup("meminterval").Value.String())
if err != nil {
interval, _ = time.ParseDuration("100ms")
}