github.com/hellofresh/janus@v0.0.0-20230925145208-ce8de8183c67/pkg/plugin/requesttransformer/middleware.go (about)

     1  package requesttransformer
     2  
     3  import (
     4  	"net/http"
     5  	"net/url"
     6  )
     7  
     8  type headerFn func(headerName string, headerValue string)
     9  
    10  // Options represents the available options to transform
    11  type Options struct {
    12  	Headers     map[string]string `json:"headers"`
    13  	QueryString map[string]string `json:"querystring"`
    14  }
    15  
    16  // Config represent the configuration of the modify headers middleware
    17  type Config struct {
    18  	Add     Options `json:"add"`
    19  	Append  Options `json:"append"`
    20  	Remove  Options `json:"remove"`
    21  	Replace Options `json:"replace"`
    22  }
    23  
    24  // NewRequestTransformer creates a new instance of RequestTransformer
    25  func NewRequestTransformer(config Config) func(http.Handler) http.Handler {
    26  	return func(next http.Handler) http.Handler {
    27  		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    28  			query := r.URL.Query()
    29  
    30  			transform(config.Remove.Headers, removeHeaders(r))
    31  			transform(config.Remove.QueryString, removeQueryString(query))
    32  
    33  			transform(config.Replace.Headers, replaceHeaders(r))
    34  			transform(config.Replace.QueryString, replaceQueryString(query))
    35  
    36  			transform(config.Add.Headers, addHeaders(r))
    37  			transform(config.Add.QueryString, addQueryString(query))
    38  
    39  			transform(config.Append.Headers, appendHeaders(r))
    40  			transform(config.Append.QueryString, appendQueryString(query))
    41  
    42  			r.URL.RawQuery = query.Encode()
    43  
    44  			next.ServeHTTP(w, r)
    45  		})
    46  	}
    47  }
    48  
    49  // If and only if the header is not already set, set a new header with the given value. Ignored if the header is already set.
    50  func addHeaders(r *http.Request) headerFn {
    51  	return func(headerName string, headerValue string) {
    52  		if r.Header.Get(headerName) == "" {
    53  			r.Header.Add(headerName, headerValue)
    54  		}
    55  	}
    56  }
    57  
    58  // If the header is not set, set it with the given value. If it is already set, a new header with the same name and the new value will be set.
    59  func appendHeaders(r *http.Request) headerFn {
    60  	return func(headerName string, headerValue string) {
    61  		r.Header.Add(headerName, headerValue)
    62  	}
    63  }
    64  
    65  // Unset the headers with the given name.
    66  func removeHeaders(r *http.Request) headerFn {
    67  	return func(headerName string, headerValue string) {
    68  		r.Header.Del(headerName)
    69  	}
    70  }
    71  
    72  // If and only if the header is already set, replace its old value with the new one. Ignored if the header is not already set.
    73  func replaceHeaders(r *http.Request) headerFn {
    74  	return func(headerName string, headerValue string) {
    75  		if r.Header.Get(headerName) != "" {
    76  			r.Header.Set(headerName, headerValue)
    77  		}
    78  	}
    79  }
    80  
    81  func transform(values map[string]string, fn headerFn) {
    82  	if len(values) <= 0 {
    83  		return
    84  	}
    85  
    86  	for name, value := range values {
    87  		fn(name, value)
    88  	}
    89  }
    90  
    91  func addQueryString(query url.Values) headerFn {
    92  	return func(name string, value string) {
    93  		if query.Get(name) == "" {
    94  			query.Add(name, value)
    95  		}
    96  	}
    97  }
    98  
    99  func appendQueryString(query url.Values) headerFn {
   100  	return func(name string, value string) {
   101  		query.Add(name, value)
   102  	}
   103  }
   104  
   105  func removeQueryString(query url.Values) headerFn {
   106  	return func(name string, value string) {
   107  		query.Del(name)
   108  	}
   109  }
   110  
   111  func replaceQueryString(query url.Values) headerFn {
   112  	return func(name string, value string) {
   113  		if query.Get(name) != "" {
   114  			query.Set(name, value)
   115  		}
   116  	}
   117  }