gitlab.com/gitlab-org/labkit@v1.21.0/mask/url.go (about)

     1  package mask
     2  
     3  import (
     4  	"bytes"
     5  	"net/url"
     6  )
     7  
     8  // URL will mask the sensitive components in an URL with `[FILTERED]`.
     9  // This list should maintain parity with the list in
    10  // GitLab-CE, maintained at https://gitlab.com/gitlab-org/gitlab-ce/blob/master/config/application.rb.
    11  // Based on https://stackoverflow.com/a/52965552/474597.
    12  func URL(originalURL string) string {
    13  	u, err := url.Parse(originalURL)
    14  	if err != nil {
    15  		return "<invalid URL>"
    16  	}
    17  	if u.User != nil {
    18  		username := u.User.Username()
    19  		_, hasPass := u.User.Password()
    20  		switch {
    21  		case username != "" && hasPass:
    22  			u.User = url.UserPassword("FILTERED", "FILTERED")
    23  		case username != "" && !hasPass:
    24  			u.User = url.User("FILTERED")
    25  		}
    26  	}
    27  
    28  	redactionBytes := []byte(RedactionString)
    29  	buf := bytes.NewBuffer(make([]byte, 0, len(originalURL)))
    30  
    31  	for i, queryPart := range bytes.Split([]byte(u.RawQuery), []byte("&")) {
    32  		if i != 0 {
    33  			buf.WriteByte('&')
    34  		}
    35  
    36  		splitParam := bytes.SplitN(queryPart, []byte("="), 2)
    37  
    38  		if len(splitParam) == 2 {
    39  			buf.Write(splitParam[0])
    40  			buf.WriteByte('=')
    41  
    42  			if parameterMatcher.Match(splitParam[0]) {
    43  				buf.Write(redactionBytes)
    44  			} else {
    45  				buf.Write(splitParam[1])
    46  			}
    47  		} else {
    48  			buf.Write(queryPart)
    49  		}
    50  	}
    51  	u.RawQuery = buf.String()
    52  	return u.String()
    53  }