@@ -22,40 +22,23 @@ func parseRequest(req *http.Request, withTrailers bool) (*parsedMessage, error)
2222 if req == nil {
2323 return nil , nil
2424 }
25- err := validateMessageHeaders (req .Header )
26- if err != nil {
27- return nil , err
28- }
29- if withTrailers {
30- _ , err = duplicateBody (& req .Body ) // read the entire body to populate the trailers
31- if err != nil {
32- return nil , fmt .Errorf ("cannot duplicate request body: %w" , err )
33- }
34- err = validateMessageHeaders (req .Trailer )
35- if err != nil {
36- return nil , fmt .Errorf ("could not validate trailers: %w" , err )
37- }
25+
26+ scheme := "http"
27+ if req .TLS != nil {
28+ scheme = "https"
3829 }
39- // Query params are only obtained from the URL (i.e. not from the message body, when using application/x-www-form-urlencoded)
40- // So we are not vulnerable to the issue described in Sec. "Ambiguous Handling of Query Elements" of the draft.
41- values , err := url .ParseQuery (req .URL .RawQuery )
42- if err != nil {
43- return nil , fmt .Errorf ("cannot parse query: %s" , req .URL .RawQuery )
44- }
45- escaped := reEncodeQPs (values )
46- u := req .URL
47- if u .Host == "" {
48- u .Host = req .Host
49- }
50- if u .Scheme == "" {
51- if req .TLS == nil {
52- u .Scheme = "http"
53- } else {
54- u .Scheme = "https"
55- }
30+
31+ msg := & Message {
32+ method : req .Method ,
33+ url : req .URL ,
34+ headers : req .Header ,
35+ trailers : req .Trailer ,
36+ body : & req .Body ,
37+ authority : req .Host ,
38+ scheme : scheme ,
5639 }
57- return & parsedMessage { derived : generateReqDerivedComponents ( req ), url : u , headers : normalizeHeaderNames ( req . Header ),
58- trailers : normalizeHeaderNames ( req . Trailer ), qParams : escaped }, nil
40+
41+ return parseMessage ( msg , withTrailers )
5942}
6043
6144func reEncodeQPs (values url.Values ) url.Values {
@@ -82,23 +65,14 @@ func normalizeHeaderNames(header http.Header) http.Header {
8265}
8366
8467func parseResponse (res * http.Response , withTrailers bool ) (* parsedMessage , error ) {
85- err := validateMessageHeaders (res .Header )
86- if err != nil {
87- return nil , err
88- }
89- if withTrailers {
90- _ , err = duplicateBody (& res .Body ) // read the entire body to populate the trailers
91- if err != nil {
92- return nil , fmt .Errorf ("cannot duplicate request body: %w" , err )
93- }
94- err = validateMessageHeaders (res .Trailer )
95- if err != nil {
96- return nil , fmt .Errorf ("could not validate trailers: %w" , err )
97- }
68+ msg := & Message {
69+ statusCode : & res .StatusCode ,
70+ headers : res .Header ,
71+ trailers : res .Trailer ,
72+ body : & res .Body ,
9873 }
9974
100- return & parsedMessage {derived : generateResDerivedComponents (res ), url : nil ,
101- headers : normalizeHeaderNames (res .Header )}, nil
75+ return parseMessage (msg , withTrailers )
10276}
10377
10478func validateMessageHeaders (header http.Header ) error {
@@ -112,6 +86,9 @@ func validateMessageHeaders(header http.Header) error {
11286}
11387
11488func foldFields (fields []string ) string {
89+ if len (fields ) == 0 {
90+ return ""
91+ }
11592 ff := strings .TrimSpace (fields [0 ])
11693 for i := 1 ; i < len (fields ); i ++ {
11794 ff += ", " + strings .TrimSpace (fields [i ])
@@ -123,17 +100,14 @@ func derivedComponent(name, v string, components components) {
123100 components [name ] = v
124101}
125102
126- func generateReqDerivedComponents (req * http.Request ) components {
127- components := components {}
128- derivedComponent ("@method" , scMethod (req ), components )
129- theURL := req .URL
130- derivedComponent ("@target-uri" , scTargetURI (theURL ), components )
131- derivedComponent ("@path" , scPath (theURL ), components )
132- derivedComponent ("@authority" , scAuthority (req ), components )
133- derivedComponent ("@scheme" , scScheme (theURL ), components )
134- derivedComponent ("@request-target" , scRequestTarget (theURL ), components )
135- derivedComponent ("@query" , scQuery (theURL ), components )
136- return components
103+ func generateReqDerivedComponents (method string , u * url.URL , authority string , components components ) {
104+ derivedComponent ("@method" , method , components )
105+ derivedComponent ("@target-uri" , scTargetURI (u ), components )
106+ derivedComponent ("@path" , scPath (u ), components )
107+ derivedComponent ("@authority" , authority , components )
108+ derivedComponent ("@scheme" , scScheme (u ), components )
109+ derivedComponent ("@request-target" , scRequestTarget (u ), components )
110+ derivedComponent ("@query" , scQuery (u ), components )
137111}
138112
139113func scPath (theURL * url.URL ) string {
@@ -162,24 +136,81 @@ func scScheme(url *url.URL) string {
162136 return url .Scheme
163137}
164138
165- func scAuthority (req * http.Request ) string {
166- return req .Host
167- }
168-
169139func scTargetURI (url * url.URL ) string {
170140 return url .String ()
171141}
172142
173- func scMethod ( req * http. Request ) string {
174- return req . Method
143+ func scStatus ( statusCode int ) string {
144+ return strconv . Itoa ( statusCode )
175145}
176146
177- func generateResDerivedComponents (res * http.Response ) components {
178- components := components {}
179- derivedComponent ("@status" , scStatus (res ), components )
180- return components
181- }
147+ func parseMessage (msg * Message , withTrailers bool ) (* parsedMessage , error ) {
148+ if msg == nil {
149+ return nil , nil
150+ }
151+
152+ err := validateMessageHeaders (msg .headers )
153+ if err != nil {
154+ return nil , err
155+ }
156+
157+ if withTrailers {
158+ if msg .body != nil {
159+ _ , err = duplicateBody (msg .body )
160+ if err != nil {
161+ return nil , fmt .Errorf ("cannot duplicate message body: %w" , err )
162+ }
163+ }
164+ err = validateMessageHeaders (msg .trailers )
165+ if err != nil {
166+ return nil , fmt .Errorf ("could not validate trailers: %w" , err )
167+ }
168+ }
169+
170+ derived := components {}
171+ var u * url.URL
172+ var qParams url.Values
173+
174+ if msg .method != "" || msg .url != nil {
175+ if msg .method == "" || msg .url == nil {
176+ return nil , fmt .Errorf ("invalid state: method or url without the other" )
177+ }
178+
179+ u = msg .url
180+ if u == nil {
181+ u = & url.URL {Path : "/" }
182+ }
183+ if u .Host == "" && msg .authority != "" {
184+ u .Host = msg .authority
185+ }
186+ if u .Scheme == "" {
187+ if msg .scheme != "" {
188+ u .Scheme = msg .scheme
189+ } else {
190+ u .Scheme = "http"
191+ }
192+ }
193+
194+ if u .RawQuery != "" {
195+ values , err := url .ParseQuery (u .RawQuery )
196+ if err != nil {
197+ return nil , fmt .Errorf ("cannot parse query: %s" , u .RawQuery )
198+ }
199+ qParams = reEncodeQPs (values )
200+ }
201+
202+ generateReqDerivedComponents (msg .method , u , msg .authority , derived )
203+ } else if msg .statusCode != nil {
204+ derivedComponent ("@status" , scStatus (* msg .statusCode ), derived )
205+ } else {
206+ return nil , fmt .Errorf ("invalid state: method and url, or status required" )
207+ }
182208
183- func scStatus (res * http.Response ) string {
184- return strconv .Itoa (res .StatusCode )
209+ return & parsedMessage {
210+ derived : derived ,
211+ url : u ,
212+ headers : normalizeHeaderNames (msg .headers ),
213+ trailers : normalizeHeaderNames (msg .trailers ),
214+ qParams : qParams ,
215+ }, nil
185216}
0 commit comments