github.com/webonyx/up@v0.7.4-0.20180808230834-91b94e551323/http/headers/headers.go (about) 1 // Package headers provides header injection support. 2 package headers 3 4 import ( 5 "net/http" 6 "os" 7 8 "github.com/apex/log" 9 "github.com/pkg/errors" 10 hdr "github.com/tj/go-headers" 11 12 "github.com/apex/up" 13 "github.com/apex/up/internal/header" 14 ) 15 16 // TODO: document precedence and/or add options 17 // TODO: maybe allow storing _headers in Static.Dir? 18 19 // filename of headers file. 20 var filename = "_headers" 21 22 // New headers handler. 23 func New(c *up.Config, next http.Handler) (http.Handler, error) { 24 rulesFromFile, err := readFromFile(filename) 25 if err != nil { 26 return nil, errors.Wrap(err, "reading header file") 27 } 28 29 rules, err := header.Compile(header.Merge(rulesFromFile, c.Headers)) 30 if err != nil { 31 return nil, errors.Wrap(err, "compiling header") 32 } 33 34 log.Debugf("header rules from _headers file: %d", len(rulesFromFile)) 35 log.Debugf("header rules from up.json: %d", len(c.Headers)) 36 37 h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 38 fields := rules.Lookup(r.URL.Path) 39 40 for k, v := range fields { 41 w.Header().Set(k, v) 42 } 43 44 next.ServeHTTP(w, r) 45 }) 46 47 return h, nil 48 } 49 50 // readFromFile reads from a Netlify style headers file. 51 func readFromFile(path string) (header.Rules, error) { 52 rules := make(header.Rules) 53 54 f, err := os.Open(path) 55 56 if os.IsNotExist(err) { 57 return nil, nil 58 } 59 60 if err != nil { 61 return nil, errors.Wrap(err, "opening headers file") 62 } 63 64 defer f.Close() 65 66 h, err := hdr.Parse(f) 67 if err != nil { 68 return nil, errors.Wrap(err, "parsing") 69 } 70 71 for path, fields := range h { 72 rules[path] = make(header.Fields) 73 for name, vals := range fields { 74 rules[path][name] = vals[0] 75 } 76 } 77 78 return rules, nil 79 }