github.com/google/martian/v3@v3.3.3/martianurl/url_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 martianurl 16 17 import ( 18 "encoding/json" 19 "net/url" 20 21 "github.com/google/martian/v3" 22 "github.com/google/martian/v3/filter" 23 "github.com/google/martian/v3/log" 24 "github.com/google/martian/v3/parse" 25 ) 26 27 var noop = martian.Noop("url.Filter") 28 29 func init() { 30 parse.Register("url.Filter", filterFromJSON) 31 } 32 33 // Filter runs modifiers iff the request URL matches all of the segments in url. 34 type Filter struct { 35 *filter.Filter 36 } 37 38 type filterJSON struct { 39 Scheme string `json:"scheme"` 40 Host string `json:"host"` 41 Path string `json:"path"` 42 Query string `json:"query"` 43 Modifier json.RawMessage `json:"modifier"` 44 ElseModifier json.RawMessage `json:"else"` 45 Scope []parse.ModifierType `json:"scope"` 46 } 47 48 // NewFilter constructs a filter that applies the modifer when the 49 // request URL matches all of the provided URL segments. 50 func NewFilter(u *url.URL) *Filter { 51 log.Debugf("martianurl.NewFilter: %s", u) 52 m := NewMatcher(u) 53 f := filter.New() 54 f.SetRequestCondition(m) 55 f.SetResponseCondition(m) 56 return &Filter{f} 57 } 58 59 // filterFromJSON takes a JSON message as a byte slice and returns a 60 // parse.Result that contains a URLFilter and a bitmask that represents the 61 // type of modifier. 62 // 63 // Example JSON configuration message: 64 // { 65 // "scheme": "https", 66 // "host": "example.com", 67 // "path": "/foo/bar", 68 // "query": "q=value", 69 // "scope": ["request", "response"], 70 // "modifier": { ... } 71 // "else": { ... } 72 // } 73 func filterFromJSON(b []byte) (*parse.Result, error) { 74 msg := &filterJSON{} 75 if err := json.Unmarshal(b, msg); err != nil { 76 return nil, err 77 } 78 79 filter := NewFilter(&url.URL{ 80 Scheme: msg.Scheme, 81 Host: msg.Host, 82 Path: msg.Path, 83 RawQuery: msg.Query, 84 }) 85 86 m, err := parse.FromJSON(msg.Modifier) 87 if err != nil { 88 return nil, err 89 } 90 91 filter.RequestWhenTrue(m.RequestModifier()) 92 filter.ResponseWhenTrue(m.ResponseModifier()) 93 94 if len(msg.ElseModifier) > 0 { 95 em, err := parse.FromJSON(msg.ElseModifier) 96 if err != nil { 97 return nil, err 98 } 99 100 if em != nil { 101 filter.RequestWhenFalse(em.RequestModifier()) 102 filter.ResponseWhenFalse(em.ResponseModifier()) 103 } 104 } 105 106 return parse.NewResult(filter, msg.Scope) 107 }