github.com/google/martian/v3@v3.3.3/h2/processor.go (about) 1 // Copyright 2021 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 h2 16 17 import ( 18 "fmt" 19 "net/url" 20 21 "golang.org/x/net/http2" 22 "golang.org/x/net/http2/hpack" 23 ) 24 25 // Direction indicates the direction of the traffic flow. 26 type Direction uint8 27 28 const ( 29 // ClientToServer indicates traffic flowing from client-to-server. 30 ClientToServer Direction = iota 31 // ServerToClient indicates traffic flowing from server-to-client. 32 ServerToClient 33 ) 34 35 // StreamProcessorFactory is implemented by clients that wish to observe or edit HTTP/2 frames 36 // flowing through the proxy. It creates a pair of processors for the bidirectional stream. A 37 // processor consumes frames then calls the corresponding sink methods to forward frames to the 38 // destination, modifying the frame if needed. 39 // 40 // Returns the client-to-server and server-to-client processors. Nil values are safe to return and 41 // no processing occurs in such cases. NOTE: an interface may have a non-nil type with a nil value. 42 // Such values are treated as valid processors. 43 // 44 // Concurrency: there is a separate client-to-server and server-to-client thread. Calls against 45 // the `ClientToServer` sink must be made on the client-to-server thread and calls against 46 // the `ServerToClient` sink must be made on the server-to-client thread. Implementors should 47 // guard interactions across threads. 48 type StreamProcessorFactory func(url *url.URL, sinks *Processors) (Processor, Processor) 49 50 // Processors encapsulates the two traffic receiving endpoints. 51 type Processors struct { 52 cToS, sToC Processor 53 } 54 55 // ForDirection returns the processor receiving traffic in the given direction. 56 func (s *Processors) ForDirection(dir Direction) Processor { 57 switch dir { 58 case ClientToServer: 59 return s.cToS 60 case ServerToClient: 61 return s.sToC 62 } 63 panic(fmt.Sprintf("invalid direction: %v", dir)) 64 } 65 66 // Processor accepts the possible stream frames. 67 // 68 // This API abstracts away some of the lower level HTTP/2 mechanisms. 69 // CONTINUATION frames are appropriately buffered and turned into Header calls and Header or 70 // PushPromise calls are split into CONTINUATION frames when needed. 71 // 72 // The proxy handles WINDOW_UPDATE frames and flow control, managing it independently for both 73 // endpoints. 74 type Processor interface { 75 DataFrameProcessor 76 HeaderProcessor 77 PriorityFrameProcessor 78 RSTStreamProcessor 79 PushPromiseProcessor 80 } 81 82 // DataFrameProcessor processes data frames. 83 type DataFrameProcessor interface { 84 Data(data []byte, streamEnded bool) error 85 } 86 87 // HeaderProcessor processes headers, abstracting out continuations. 88 type HeaderProcessor interface { 89 Header( 90 headers []hpack.HeaderField, 91 streamEnded bool, 92 priority http2.PriorityParam, 93 ) error 94 } 95 96 // PriorityFrameProcessor processes priority frames. 97 type PriorityFrameProcessor interface { 98 Priority(http2.PriorityParam) error 99 } 100 101 // RSTStreamProcessor processes RSTStream frames. 102 type RSTStreamProcessor interface { 103 RSTStream(http2.ErrCode) error 104 } 105 106 // PushPromiseProcessor processes push promises, abstracting out continuations. 107 type PushPromiseProcessor interface { 108 PushPromise(promiseID uint32, headers []hpack.HeaderField) error 109 } 110 111 // relayAdapter implements the Processor interface by delegating to an underlying relay. 112 type relayAdapter struct { 113 id uint32 114 relay *relay 115 } 116 117 func (r *relayAdapter) Data(data []byte, streamEnded bool) error { 118 return r.relay.data(r.id, data, streamEnded) 119 } 120 121 func (r *relayAdapter) Header( 122 headers []hpack.HeaderField, 123 streamEnded bool, 124 priority http2.PriorityParam, 125 ) error { 126 return r.relay.header(r.id, headers, streamEnded, priority) 127 } 128 129 func (r *relayAdapter) Priority(priority http2.PriorityParam) error { 130 r.relay.priority(r.id, priority) 131 return nil 132 } 133 134 func (r *relayAdapter) RSTStream(errCode http2.ErrCode) error { 135 r.relay.rstStream(r.id, errCode) 136 return nil 137 } 138 139 func (r *relayAdapter) PushPromise(promiseID uint32, headers []hpack.HeaderField) error { 140 return r.relay.pushPromise(r.id, promiseID, headers) 141 }