MCPcopy
hub / github.com/keploy/keploy / HandleFrame

Method HandleFrame

pkg/http2.go:176–314  ·  view source on GitHub ↗

HandleFrame processes an HTTP/2 frame isOutgoing=false => incoming (client->server) => REQUEST side isOutgoing=true => outgoing (server->client) => RESPONSE side

(frame http2.Frame, isOutgoing bool, frameTime time.Time)

Source from the content-addressed store, hash-verified

174// isOutgoing=false => incoming (client->server) => REQUEST side
175// isOutgoing=true => outgoing (server->client) => RESPONSE side
176func (sm *DefaultStreamManager) HandleFrame(frame http2.Frame, isOutgoing bool, frameTime time.Time) error {
177 sm.mutex.Lock()
178 defer sm.mutex.Unlock()
179
180 streamID := frame.Header().StreamID
181 if streamID == 0 {
182 // Handle SETTINGS frames to keep HPACK decoders in sync with
183 // the negotiated dynamic table size. Without this, the decoders
184 // stay at the initial MaxDynamicTableSize (8192) and fail to
185 // decode headers when the peer negotiates a larger table via
186 // SETTINGS_HEADER_TABLE_SIZE.
187 if sf, ok := frame.(*http2.SettingsFrame); ok && !sf.IsAck() {
188 sm.updateDecoderTableSize(sf, isOutgoing)
189 }
190 return nil
191 }
192
193 // Init stream
194 if _, exists := sm.streams[streamID]; !exists {
195 prefix := "Incoming_"
196 if isOutgoing {
197 prefix = "Outgoing_"
198 }
199 requestID := fmt.Sprintf(prefix+"%d", streamID)
200 sm.streams[streamID] = &HTTP2StreamState{
201 ID: streamID,
202 RequestID: requestID,
203 }
204 }
205 s := sm.streams[streamID]
206 if !isOutgoing && s.startTime.IsZero() {
207 s.startTime = frameTime
208 }
209
210 switch f := frame.(type) {
211
212 case *http2.HeadersFrame:
213 // Copy the header block fragment — http2.Framer reuses its internal
214 // buffer, so f.HeaderBlockFragment() becomes invalid after the next
215 // ReadFrame() call.
216 fragCopy := make([]byte, len(f.HeaderBlockFragment()))
217 copy(fragCopy, f.HeaderBlockFragment())
218
219 if isOutgoing {
220 s.respHeaderFrags = append(s.respHeaderFrags, fragCopy)
221 if f.HeadersEnded() {
222 if err := sm.processHeaderBlock(s /*isOutgoing=*/, true); err != nil {
223 return err
224 }
225 }
226 if f.StreamEnded() {
227 s.respEndStreamReceived = true
228 // gRPC error responses send a single HEADERS frame with END_STREAM
229 // that merges initial headers and trailers (grpc-status, grpc-message).
230 // processHeaderBlock treated it as initial headers, so respTrailersReceived
231 // is still false. Promote the initial headers to trailers so that
232 // checkStreamCompletion can mark the stream complete.
233 if s.respHeadersReceived && !s.respTrailersReceived {

Calls 6

processHeaderBlockMethod · 0.95
checkStreamCompletionMethod · 0.95
IsZeroMethod · 0.80
CloneMethod · 0.45