1package terminal
2
3import (
4	"net"
5	"net/http"
6	"regexp"
7	"strings"
8
9	log "github.com/sirupsen/logrus"
10)
11
12var scrubRegexp = regexp.MustCompile(`(?i)([\?&]((?:private|authenticity|rss)[\-_]token)|(?:X-AMZ-)?Signature)=[^&]*`)
13
14func fail500(w http.ResponseWriter, r *http.Request, err error) {
15	http.Error(w, "Internal server error", 500)
16	printError(r, err)
17}
18
19func printError(r *http.Request, err error) {
20	if r != nil {
21		log.WithFields(log.Fields{
22			"method": r.Method,
23			"uri":    scrubURLParams(r.RequestURI),
24		}).WithError(err).Error("error")
25	} else {
26		log.WithError(err).Error("unknown error")
27	}
28}
29
30func headerClone(h http.Header) http.Header {
31	h2 := make(http.Header, len(h))
32	for k, vv := range h {
33		vv2 := make([]string, len(vv))
34		copy(vv2, vv)
35		h2[k] = vv2
36	}
37	return h2
38}
39
40func setForwardedFor(newHeaders *http.Header, originalRequest *http.Request) {
41	if clientIP, _, err := net.SplitHostPort(originalRequest.RemoteAddr); err == nil {
42		var header string
43
44		// If we aren't the first proxy retain prior
45		// X-Forwarded-For information as a comma+space
46		// separated list and fold multiple headers into one.
47		if prior, ok := originalRequest.Header["X-Forwarded-For"]; ok {
48			header = strings.Join(prior, ", ") + ", " + clientIP
49		} else {
50			header = clientIP
51		}
52		newHeaders.Set("X-Forwarded-For", header)
53	}
54}
55
56// ScrubURLParams replaces the content of any sensitive query string parameters
57// in an URL with `[FILTERED]`
58func scrubURLParams(url string) string {
59	return scrubRegexp.ReplaceAllString(url, "$1=[FILTERED]")
60}
61