github.com/google/martian/v3@v3.3.3/method/method_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 method
    16  
    17  import (
    18  	"encoding/json"
    19  	"net/http"
    20  	"strings"
    21  
    22  	"github.com/google/martian/v3"
    23  	"github.com/google/martian/v3/filter"
    24  	"github.com/google/martian/v3/log"
    25  	"github.com/google/martian/v3/parse"
    26  )
    27  
    28  var noop = martian.Noop("method.Filter")
    29  
    30  func init() {
    31  	parse.Register("method.Filter", filterFromJSON)
    32  }
    33  
    34  // Filter runs modifier iff the request method matches the specified method.
    35  type Filter struct {
    36  	*filter.Filter
    37  }
    38  
    39  type filterJSON struct {
    40  	Method       string               `json:"method"`
    41  	Modifier     json.RawMessage      `json:"modifier"`
    42  	ElseModifier json.RawMessage      `json:"else"`
    43  	Scope        []parse.ModifierType `json:"scope"`
    44  }
    45  
    46  func filterFromJSON(b []byte) (*parse.Result, error) {
    47  	msg := &filterJSON{}
    48  	if err := json.Unmarshal(b, msg); err != nil {
    49  		return nil, err
    50  	}
    51  
    52  	filter := NewFilter(msg.Method)
    53  
    54  	m, err := parse.FromJSON(msg.Modifier)
    55  	if err != nil {
    56  		return nil, err
    57  	}
    58  
    59  	filter.RequestWhenTrue(m.RequestModifier())
    60  	filter.ResponseWhenTrue(m.ResponseModifier())
    61  
    62  	if len(msg.ElseModifier) > 0 {
    63  		em, err := parse.FromJSON(msg.ElseModifier)
    64  		if err != nil {
    65  			return nil, err
    66  		}
    67  
    68  		if em != nil {
    69  			filter.RequestWhenFalse(em.RequestModifier())
    70  			filter.ResponseWhenFalse(em.ResponseModifier())
    71  		}
    72  	}
    73  
    74  	return parse.NewResult(filter, msg.Scope)
    75  }
    76  
    77  // NewFilter constructs a filter that applies the modifer when the
    78  // request method matches meth.
    79  func NewFilter(meth string) *Filter {
    80  	log.Debugf("method.NewFilter(%q)", meth)
    81  	m := NewMatcher(meth)
    82  	f := filter.New()
    83  	f.SetRequestCondition(m)
    84  	f.SetResponseCondition(m)
    85  	return &Filter{f}
    86  }
    87  
    88  // Matcher is a conditional evaluator of request methods to be used in
    89  // filters that take conditionals.
    90  type Matcher struct {
    91  	method string
    92  }
    93  
    94  // NewMatcher builds a new method matcher.
    95  func NewMatcher(method string) *Matcher {
    96  	return &Matcher{
    97  		method: method,
    98  	}
    99  }
   100  
   101  // MatchRequest retuns true if m.method matches the request method.
   102  func (m *Matcher) MatchRequest(req *http.Request) bool {
   103  	matched := m.matches(req.Method)
   104  	if matched {
   105  		log.Debugf("method.MatchRequest: matched %s request: %s", req.Method, req.URL)
   106  	}
   107  	return matched
   108  }
   109  
   110  // MatchResponse retuns true if m.method matches res.Request.Method.
   111  func (m *Matcher) MatchResponse(res *http.Response) bool {
   112  	matched := m.matches(res.Request.Method)
   113  	if matched {
   114  		log.Debugf("method.MatchResponse: matched %s request: %s", res.Request.Method, res.Request.URL)
   115  	}
   116  	return matched
   117  }
   118  
   119  func (m *Matcher) matches(method string) bool {
   120  	return strings.EqualFold(method, m.method)
   121  }