github.com/google/martian/v3@v3.3.3/filter/filter.go (about)

     1  // Copyright 2015 Google Inc. All rights reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  // Package filter provides a modifier that executes a given set of child
    16  // modifiers based on the evaluated value of the provided conditional.
    17  package filter
    18  
    19  import (
    20  	"fmt"
    21  	"net/http"
    22  
    23  	"github.com/google/martian/v3"
    24  	"github.com/google/martian/v3/log"
    25  	"github.com/google/martian/v3/verify"
    26  )
    27  
    28  var noop = martian.Noop("Filter")
    29  
    30  // Filter is a modifer that contains conditions to evaluate on request and
    31  // response as well as a set of modifiers to execute based on the value of
    32  // the provided RequestCondition or ResponseCondition.
    33  type Filter struct {
    34  	reqcond RequestCondition
    35  	rescond ResponseCondition
    36  
    37  	treqmod martian.RequestModifier
    38  	tresmod martian.ResponseModifier
    39  	freqmod martian.RequestModifier
    40  	fresmod martian.ResponseModifier
    41  }
    42  
    43  // New returns a pointer to a Filter with all child modifiers initialized to
    44  // the noop modifier.
    45  func New() *Filter {
    46  	return &Filter{
    47  		treqmod: noop,
    48  		tresmod: noop,
    49  		fresmod: noop,
    50  		freqmod: noop,
    51  	}
    52  }
    53  
    54  // SetRequestCondition sets the condition to evaluate on requests.
    55  func (f *Filter) SetRequestCondition(reqcond RequestCondition) {
    56  	f.reqcond = reqcond
    57  }
    58  
    59  // SetResponseCondition sets the condition to evaluate on responses.
    60  func (f *Filter) SetResponseCondition(rescond ResponseCondition) {
    61  	f.rescond = rescond
    62  }
    63  
    64  // SetRequestModifier sets the martian.RequestModifier that is executed
    65  // when the RequestCondition evaluates to True.  This function is provided
    66  // to maintain backwards compatability with filtering prior to filter.Filter.
    67  func (f *Filter) SetRequestModifier(reqmod martian.RequestModifier) {
    68  	f.RequestWhenTrue(reqmod)
    69  }
    70  
    71  // RequestWhenTrue sets the martian.RequestModifier that is executed
    72  // when the RequestCondition evaluates to True.
    73  func (f *Filter) RequestWhenTrue(mod martian.RequestModifier) {
    74  	if mod == nil {
    75  		f.treqmod = noop
    76  		return
    77  	}
    78  
    79  	f.treqmod = mod
    80  }
    81  
    82  // SetResponseModifier sets the martian.ResponseModifier that is executed
    83  // when the ResponseCondition evaluates to True.  This function is provided
    84  // to maintain backwards compatability with filtering prior to filter.Filter.
    85  func (f *Filter) SetResponseModifier(resmod martian.ResponseModifier) {
    86  	f.ResponseWhenTrue(resmod)
    87  }
    88  
    89  // RequestWhenFalse sets the martian.RequestModifier that is executed
    90  // when the RequestCondition evaluates to False.
    91  func (f *Filter) RequestWhenFalse(mod martian.RequestModifier) {
    92  	if mod == nil {
    93  		f.freqmod = noop
    94  		return
    95  	}
    96  
    97  	f.freqmod = mod
    98  }
    99  
   100  // ResponseWhenTrue sets the martian.ResponseModifier that is executed
   101  // when the ResponseCondition evaluates to True.
   102  func (f *Filter) ResponseWhenTrue(mod martian.ResponseModifier) {
   103  	if mod == nil {
   104  		f.tresmod = noop
   105  		return
   106  	}
   107  
   108  	f.tresmod = mod
   109  }
   110  
   111  // ResponseWhenFalse sets the martian.ResponseModifier that is executed
   112  // when the ResponseCondition evaluates to False.
   113  func (f *Filter) ResponseWhenFalse(mod martian.ResponseModifier) {
   114  	if mod == nil {
   115  		f.fresmod = noop
   116  		return
   117  	}
   118  
   119  	f.fresmod = mod
   120  }
   121  
   122  // ModifyRequest evaluates reqcond and executes treqmod iff reqcond evaluates
   123  // to true; otherwise, freqmod is executed.
   124  func (f *Filter) ModifyRequest(req *http.Request) error {
   125  	if f.reqcond == nil {
   126  		return fmt.Errorf("filter.ModifyRequest: no request condition set. Set condition with SetRequestCondition")
   127  	}
   128  
   129  	match := f.reqcond.MatchRequest(req)
   130  	if match {
   131  		log.Debugf("filter.ModifyRequest: matched %s", req.URL)
   132  		return f.treqmod.ModifyRequest(req)
   133  	}
   134  
   135  	return f.freqmod.ModifyRequest(req)
   136  }
   137  
   138  // ModifyResponse evaluates rescond and executes tresmod iff rescond evaluates
   139  // to true; otherwise, fresmod is executed.
   140  func (f *Filter) ModifyResponse(res *http.Response) error {
   141  	if f.rescond == nil {
   142  		return fmt.Errorf("filter.ModifyResponse: no response condition set. Set condition with SetResponseCondition")
   143  	}
   144  
   145  	match := f.rescond.MatchResponse(res)
   146  	if match {
   147  		requ := ""
   148  		if res.Request != nil {
   149  			requ = res.Request.URL.String()
   150  		}
   151  		log.Debugf("filter.ModifyResponse: %s", requ)
   152  		return f.tresmod.ModifyResponse(res)
   153  	}
   154  
   155  	return f.fresmod.ModifyResponse(res)
   156  }
   157  
   158  // VerifyRequests returns an error containing all the verification errors
   159  // returned by request verifiers.
   160  func (f *Filter) VerifyRequests() error {
   161  	merr := martian.NewMultiError()
   162  
   163  	freqv, ok := f.freqmod.(verify.RequestVerifier)
   164  	if ok {
   165  		if ve := freqv.VerifyRequests(); ve != nil {
   166  			merr.Add(ve)
   167  		}
   168  	}
   169  
   170  	treqv, ok := f.treqmod.(verify.RequestVerifier)
   171  	if ok {
   172  		if ve := treqv.VerifyRequests(); ve != nil {
   173  			merr.Add(ve)
   174  		}
   175  	}
   176  
   177  	if merr.Empty() {
   178  		return nil
   179  	}
   180  
   181  	return merr
   182  }
   183  
   184  // VerifyResponses returns an error containing all the verification errors
   185  // returned by response verifiers.
   186  func (f *Filter) VerifyResponses() error {
   187  	merr := martian.NewMultiError()
   188  
   189  	tresv, ok := f.tresmod.(verify.ResponseVerifier)
   190  	if ok {
   191  		if ve := tresv.VerifyResponses(); ve != nil {
   192  			merr.Add(ve)
   193  		}
   194  	}
   195  
   196  	fresv, ok := f.fresmod.(verify.ResponseVerifier)
   197  	if ok {
   198  		if ve := fresv.VerifyResponses(); ve != nil {
   199  			merr.Add(ve)
   200  		}
   201  	}
   202  
   203  	if merr.Empty() {
   204  		return nil
   205  	}
   206  
   207  	return merr
   208  }
   209  
   210  // ResetRequestVerifications resets the state of the contained request verifiers.
   211  func (f *Filter) ResetRequestVerifications() {
   212  	if treqv, ok := f.treqmod.(verify.RequestVerifier); ok {
   213  		treqv.ResetRequestVerifications()
   214  	}
   215  	if freqv, ok := f.freqmod.(verify.RequestVerifier); ok {
   216  		freqv.ResetRequestVerifications()
   217  	}
   218  }
   219  
   220  // ResetResponseVerifications resets the state of the contained request verifiers.
   221  func (f *Filter) ResetResponseVerifications() {
   222  	if tresv, ok := f.tresmod.(verify.ResponseVerifier); ok {
   223  		tresv.ResetResponseVerifications()
   224  	}
   225  }