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