-
Notifications
You must be signed in to change notification settings - Fork 0
/
h2_streamprocess.go
100 lines (81 loc) · 2.87 KB
/
h2_streamprocess.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
package fns
import (
"log"
"github.com/pablolagos/fns/internal/hpack"
)
// StreamProcessor handles the processing of HTTP/2 streams
type StreamProcessor struct{}
// NewStreamProcessor creates a new StreamProcessor
func NewStreamProcessor() *StreamProcessor {
return &StreamProcessor{}
}
// ProcessStream processes a completed HTTP/2 stream
func (sp *StreamProcessor) ProcessStream(stream *Stream, s *Server) {
// Create a new RequestCtx
ctx := &RequestCtx{}
// Populate the RequestCtx with the headers and body from the stream
sp.populateRequestCtx(ctx, stream)
// Call the handler
s.Handler(ctx)
// Process the response from the handler
sp.processResponse(ctx, stream)
}
// populateRequestCtx populates the RequestCtx with data from the stream
func (sp *StreamProcessor) populateRequestCtx(ctx *RequestCtx, stream *Stream) {
// Parse headers from the stream and populate the RequestCtx
for _, headerField := range stream.Headers {
ctx.Request.Header.Set(headerField.Name, headerField.Value)
}
// Determine the HTTP method
method := ctx.Request.Header.Method()
if len(method) == 0 {
method = []byte("GET") // Default method if not set
}
ctx.Request.Header.SetMethodBytes(method)
// Set the request body
ctx.Request.SetBody(stream.Body)
// Extract the URI from the headers
uri := ctx.Request.Header.Peek(":path")
if uri != nil {
ctx.Request.SetRequestURIBytes(uri)
}
// Set the host
host := ctx.Request.Header.Peek("host")
if host != nil {
ctx.Request.SetHostBytes(host)
}
// Set the scheme
scheme := ctx.Request.Header.Peek(":scheme")
if scheme == nil {
scheme = []byte("https") // Default to https if not set
}
ctx.Request.URI().SetSchemeBytes(scheme)
// Set the authority (host:port)
authority := ctx.Request.Header.Peek(":authority")
if authority != nil {
ctx.Request.URI().SetHostBytes(authority)
}
// Set the remote address
remoteAddr := stream.conn.conn.RemoteAddr()
ctx.Init(&ctx.Request, remoteAddr, ctx.Logger())
// Log the populated request context for debugging
log.Printf("Request Headers: %s", ctx.Request.Header.String())
log.Printf("Request URI: %s", ctx.Request.URI().String())
log.Printf("Request Body: %s", string(ctx.Request.Body()))
}
// processResponse processes the response and updates the stream
func (sp *StreamProcessor) processResponse(ctx *RequestCtx, stream *Stream) {
// Copy the response headers and body from the RequestCtx to the stream
response := ctx.Response
stream.ResponseHeaders = make([]hpack.HeaderField, 0, response.Header.Len())
response.Header.VisitAll(func(key, value []byte) {
stream.ResponseHeaders = append(stream.ResponseHeaders, hpack.HeaderField{
Name: string(key),
Value: string(value),
})
})
stream.ResponseBody = response.Body()
// Log the processed response for debugging
log.Printf("Response Headers: %s", response.Header.String())
log.Printf("Response Body: %s", string(response.Body()))
}