...

Source file src/github.com/henvic/httpretty/internal/header/header.go

Documentation: github.com/henvic/httpretty/internal/header

     1  // Package header can be used to sanitize HTTP request and response headers.
     2  package header
     3  
     4  import (
     5  	"fmt"
     6  	"net/http"
     7  	"strings"
     8  )
     9  
    10  // Sanitize list of headers.
    11  // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ can be consulted for header syntax.
    12  func Sanitize(sanitizers map[string]SanitizeHeaderFunc, headers http.Header) http.Header {
    13  	var redacted = http.Header{}
    14  
    15  	for k, values := range headers {
    16  		if s, ok := sanitizers[http.CanonicalHeaderKey(k)]; ok {
    17  			redacted[k] = sanitize(s, values)
    18  			continue
    19  		}
    20  
    21  		redacted[k] = values
    22  	}
    23  
    24  	return redacted
    25  }
    26  
    27  func sanitize(s SanitizeHeaderFunc, values []string) []string {
    28  	var redacted = []string{}
    29  
    30  	for _, v := range values {
    31  		redacted = append(redacted, s(v))
    32  	}
    33  
    34  	return redacted
    35  }
    36  
    37  // DefaultSanitizers contains a list of sanitizers to be used for common headers.
    38  var DefaultSanitizers = map[string]SanitizeHeaderFunc{
    39  	"Authorization":       AuthorizationSanitizer,
    40  	"Set-Cookie":          SetCookieSanitizer,
    41  	"Cookie":              CookieSanitizer,
    42  	"Proxy-Authorization": AuthorizationSanitizer,
    43  }
    44  
    45  // SanitizeHeaderFunc implements sanitization for a header value.
    46  type SanitizeHeaderFunc func(string) string
    47  
    48  // AuthorizationSanitizer is used to sanitize Authorization and Proxy-Authorization headers.
    49  func AuthorizationSanitizer(unsafe string) string {
    50  	if unsafe == "" {
    51  		return ""
    52  	}
    53  
    54  	directives := strings.SplitN(unsafe, " ", 2)
    55  
    56  	l := 0
    57  
    58  	if len(directives) > 1 {
    59  		l = len(directives[1])
    60  	}
    61  
    62  	if l == 0 {
    63  		return directives[0]
    64  	}
    65  
    66  	return directives[0] + " " + redact(l)
    67  }
    68  
    69  // SetCookieSanitizer is used to sanitize Set-Cookie header.
    70  func SetCookieSanitizer(unsafe string) string {
    71  	directives := strings.SplitN(unsafe, ";", 2)
    72  
    73  	cookie := strings.SplitN(directives[0], "=", 2)
    74  
    75  	l := 0
    76  
    77  	if len(cookie) > 1 {
    78  		l = len(cookie[1])
    79  	}
    80  
    81  	if len(directives) == 2 {
    82  		return fmt.Sprintf("%s=%s; %s", cookie[0], redact(l), strings.TrimPrefix(directives[1], " "))
    83  	}
    84  
    85  	return fmt.Sprintf("%s=%s", cookie[0], redact(l))
    86  }
    87  
    88  // CookieSanitizer is used to sanitize Cookie header.
    89  func CookieSanitizer(unsafe string) string {
    90  	cookies := strings.Split(unsafe, ";")
    91  
    92  	var list []string
    93  
    94  	for _, unsafeCookie := range cookies {
    95  		cookie := strings.SplitN(unsafeCookie, "=", 2)
    96  		l := 0
    97  
    98  		if len(cookie) > 1 {
    99  			l = len(cookie[1])
   100  		}
   101  
   102  		list = append(list, fmt.Sprintf("%s=%s", cookie[0], redact(l)))
   103  	}
   104  
   105  	return strings.Join(list, "; ")
   106  }
   107  
   108  func redact(count int) string {
   109  	if count == 0 {
   110  		return ""
   111  	}
   112  
   113  	return "████████████████████"
   114  }
   115  

View as plain text