mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-29 02:52:14 -05:00
parent
cebd886ac1
commit
31fbc081c9
2 changed files with 48 additions and 21 deletions
|
@ -15,6 +15,7 @@ package commands
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
|
@ -32,6 +33,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/common/paths"
|
"github.com/gohugoio/hugo/common/paths"
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
|
@ -139,7 +141,7 @@ func (sc *serverCmd) server(cmd *cobra.Command, args []string) error {
|
||||||
|
|
||||||
var serverCfgInit sync.Once
|
var serverCfgInit sync.Once
|
||||||
|
|
||||||
cfgInit := func(c *commandeer) error {
|
cfgInit := func(c *commandeer) (rerr error) {
|
||||||
c.Set("renderToMemory", !sc.renderToDisk)
|
c.Set("renderToMemory", !sc.renderToDisk)
|
||||||
if cmd.Flags().Changed("navigateToChanged") {
|
if cmd.Flags().Changed("navigateToChanged") {
|
||||||
c.Set("navigateToChanged", sc.navigateToChanged)
|
c.Set("navigateToChanged", sc.navigateToChanged)
|
||||||
|
@ -162,15 +164,13 @@ func (sc *serverCmd) server(cmd *cobra.Command, args []string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
|
||||||
|
|
||||||
// We can only do this once.
|
// We can only do this once.
|
||||||
serverCfgInit.Do(func() {
|
serverCfgInit.Do(func() {
|
||||||
serverPorts = make([]int, 1)
|
serverPorts = make([]int, 1)
|
||||||
|
|
||||||
if c.languages.IsMultihost() {
|
if c.languages.IsMultihost() {
|
||||||
if !sc.serverAppend {
|
if !sc.serverAppend {
|
||||||
err = newSystemError("--appendPort=false not supported when in multihost mode")
|
rerr = newSystemError("--appendPort=false not supported when in multihost mode")
|
||||||
}
|
}
|
||||||
serverPorts = make([]int, len(c.languages))
|
serverPorts = make([]int, len(c.languages))
|
||||||
}
|
}
|
||||||
|
@ -185,12 +185,14 @@ func (sc *serverCmd) server(cmd *cobra.Command, args []string) error {
|
||||||
} else {
|
} else {
|
||||||
if i == 0 && sc.cmd.Flags().Changed("port") {
|
if i == 0 && sc.cmd.Flags().Changed("port") {
|
||||||
// port set explicitly by user -- he/she probably meant it!
|
// port set explicitly by user -- he/she probably meant it!
|
||||||
err = newSystemErrorF("Server startup failed: %s", err)
|
rerr = newSystemErrorF("Server startup failed: %s", err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
c.logger.Println("port", sc.serverPort, "already in use, attempting to use an available port")
|
c.logger.Println("port", sc.serverPort, "already in use, attempting to use an available port")
|
||||||
sp, err := helpers.FindAvailablePort()
|
sp, err := helpers.FindAvailablePort()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = newSystemError("Unable to find alternative port to use:", err)
|
rerr = newSystemError("Unable to find alternative port to use:", err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
serverPorts[i] = sp.Port
|
serverPorts[i] = sp.Port
|
||||||
}
|
}
|
||||||
|
@ -199,6 +201,10 @@ func (sc *serverCmd) server(cmd *cobra.Command, args []string) error {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if rerr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
c.serverPorts = serverPorts
|
c.serverPorts = serverPorts
|
||||||
|
|
||||||
c.Set("port", sc.serverPort)
|
c.Set("port", sc.serverPort)
|
||||||
|
@ -229,7 +235,7 @@ func (sc *serverCmd) server(cmd *cobra.Command, args []string) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return err
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := memStats(); err != nil {
|
if err := memStats(); err != nil {
|
||||||
|
@ -506,9 +512,15 @@ func (c *commandeer) serve(s *serverCmd) error {
|
||||||
|
|
||||||
sigs := make(chan os.Signal, 1)
|
sigs := make(chan os.Signal, 1)
|
||||||
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
|
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
|
||||||
|
var servers []*http.Server
|
||||||
|
|
||||||
for i := range baseURLs {
|
for i := range baseURLs {
|
||||||
mu, serverURL, endpoint, err := srv.createEndpoint(i)
|
mu, serverURL, endpoint, err := srv.createEndpoint(i)
|
||||||
|
srv := &http.Server{
|
||||||
|
Addr: endpoint,
|
||||||
|
Handler: mu,
|
||||||
|
}
|
||||||
|
servers = append(servers, srv)
|
||||||
|
|
||||||
if doLiveReload {
|
if doLiveReload {
|
||||||
u, err := url.Parse(helpers.SanitizeURL(baseURLs[i]))
|
u, err := url.Parse(helpers.SanitizeURL(baseURLs[i]))
|
||||||
|
@ -521,8 +533,8 @@ func (c *commandeer) serve(s *serverCmd) error {
|
||||||
}
|
}
|
||||||
jww.FEEDBACK.Printf("Web Server is available at %s (bind address %s)\n", serverURL, s.serverInterface)
|
jww.FEEDBACK.Printf("Web Server is available at %s (bind address %s)\n", serverURL, s.serverInterface)
|
||||||
go func() {
|
go func() {
|
||||||
err = http.ListenAndServe(endpoint, mu)
|
err = srv.ListenAndServe()
|
||||||
if err != nil {
|
if err != nil && err != http.ErrServerClosed {
|
||||||
c.logger.Errorf("Error: %s\n", err.Error())
|
c.logger.Errorf("Error: %s\n", err.Error())
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
@ -542,7 +554,17 @@ func (c *commandeer) serve(s *serverCmd) error {
|
||||||
|
|
||||||
c.hugo().Close()
|
c.hugo().Close()
|
||||||
|
|
||||||
return nil
|
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
wg, ctx := errgroup.WithContext(ctx)
|
||||||
|
for _, srv := range servers {
|
||||||
|
srv := srv
|
||||||
|
wg.Go(func() error {
|
||||||
|
return srv.Shutdown(ctx)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return wg.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
// fixURL massages the baseURL into a form needed for serving
|
// fixURL massages the baseURL into a form needed for serving
|
||||||
|
|
|
@ -25,6 +25,8 @@ import (
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/config"
|
"github.com/gohugoio/hugo/config"
|
||||||
"github.com/gohugoio/hugo/helpers"
|
"github.com/gohugoio/hugo/helpers"
|
||||||
|
"golang.org/x/net/context"
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
|
|
||||||
qt "github.com/frankban/quicktest"
|
qt "github.com/frankban/quicktest"
|
||||||
)
|
)
|
||||||
|
@ -107,14 +109,14 @@ func runServerTest(c *qt.C, config string, args ...string) (result serverTestRes
|
||||||
defer clean()
|
defer clean()
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
|
|
||||||
// Let us hope that this port is available on all systems ...
|
sp, err := helpers.FindAvailablePort()
|
||||||
port := 1331
|
c.Assert(err, qt.IsNil)
|
||||||
|
port := sp.Port
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
os.RemoveAll(dir)
|
os.RemoveAll(dir)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
errors := make(chan error)
|
|
||||||
stop := make(chan bool)
|
stop := make(chan bool)
|
||||||
|
|
||||||
b := newCommandsBuilder()
|
b := newCommandsBuilder()
|
||||||
|
@ -124,24 +126,26 @@ func runServerTest(c *qt.C, config string, args ...string) (result serverTestRes
|
||||||
args = append([]string{"-s=" + dir, fmt.Sprintf("-p=%d", port)}, args...)
|
args = append([]string{"-s=" + dir, fmt.Sprintf("-p=%d", port)}, args...)
|
||||||
cmd.SetArgs(args)
|
cmd.SetArgs(args)
|
||||||
|
|
||||||
go func() {
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
wg, ctx := errgroup.WithContext(ctx)
|
||||||
|
|
||||||
|
wg.Go(func() error {
|
||||||
_, err := cmd.ExecuteC()
|
_, err := cmd.ExecuteC()
|
||||||
if err != nil {
|
return err
|
||||||
errors <- err
|
})
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
select {
|
select {
|
||||||
// There is no way to know exactly when the server is ready for connections.
|
// There is no way to know exactly when the server is ready for connections.
|
||||||
// We could improve by something like https://golang.org/pkg/net/http/httptest/#Server
|
// We could improve by something like https://golang.org/pkg/net/http/httptest/#Server
|
||||||
// But for now, let us sleep and pray!
|
// But for now, let us sleep and pray!
|
||||||
case <-time.After(2 * time.Second):
|
case <-time.After(2 * time.Second):
|
||||||
case err := <-errors:
|
case <-ctx.Done():
|
||||||
result.err = err
|
result.err = wg.Wait()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := http.Get("http://localhost:1331/")
|
resp, err := http.Get(fmt.Sprintf("http://localhost:%d/", port))
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
homeContent := helpers.ReaderToString(resp.Body)
|
homeContent := helpers.ReaderToString(resp.Body)
|
||||||
|
@ -158,6 +162,7 @@ func runServerTest(c *qt.C, config string, args ...string) (result serverTestRes
|
||||||
result.publicDirnames[f.Name()] = true
|
result.publicDirnames[f.Name()] = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result.err = wg.Wait()
|
||||||
return
|
return
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue