@@ -7,11 +7,11 @@ package http3
77import (
88 "context"
99 "net/http"
10- "net/url"
1110 "strconv"
1211 "sync"
1312
1413 "golang.org/x/net/http/httpguts"
14+ "golang.org/x/net/internal/httpcommon"
1515 "golang.org/x/net/quic"
1616)
1717
@@ -157,54 +157,81 @@ func (sc *serverConn) handlePushStream(*stream) error {
157157 }
158158}
159159
160- func (sc * serverConn ) parseRequest (st * stream ) (* http.Request , error ) {
161- req := & http.Request {
162- URL : & url.URL {},
163- Proto : "HTTP/3.0" ,
164- ProtoMajor : 3 ,
165- RemoteAddr : sc .qconn .RemoteAddr ().String (),
166- }
160+ type pseudoHeader struct {
161+ method string
162+ scheme string
163+ path string
164+ authority string
165+ }
166+
167+ func (sc * serverConn ) parseHeader (st * stream ) (http.Header , pseudoHeader , error ) {
167168 ftype , err := st .readFrameHeader ()
168169 if err != nil {
169- return nil , err
170+ return nil , pseudoHeader {}, err
170171 }
171172 if ftype != frameTypeHeaders {
172- return nil , err
173+ return nil , pseudoHeader {}, err
173174 }
174- req .Header = make (http.Header )
175+ header := make (http.Header )
176+ var pHeader pseudoHeader
175177 var dec qpackDecoder
176178 if err := dec .decode (st , func (_ indexType , name , value string ) error {
177179 switch name {
178180 case ":method" :
179- req . Method = value
181+ pHeader . method = value
180182 case ":scheme" :
181- req . URL . Scheme = value
183+ pHeader . scheme = value
182184 case ":path" :
183- req . URL . Path = value
185+ pHeader . path = value
184186 case ":authority" :
185- req . URL . Host = value
187+ pHeader . authority = value
186188 default :
187- req . Header .Add (name , value )
189+ header .Add (name , value )
188190 }
189191 return nil
190192 }); err != nil {
191- return nil , err
193+ return nil , pseudoHeader {}, err
192194 }
193195 if err := st .endFrame (); err != nil {
194- return nil , err
195- }
196- req .Body = & bodyReader {
197- st : st ,
198- remain : - 1 ,
196+ return nil , pseudoHeader {}, err
199197 }
200- return req , nil
198+ return header , pHeader , nil
201199}
202200
203201func (sc * serverConn ) handleRequestStream (st * stream ) error {
204- req , err := sc .parseRequest (st )
202+ header , pHeader , err := sc .parseHeader (st )
205203 if err != nil {
206204 return err
207205 }
206+
207+ reqInfo := httpcommon .NewServerRequest (httpcommon.ServerRequestParam {
208+ Method : pHeader .method ,
209+ Scheme : pHeader .scheme ,
210+ Authority : pHeader .authority ,
211+ Path : pHeader .path ,
212+ Header : header ,
213+ })
214+ if reqInfo .InvalidReason != "" {
215+ return & streamError {
216+ code : errH3MessageError ,
217+ message : reqInfo .InvalidReason ,
218+ }
219+ }
220+ req := & http.Request {
221+ Proto : "HTTP/3.0" ,
222+ Method : pHeader .method ,
223+ Host : pHeader .authority ,
224+ URL : reqInfo .URL ,
225+ RequestURI : reqInfo .RequestURI ,
226+ Trailer : reqInfo .Trailer ,
227+ ProtoMajor : 3 ,
228+ RemoteAddr : sc .qconn .RemoteAddr ().String (),
229+ Body : & bodyReader {
230+ st : st ,
231+ remain : - 1 ,
232+ },
233+ Header : header ,
234+ }
208235 defer req .Body .Close ()
209236
210237 rw := & responseWriter {
@@ -219,6 +246,12 @@ func (sc *serverConn) handleRequestStream(st *stream) error {
219246 },
220247 }
221248 defer rw .close ()
249+ if reqInfo .NeedsContinue {
250+ req .Body .(* bodyReader ).send100Continue = func () {
251+ rw .WriteHeader (http .StatusContinue )
252+ rw .Flush ()
253+ }
254+ }
222255
223256 // TODO: handle panic coming from the HTTP handler.
224257 sc .handler .ServeHTTP (rw , req )
@@ -238,11 +271,10 @@ func (sc *serverConn) abort(err error) {
238271}
239272
240273type responseWriter struct {
241- st * stream
242- bw * bodyWriter
243- mu sync.Mutex
244- headers http.Header
245- // TODO: support 1xx status
274+ st * stream
275+ bw * bodyWriter
276+ mu sync.Mutex
277+ headers http.Header
246278 wroteHeader bool // Non-1xx header has been (logically) written.
247279 isHeadResp bool // response is for a HEAD request.
248280}
@@ -278,7 +310,9 @@ func (rw *responseWriter) writeHeaderLockedOnce(statusCode int) {
278310 rw .st .writeVarint (int64 (frameTypeHeaders ))
279311 rw .st .writeVarint (int64 (len (encHeaders )))
280312 rw .st .Write (encHeaders )
281- rw .wroteHeader = true
313+ if statusCode >= http .StatusOK {
314+ rw .wroteHeader = true
315+ }
282316}
283317
284318func (rw * responseWriter ) WriteHeader (statusCode int ) {
0 commit comments