Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.
 
 
 

269 righe
6.7 KiB

  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. // Package fifo provides Group, which is a list of modifiers that are executed
  15. // consecutively. By default, when an error is returned by a modifier, the
  16. // execution of the modifiers is halted, and the error is returned. Optionally,
  17. // when errror aggregation is enabled (by calling SetAggretateErrors(true)), modifier
  18. // execution is not halted, and errors are aggretated and returned after all
  19. // modifiers have been executed.
  20. package fifo
  21. import (
  22. "encoding/json"
  23. "net/http"
  24. "sync"
  25. "github.com/google/martian"
  26. "github.com/google/martian/log"
  27. "github.com/google/martian/parse"
  28. "github.com/google/martian/verify"
  29. )
  30. // Group is a martian.RequestResponseModifier that maintains lists of
  31. // request and response modifiers executed on a first-in, first-out basis.
  32. type Group struct {
  33. reqmu sync.RWMutex
  34. reqmods []martian.RequestModifier
  35. resmu sync.RWMutex
  36. resmods []martian.ResponseModifier
  37. aggregateErrors bool
  38. }
  39. type groupJSON struct {
  40. Modifiers []json.RawMessage `json:"modifiers"`
  41. Scope []parse.ModifierType `json:"scope"`
  42. AggregateErrors bool `json:"aggregateErrors"`
  43. }
  44. func init() {
  45. parse.Register("fifo.Group", groupFromJSON)
  46. }
  47. // NewGroup returns a modifier group.
  48. func NewGroup() *Group {
  49. return &Group{}
  50. }
  51. // SetAggregateErrors sets the error behavior for the Group. When true, the Group will
  52. // continue to execute consecutive modifiers when a modifier in the group encounters an
  53. // error. The Group will then return all errors returned by each modifier after all
  54. // modifiers have been executed. When false, if an error is returned by a modifier, the
  55. // error is returned by ModifyRequest/Response and no further modifiers are run.
  56. // By default, error aggregation is disabled.
  57. func (g *Group) SetAggregateErrors(aggerr bool) {
  58. g.aggregateErrors = aggerr
  59. }
  60. // AddRequestModifier adds a RequestModifier to the group's list of request modifiers.
  61. func (g *Group) AddRequestModifier(reqmod martian.RequestModifier) {
  62. g.reqmu.Lock()
  63. defer g.reqmu.Unlock()
  64. g.reqmods = append(g.reqmods, reqmod)
  65. }
  66. // AddResponseModifier adds a ResponseModifier to the group's list of response modifiers.
  67. func (g *Group) AddResponseModifier(resmod martian.ResponseModifier) {
  68. g.resmu.Lock()
  69. defer g.resmu.Unlock()
  70. g.resmods = append(g.resmods, resmod)
  71. }
  72. // ModifyRequest modifies the request. By default, aggregateErrors is false; if an error is
  73. // returned by a RequestModifier the error is returned and no further modifiers are run. When
  74. // aggregateErrors is set to true, the errors returned by each modifier in the group are
  75. // aggregated.
  76. func (g *Group) ModifyRequest(req *http.Request) error {
  77. log.Debugf("fifo.ModifyRequest: %s", req.URL)
  78. g.reqmu.RLock()
  79. defer g.reqmu.RUnlock()
  80. merr := martian.NewMultiError()
  81. for _, reqmod := range g.reqmods {
  82. if err := reqmod.ModifyRequest(req); err != nil {
  83. if g.aggregateErrors {
  84. merr.Add(err)
  85. continue
  86. }
  87. return err
  88. }
  89. }
  90. if merr.Empty() {
  91. return nil
  92. }
  93. return merr
  94. }
  95. // ModifyResponse modifies the request. By default, aggregateErrors is false; if an error is
  96. // returned by a RequestModifier the error is returned and no further modifiers are run. When
  97. // aggregateErrors is set to true, the errors returned by each modifier in the group are
  98. // aggregated.
  99. func (g *Group) ModifyResponse(res *http.Response) error {
  100. requ := ""
  101. if res.Request != nil {
  102. requ = res.Request.URL.String()
  103. log.Debugf("fifo.ModifyResponse: %s", requ)
  104. }
  105. g.resmu.RLock()
  106. defer g.resmu.RUnlock()
  107. merr := martian.NewMultiError()
  108. for _, resmod := range g.resmods {
  109. if err := resmod.ModifyResponse(res); err != nil {
  110. if g.aggregateErrors {
  111. merr.Add(err)
  112. continue
  113. }
  114. return err
  115. }
  116. }
  117. if merr.Empty() {
  118. return nil
  119. }
  120. return merr
  121. }
  122. // VerifyRequests returns a MultiError containing all the
  123. // verification errors returned by request verifiers.
  124. func (g *Group) VerifyRequests() error {
  125. log.Debugf("fifo.VerifyRequests()")
  126. g.reqmu.Lock()
  127. defer g.reqmu.Unlock()
  128. merr := martian.NewMultiError()
  129. for _, reqmod := range g.reqmods {
  130. reqv, ok := reqmod.(verify.RequestVerifier)
  131. if !ok {
  132. continue
  133. }
  134. if err := reqv.VerifyRequests(); err != nil {
  135. merr.Add(err)
  136. }
  137. }
  138. if merr.Empty() {
  139. return nil
  140. }
  141. return merr
  142. }
  143. // VerifyResponses returns a MultiError containing all the
  144. // verification errors returned by response verifiers.
  145. func (g *Group) VerifyResponses() error {
  146. log.Debugf("fifo.VerifyResponses()")
  147. g.resmu.Lock()
  148. defer g.resmu.Unlock()
  149. merr := martian.NewMultiError()
  150. for _, resmod := range g.resmods {
  151. resv, ok := resmod.(verify.ResponseVerifier)
  152. if !ok {
  153. continue
  154. }
  155. if err := resv.VerifyResponses(); err != nil {
  156. merr.Add(err)
  157. }
  158. }
  159. if merr.Empty() {
  160. return nil
  161. }
  162. return merr
  163. }
  164. // ResetRequestVerifications resets the state of the contained request verifiers.
  165. func (g *Group) ResetRequestVerifications() {
  166. log.Debugf("fifo.ResetRequestVerifications()")
  167. g.reqmu.Lock()
  168. defer g.reqmu.Unlock()
  169. for _, reqmod := range g.reqmods {
  170. if reqv, ok := reqmod.(verify.RequestVerifier); ok {
  171. reqv.ResetRequestVerifications()
  172. }
  173. }
  174. }
  175. // ResetResponseVerifications resets the state of the contained request verifiers.
  176. func (g *Group) ResetResponseVerifications() {
  177. log.Debugf("fifo.ResetResponseVerifications()")
  178. g.resmu.Lock()
  179. defer g.resmu.Unlock()
  180. for _, resmod := range g.resmods {
  181. if resv, ok := resmod.(verify.ResponseVerifier); ok {
  182. resv.ResetResponseVerifications()
  183. }
  184. }
  185. }
  186. // groupFromJSON builds a fifo.Group from JSON.
  187. //
  188. // Example JSON:
  189. // {
  190. // "fifo.Group" : {
  191. // "scope": ["request", "result"],
  192. // "modifiers": [
  193. // { ... },
  194. // { ... },
  195. // ]
  196. // }
  197. // }
  198. func groupFromJSON(b []byte) (*parse.Result, error) {
  199. msg := &groupJSON{}
  200. if err := json.Unmarshal(b, msg); err != nil {
  201. return nil, err
  202. }
  203. g := NewGroup()
  204. if msg.AggregateErrors {
  205. g.SetAggregateErrors(true)
  206. }
  207. for _, m := range msg.Modifiers {
  208. r, err := parse.FromJSON(m)
  209. if err != nil {
  210. return nil, err
  211. }
  212. reqmod := r.RequestModifier()
  213. if reqmod != nil {
  214. g.AddRequestModifier(reqmod)
  215. }
  216. resmod := r.ResponseModifier()
  217. if resmod != nil {
  218. g.AddResponseModifier(resmod)
  219. }
  220. }
  221. return parse.NewResult(g, msg.Scope)
  222. }