Skip to content

Commit

Permalink
Add HTTP header support for the dev server
Browse files Browse the repository at this point in the history
Fixes #7031
  • Loading branch information
bep committed Mar 8, 2020
1 parent cb12f41 commit d1aff33
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 1 deletion.
6 changes: 5 additions & 1 deletion commands/commandeer.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import (
"errors"
"sync"

hconfig "github.com/gohugoio/hugo/config"

"golang.org/x/sync/semaphore"

"io/ioutil"
Expand Down Expand Up @@ -58,7 +60,8 @@ type commandeerHugoState struct {
type commandeer struct {
*commandeerHugoState

logger *loggers.Logger
logger *loggers.Logger
serverConfig config.Server

// Currently only set when in "fast render mode". But it seems to
// be fast enough that we could maybe just add it for all server modes.
Expand Down Expand Up @@ -343,6 +346,7 @@ func (c *commandeer) loadConfig(mustHaveConfigFile, running bool) error {

cfg.Logger = logger
c.logger = logger
c.serverConfig = hconfig.DecodeServer(cfg.Cfg)

createMemFs := config.GetBool("renderToMemory")

Expand Down
4 changes: 4 additions & 0 deletions commands/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,10 @@ func (f *fileServer) createEndpoint(i int) (*http.ServeMux, string, string, erro
w.Header().Set("Pragma", "no-cache")
}

for _, header := range f.c.serverConfig.Match(r.RequestURI) {
w.Header().Set(header.Key, header.Value)
}

if f.c.fastRenderMode && f.c.buildErr == nil {
p := r.RequestURI
if strings.HasSuffix(p, "/") || strings.HasSuffix(p, "html") || strings.HasSuffix(p, "htm") {
Expand Down
59 changes: 59 additions & 0 deletions config/commonConfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,13 @@
package config

import (
"sort"
"strings"
"sync"

"github.com/gohugoio/hugo/common/types"

"github.com/gobwas/glob"
"github.com/gohugoio/hugo/common/herrors"
"github.com/mitchellh/mapstructure"
"github.com/spf13/cast"
Expand Down Expand Up @@ -88,3 +93,57 @@ func DecodeSitemap(prototype Sitemap, input map[string]interface{}) Sitemap {

return prototype
}

// Config for the dev server.
type Server struct {
Headers []Headers

compiledInit sync.Once
compiled []glob.Glob
}

func (s Server) Match(pattern string) []types.KeyValueStr {
s.compiledInit.Do(func() {
for _, h := range s.Headers {
s.compiled = append(s.compiled, glob.MustCompile(h.For))
}
})

if s.compiled == nil {
return nil
}

var matches []types.KeyValueStr

for i, g := range s.compiled {
if g.Match(pattern) {
h := s.Headers[i]
for k, v := range h.Values {
matches = append(matches, types.KeyValueStr{k, cast.ToString(v)})
}
}
}

sort.Slice(matches, func(i, j int) bool {
return matches[i].Key < matches[j].Key
})

return matches

}

type Headers struct {
For string
Values map[string]interface{}
}

func DecodeServer(cfg Provider) Server {
m := cfg.GetStringMap("server")
var s Server
if m == nil {
return s
}

_ = mapstructure.WeakDecode(m, &s)
return s
}
24 changes: 24 additions & 0 deletions config/commonConfig_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"testing"

"github.com/gohugoio/hugo/common/herrors"
"github.com/gohugoio/hugo/common/types"

qt "github.com/frankban/quicktest"

Expand Down Expand Up @@ -58,3 +59,26 @@ func TestBuild(t *testing.T) {
c.Assert(b.UseResourceCache(nil), qt.Equals, false)

}

func TestServer(t *testing.T) {
c := qt.New(t)

cfg, err := FromConfigString(`[[server.headers]]
for = "/*.jpg"
[server.headers.values]
X-Frame-Options = "DENY"
X-XSS-Protection = "1; mode=block"
X-Content-Type-Options = "nosniff"
`, "toml")

c.Assert(err, qt.IsNil)

s := DecodeServer(cfg)

c.Assert(s.Match("/foo.jpg"), qt.DeepEquals, []types.KeyValueStr{
{Key: "X-Content-Type-Options", Value: "nosniff"},
{Key: "X-Frame-Options", Value: "DENY"},
{Key: "X-XSS-Protection", Value: "1; mode=block"}})

}

0 comments on commit d1aff33

Please sign in to comment.