source: code/trunk/vendor/github.com/valyala/fasthttp/http.go@ 145

Last change on this file since 145 was 145, checked in by Izuru Yakumo, 22 months ago

Updated the Makefile and vendored depedencies

Signed-off-by: Izuru Yakumo <yakumo.izuru@…>

File size: 56.6 KB
Line 
1package fasthttp
2
3import (
4 "bufio"
5 "bytes"
6 "compress/gzip"
7 "encoding/base64"
8 "errors"
9 "fmt"
10 "io"
11 "mime/multipart"
12 "net"
13 "os"
14 "sync"
15 "time"
16
17 "github.com/valyala/bytebufferpool"
18)
19
20var (
21 requestBodyPoolSizeLimit = -1
22 responseBodyPoolSizeLimit = -1
23)
24
25// SetBodySizePoolLimit set the max body size for bodies to be returned to the pool.
26// If the body size is larger it will be released instead of put back into the pool for reuse.
27func SetBodySizePoolLimit(reqBodyLimit, respBodyLimit int) {
28 requestBodyPoolSizeLimit = reqBodyLimit
29 responseBodyPoolSizeLimit = respBodyLimit
30}
31
32// Request represents HTTP request.
33//
34// It is forbidden copying Request instances. Create new instances
35// and use CopyTo instead.
36//
37// Request instance MUST NOT be used from concurrently running goroutines.
38type Request struct {
39 noCopy noCopy //nolint:unused,structcheck
40
41 // Request header
42 //
43 // Copying Header by value is forbidden. Use pointer to Header instead.
44 Header RequestHeader
45
46 uri URI
47 postArgs Args
48
49 bodyStream io.Reader
50 w requestBodyWriter
51 body *bytebufferpool.ByteBuffer
52 bodyRaw []byte
53
54 multipartForm *multipart.Form
55 multipartFormBoundary string
56 secureErrorLogMessage bool
57
58 // Group bool members in order to reduce Request object size.
59 parsedURI bool
60 parsedPostArgs bool
61
62 keepBodyBuffer bool
63
64 // Used by Server to indicate the request was received on a HTTPS endpoint.
65 // Client/HostClient shouldn't use this field but should depend on the uri.scheme instead.
66 isTLS bool
67
68 // Request timeout. Usually set by DoDeadline or DoTimeout
69 // if <= 0, means not set
70 timeout time.Duration
71
72 // Use Host header (request.Header.SetHost) instead of the host from SetRequestURI, SetHost, or URI().SetHost
73 UseHostHeader bool
74}
75
76// Response represents HTTP response.
77//
78// It is forbidden copying Response instances. Create new instances
79// and use CopyTo instead.
80//
81// Response instance MUST NOT be used from concurrently running goroutines.
82type Response struct {
83 noCopy noCopy //nolint:unused,structcheck
84
85 // Response header
86 //
87 // Copying Header by value is forbidden. Use pointer to Header instead.
88 Header ResponseHeader
89
90 // Flush headers as soon as possible without waiting for first body bytes.
91 // Relevant for bodyStream only.
92 ImmediateHeaderFlush bool
93
94 bodyStream io.Reader
95 w responseBodyWriter
96 body *bytebufferpool.ByteBuffer
97 bodyRaw []byte
98
99 // Response.Read() skips reading body if set to true.
100 // Use it for reading HEAD responses.
101 //
102 // Response.Write() skips writing body if set to true.
103 // Use it for writing HEAD responses.
104 SkipBody bool
105
106 keepBodyBuffer bool
107 secureErrorLogMessage bool
108
109 // Remote TCPAddr from concurrently net.Conn
110 raddr net.Addr
111 // Local TCPAddr from concurrently net.Conn
112 laddr net.Addr
113}
114
115// SetHost sets host for the request.
116func (req *Request) SetHost(host string) {
117 req.URI().SetHost(host)
118}
119
120// SetHostBytes sets host for the request.
121func (req *Request) SetHostBytes(host []byte) {
122 req.URI().SetHostBytes(host)
123}
124
125// Host returns the host for the given request.
126func (req *Request) Host() []byte {
127 return req.URI().Host()
128}
129
130// SetRequestURI sets RequestURI.
131func (req *Request) SetRequestURI(requestURI string) {
132 req.Header.SetRequestURI(requestURI)
133 req.parsedURI = false
134}
135
136// SetRequestURIBytes sets RequestURI.
137func (req *Request) SetRequestURIBytes(requestURI []byte) {
138 req.Header.SetRequestURIBytes(requestURI)
139 req.parsedURI = false
140}
141
142// RequestURI returns request's URI.
143func (req *Request) RequestURI() []byte {
144 if req.parsedURI {
145 requestURI := req.uri.RequestURI()
146 req.SetRequestURIBytes(requestURI)
147 }
148 return req.Header.RequestURI()
149}
150
151// StatusCode returns response status code.
152func (resp *Response) StatusCode() int {
153 return resp.Header.StatusCode()
154}
155
156// SetStatusCode sets response status code.
157func (resp *Response) SetStatusCode(statusCode int) {
158 resp.Header.SetStatusCode(statusCode)
159}
160
161// ConnectionClose returns true if 'Connection: close' header is set.
162func (resp *Response) ConnectionClose() bool {
163 return resp.Header.ConnectionClose()
164}
165
166// SetConnectionClose sets 'Connection: close' header.
167func (resp *Response) SetConnectionClose() {
168 resp.Header.SetConnectionClose()
169}
170
171// ConnectionClose returns true if 'Connection: close' header is set.
172func (req *Request) ConnectionClose() bool {
173 return req.Header.ConnectionClose()
174}
175
176// SetConnectionClose sets 'Connection: close' header.
177func (req *Request) SetConnectionClose() {
178 req.Header.SetConnectionClose()
179}
180
181// SendFile registers file on the given path to be used as response body
182// when Write is called.
183//
184// Note that SendFile doesn't set Content-Type, so set it yourself
185// with Header.SetContentType.
186func (resp *Response) SendFile(path string) error {
187 f, err := os.Open(path)
188 if err != nil {
189 return err
190 }
191 fileInfo, err := f.Stat()
192 if err != nil {
193 f.Close()
194 return err
195 }
196 size64 := fileInfo.Size()
197 size := int(size64)
198 if int64(size) != size64 {
199 size = -1
200 }
201
202 resp.Header.SetLastModified(fileInfo.ModTime())
203 resp.SetBodyStream(f, size)
204 return nil
205}
206
207// SetBodyStream sets request body stream and, optionally body size.
208//
209// If bodySize is >= 0, then the bodyStream must provide exactly bodySize bytes
210// before returning io.EOF.
211//
212// If bodySize < 0, then bodyStream is read until io.EOF.
213//
214// bodyStream.Close() is called after finishing reading all body data
215// if it implements io.Closer.
216//
217// Note that GET and HEAD requests cannot have body.
218//
219// See also SetBodyStreamWriter.
220func (req *Request) SetBodyStream(bodyStream io.Reader, bodySize int) {
221 req.ResetBody()
222 req.bodyStream = bodyStream
223 req.Header.SetContentLength(bodySize)
224}
225
226// SetBodyStream sets response body stream and, optionally body size.
227//
228// If bodySize is >= 0, then the bodyStream must provide exactly bodySize bytes
229// before returning io.EOF.
230//
231// If bodySize < 0, then bodyStream is read until io.EOF.
232//
233// bodyStream.Close() is called after finishing reading all body data
234// if it implements io.Closer.
235//
236// See also SetBodyStreamWriter.
237func (resp *Response) SetBodyStream(bodyStream io.Reader, bodySize int) {
238 resp.ResetBody()
239 resp.bodyStream = bodyStream
240 resp.Header.SetContentLength(bodySize)
241}
242
243// IsBodyStream returns true if body is set via SetBodyStream*
244func (req *Request) IsBodyStream() bool {
245 return req.bodyStream != nil
246}
247
248// IsBodyStream returns true if body is set via SetBodyStream*
249func (resp *Response) IsBodyStream() bool {
250 return resp.bodyStream != nil
251}
252
253// SetBodyStreamWriter registers the given sw for populating request body.
254//
255// This function may be used in the following cases:
256//
257// * if request body is too big (more than 10MB).
258// * if request body is streamed from slow external sources.
259// * if request body must be streamed to the server in chunks
260// (aka `http client push` or `chunked transfer-encoding`).
261//
262// Note that GET and HEAD requests cannot have body.
263//
264/// See also SetBodyStream.
265func (req *Request) SetBodyStreamWriter(sw StreamWriter) {
266 sr := NewStreamReader(sw)
267 req.SetBodyStream(sr, -1)
268}
269
270// SetBodyStreamWriter registers the given sw for populating response body.
271//
272// This function may be used in the following cases:
273//
274// * if response body is too big (more than 10MB).
275// * if response body is streamed from slow external sources.
276// * if response body must be streamed to the client in chunks
277// (aka `http server push` or `chunked transfer-encoding`).
278//
279// See also SetBodyStream.
280func (resp *Response) SetBodyStreamWriter(sw StreamWriter) {
281 sr := NewStreamReader(sw)
282 resp.SetBodyStream(sr, -1)
283}
284
285// BodyWriter returns writer for populating response body.
286//
287// If used inside RequestHandler, the returned writer must not be used
288// after returning from RequestHandler. Use RequestCtx.Write
289// or SetBodyStreamWriter in this case.
290func (resp *Response) BodyWriter() io.Writer {
291 resp.w.r = resp
292 return &resp.w
293}
294
295// BodyWriter returns writer for populating request body.
296func (req *Request) BodyWriter() io.Writer {
297 req.w.r = req
298 return &req.w
299}
300
301type responseBodyWriter struct {
302 r *Response
303}
304
305func (w *responseBodyWriter) Write(p []byte) (int, error) {
306 w.r.AppendBody(p)
307 return len(p), nil
308}
309
310type requestBodyWriter struct {
311 r *Request
312}
313
314func (w *requestBodyWriter) Write(p []byte) (int, error) {
315 w.r.AppendBody(p)
316 return len(p), nil
317}
318
319func (resp *Response) parseNetConn(conn net.Conn) {
320 resp.raddr = conn.RemoteAddr()
321 resp.laddr = conn.LocalAddr()
322}
323
324// RemoteAddr returns the remote network address. The Addr returned is shared
325// by all invocations of RemoteAddr, so do not modify it.
326func (resp *Response) RemoteAddr() net.Addr {
327 return resp.raddr
328}
329
330// LocalAddr returns the local network address. The Addr returned is shared
331// by all invocations of LocalAddr, so do not modify it.
332func (resp *Response) LocalAddr() net.Addr {
333 return resp.laddr
334}
335
336// Body returns response body.
337//
338// The returned value is valid until the response is released,
339// either though ReleaseResponse or your request handler returning.
340// Do not store references to returned value. Make copies instead.
341func (resp *Response) Body() []byte {
342 if resp.bodyStream != nil {
343 bodyBuf := resp.bodyBuffer()
344 bodyBuf.Reset()
345 _, err := copyZeroAlloc(bodyBuf, resp.bodyStream)
346 resp.closeBodyStream() //nolint:errcheck
347 if err != nil {
348 bodyBuf.SetString(err.Error())
349 }
350 }
351 return resp.bodyBytes()
352}
353
354func (resp *Response) bodyBytes() []byte {
355 if resp.bodyRaw != nil {
356 return resp.bodyRaw
357 }
358 if resp.body == nil {
359 return nil
360 }
361 return resp.body.B
362}
363
364func (req *Request) bodyBytes() []byte {
365 if req.bodyRaw != nil {
366 return req.bodyRaw
367 }
368 if req.bodyStream != nil {
369 bodyBuf := req.bodyBuffer()
370 bodyBuf.Reset()
371 _, err := copyZeroAlloc(bodyBuf, req.bodyStream)
372 req.closeBodyStream() //nolint:errcheck
373 if err != nil {
374 bodyBuf.SetString(err.Error())
375 }
376 }
377 if req.body == nil {
378 return nil
379 }
380 return req.body.B
381}
382
383func (resp *Response) bodyBuffer() *bytebufferpool.ByteBuffer {
384 if resp.body == nil {
385 resp.body = responseBodyPool.Get()
386 }
387 resp.bodyRaw = nil
388 return resp.body
389}
390
391func (req *Request) bodyBuffer() *bytebufferpool.ByteBuffer {
392 if req.body == nil {
393 req.body = requestBodyPool.Get()
394 }
395 req.bodyRaw = nil
396 return req.body
397}
398
399var (
400 responseBodyPool bytebufferpool.Pool
401 requestBodyPool bytebufferpool.Pool
402)
403
404// BodyGunzip returns un-gzipped body data.
405//
406// This method may be used if the request header contains
407// 'Content-Encoding: gzip' for reading un-gzipped body.
408// Use Body for reading gzipped request body.
409func (req *Request) BodyGunzip() ([]byte, error) {
410 return gunzipData(req.Body())
411}
412
413// BodyGunzip returns un-gzipped body data.
414//
415// This method may be used if the response header contains
416// 'Content-Encoding: gzip' for reading un-gzipped body.
417// Use Body for reading gzipped response body.
418func (resp *Response) BodyGunzip() ([]byte, error) {
419 return gunzipData(resp.Body())
420}
421
422func gunzipData(p []byte) ([]byte, error) {
423 var bb bytebufferpool.ByteBuffer
424 _, err := WriteGunzip(&bb, p)
425 if err != nil {
426 return nil, err
427 }
428 return bb.B, nil
429}
430
431// BodyUnbrotli returns un-brotlied body data.
432//
433// This method may be used if the request header contains
434// 'Content-Encoding: br' for reading un-brotlied body.
435// Use Body for reading brotlied request body.
436func (req *Request) BodyUnbrotli() ([]byte, error) {
437 return unBrotliData(req.Body())
438}
439
440// BodyUnbrotli returns un-brotlied body data.
441//
442// This method may be used if the response header contains
443// 'Content-Encoding: br' for reading un-brotlied body.
444// Use Body for reading brotlied response body.
445func (resp *Response) BodyUnbrotli() ([]byte, error) {
446 return unBrotliData(resp.Body())
447}
448
449func unBrotliData(p []byte) ([]byte, error) {
450 var bb bytebufferpool.ByteBuffer
451 _, err := WriteUnbrotli(&bb, p)
452 if err != nil {
453 return nil, err
454 }
455 return bb.B, nil
456}
457
458// BodyInflate returns inflated body data.
459//
460// This method may be used if the response header contains
461// 'Content-Encoding: deflate' for reading inflated request body.
462// Use Body for reading deflated request body.
463func (req *Request) BodyInflate() ([]byte, error) {
464 return inflateData(req.Body())
465}
466
467// BodyInflate returns inflated body data.
468//
469// This method may be used if the response header contains
470// 'Content-Encoding: deflate' for reading inflated response body.
471// Use Body for reading deflated response body.
472func (resp *Response) BodyInflate() ([]byte, error) {
473 return inflateData(resp.Body())
474}
475
476func (ctx *RequestCtx) RequestBodyStream() io.Reader {
477 return ctx.Request.bodyStream
478}
479
480func inflateData(p []byte) ([]byte, error) {
481 var bb bytebufferpool.ByteBuffer
482 _, err := WriteInflate(&bb, p)
483 if err != nil {
484 return nil, err
485 }
486 return bb.B, nil
487}
488
489// BodyWriteTo writes request body to w.
490func (req *Request) BodyWriteTo(w io.Writer) error {
491 if req.bodyStream != nil {
492 _, err := copyZeroAlloc(w, req.bodyStream)
493 req.closeBodyStream() //nolint:errcheck
494 return err
495 }
496 if req.onlyMultipartForm() {
497 return WriteMultipartForm(w, req.multipartForm, req.multipartFormBoundary)
498 }
499 _, err := w.Write(req.bodyBytes())
500 return err
501}
502
503// BodyWriteTo writes response body to w.
504func (resp *Response) BodyWriteTo(w io.Writer) error {
505 if resp.bodyStream != nil {
506 _, err := copyZeroAlloc(w, resp.bodyStream)
507 resp.closeBodyStream() //nolint:errcheck
508 return err
509 }
510 _, err := w.Write(resp.bodyBytes())
511 return err
512}
513
514// AppendBody appends p to response body.
515//
516// It is safe re-using p after the function returns.
517func (resp *Response) AppendBody(p []byte) {
518 resp.closeBodyStream() //nolint:errcheck
519 resp.bodyBuffer().Write(p) //nolint:errcheck
520}
521
522// AppendBodyString appends s to response body.
523func (resp *Response) AppendBodyString(s string) {
524 resp.closeBodyStream() //nolint:errcheck
525 resp.bodyBuffer().WriteString(s) //nolint:errcheck
526}
527
528// SetBody sets response body.
529//
530// It is safe re-using body argument after the function returns.
531func (resp *Response) SetBody(body []byte) {
532 resp.closeBodyStream() //nolint:errcheck
533 bodyBuf := resp.bodyBuffer()
534 bodyBuf.Reset()
535 bodyBuf.Write(body) //nolint:errcheck
536}
537
538// SetBodyString sets response body.
539func (resp *Response) SetBodyString(body string) {
540 resp.closeBodyStream() //nolint:errcheck
541 bodyBuf := resp.bodyBuffer()
542 bodyBuf.Reset()
543 bodyBuf.WriteString(body) //nolint:errcheck
544}
545
546// ResetBody resets response body.
547func (resp *Response) ResetBody() {
548 resp.bodyRaw = nil
549 resp.closeBodyStream() //nolint:errcheck
550 if resp.body != nil {
551 if resp.keepBodyBuffer {
552 resp.body.Reset()
553 } else {
554 responseBodyPool.Put(resp.body)
555 resp.body = nil
556 }
557 }
558}
559
560// SetBodyRaw sets response body, but without copying it.
561//
562// From this point onward the body argument must not be changed.
563func (resp *Response) SetBodyRaw(body []byte) {
564 resp.ResetBody()
565 resp.bodyRaw = body
566}
567
568// SetBodyRaw sets response body, but without copying it.
569//
570// From this point onward the body argument must not be changed.
571func (req *Request) SetBodyRaw(body []byte) {
572 req.ResetBody()
573 req.bodyRaw = body
574}
575
576// ReleaseBody retires the response body if it is greater than "size" bytes.
577//
578// This permits GC to reclaim the large buffer. If used, must be before
579// ReleaseResponse.
580//
581// Use this method only if you really understand how it works.
582// The majority of workloads don't need this method.
583func (resp *Response) ReleaseBody(size int) {
584 resp.bodyRaw = nil
585 if cap(resp.body.B) > size {
586 resp.closeBodyStream() //nolint:errcheck
587 resp.body = nil
588 }
589}
590
591// ReleaseBody retires the request body if it is greater than "size" bytes.
592//
593// This permits GC to reclaim the large buffer. If used, must be before
594// ReleaseRequest.
595//
596// Use this method only if you really understand how it works.
597// The majority of workloads don't need this method.
598func (req *Request) ReleaseBody(size int) {
599 req.bodyRaw = nil
600 if cap(req.body.B) > size {
601 req.closeBodyStream() //nolint:errcheck
602 req.body = nil
603 }
604}
605
606// SwapBody swaps response body with the given body and returns
607// the previous response body.
608//
609// It is forbidden to use the body passed to SwapBody after
610// the function returns.
611func (resp *Response) SwapBody(body []byte) []byte {
612 bb := resp.bodyBuffer()
613
614 if resp.bodyStream != nil {
615 bb.Reset()
616 _, err := copyZeroAlloc(bb, resp.bodyStream)
617 resp.closeBodyStream() //nolint:errcheck
618 if err != nil {
619 bb.Reset()
620 bb.SetString(err.Error())
621 }
622 }
623
624 resp.bodyRaw = nil
625
626 oldBody := bb.B
627 bb.B = body
628 return oldBody
629}
630
631// SwapBody swaps request body with the given body and returns
632// the previous request body.
633//
634// It is forbidden to use the body passed to SwapBody after
635// the function returns.
636func (req *Request) SwapBody(body []byte) []byte {
637 bb := req.bodyBuffer()
638
639 if req.bodyStream != nil {
640 bb.Reset()
641 _, err := copyZeroAlloc(bb, req.bodyStream)
642 req.closeBodyStream() //nolint:errcheck
643 if err != nil {
644 bb.Reset()
645 bb.SetString(err.Error())
646 }
647 }
648
649 req.bodyRaw = nil
650
651 oldBody := bb.B
652 bb.B = body
653 return oldBody
654}
655
656// Body returns request body.
657//
658// The returned value is valid until the request is released,
659// either though ReleaseRequest or your request handler returning.
660// Do not store references to returned value. Make copies instead.
661func (req *Request) Body() []byte {
662 if req.bodyRaw != nil {
663 return req.bodyRaw
664 } else if req.onlyMultipartForm() {
665 body, err := marshalMultipartForm(req.multipartForm, req.multipartFormBoundary)
666 if err != nil {
667 return []byte(err.Error())
668 }
669 return body
670 }
671 return req.bodyBytes()
672}
673
674// AppendBody appends p to request body.
675//
676// It is safe re-using p after the function returns.
677func (req *Request) AppendBody(p []byte) {
678 req.RemoveMultipartFormFiles()
679 req.closeBodyStream() //nolint:errcheck
680 req.bodyBuffer().Write(p) //nolint:errcheck
681}
682
683// AppendBodyString appends s to request body.
684func (req *Request) AppendBodyString(s string) {
685 req.RemoveMultipartFormFiles()
686 req.closeBodyStream() //nolint:errcheck
687 req.bodyBuffer().WriteString(s) //nolint:errcheck
688}
689
690// SetBody sets request body.
691//
692// It is safe re-using body argument after the function returns.
693func (req *Request) SetBody(body []byte) {
694 req.RemoveMultipartFormFiles()
695 req.closeBodyStream() //nolint:errcheck
696 req.bodyBuffer().Set(body)
697}
698
699// SetBodyString sets request body.
700func (req *Request) SetBodyString(body string) {
701 req.RemoveMultipartFormFiles()
702 req.closeBodyStream() //nolint:errcheck
703 req.bodyBuffer().SetString(body)
704}
705
706// ResetBody resets request body.
707func (req *Request) ResetBody() {
708 req.bodyRaw = nil
709 req.RemoveMultipartFormFiles()
710 req.closeBodyStream() //nolint:errcheck
711 if req.body != nil {
712 if req.keepBodyBuffer {
713 req.body.Reset()
714 } else {
715 requestBodyPool.Put(req.body)
716 req.body = nil
717 }
718 }
719}
720
721// CopyTo copies req contents to dst except of body stream.
722func (req *Request) CopyTo(dst *Request) {
723 req.copyToSkipBody(dst)
724 if req.bodyRaw != nil {
725 dst.bodyRaw = req.bodyRaw
726 if dst.body != nil {
727 dst.body.Reset()
728 }
729 } else if req.body != nil {
730 dst.bodyBuffer().Set(req.body.B)
731 } else if dst.body != nil {
732 dst.body.Reset()
733 }
734}
735
736func (req *Request) copyToSkipBody(dst *Request) {
737 dst.Reset()
738 req.Header.CopyTo(&dst.Header)
739
740 req.uri.CopyTo(&dst.uri)
741 dst.parsedURI = req.parsedURI
742
743 req.postArgs.CopyTo(&dst.postArgs)
744 dst.parsedPostArgs = req.parsedPostArgs
745 dst.isTLS = req.isTLS
746
747 dst.UseHostHeader = req.UseHostHeader
748
749 // do not copy multipartForm - it will be automatically
750 // re-created on the first call to MultipartForm.
751}
752
753// CopyTo copies resp contents to dst except of body stream.
754func (resp *Response) CopyTo(dst *Response) {
755 resp.copyToSkipBody(dst)
756 if resp.bodyRaw != nil {
757 dst.bodyRaw = resp.bodyRaw
758 if dst.body != nil {
759 dst.body.Reset()
760 }
761 } else if resp.body != nil {
762 dst.bodyBuffer().Set(resp.body.B)
763 } else if dst.body != nil {
764 dst.body.Reset()
765 }
766}
767
768func (resp *Response) copyToSkipBody(dst *Response) {
769 dst.Reset()
770 resp.Header.CopyTo(&dst.Header)
771 dst.SkipBody = resp.SkipBody
772 dst.raddr = resp.raddr
773 dst.laddr = resp.laddr
774}
775
776func swapRequestBody(a, b *Request) {
777 a.body, b.body = b.body, a.body
778 a.bodyRaw, b.bodyRaw = b.bodyRaw, a.bodyRaw
779 a.bodyStream, b.bodyStream = b.bodyStream, a.bodyStream
780}
781
782func swapResponseBody(a, b *Response) {
783 a.body, b.body = b.body, a.body
784 a.bodyRaw, b.bodyRaw = b.bodyRaw, a.bodyRaw
785 a.bodyStream, b.bodyStream = b.bodyStream, a.bodyStream
786}
787
788// URI returns request URI
789func (req *Request) URI() *URI {
790 req.parseURI() //nolint:errcheck
791 return &req.uri
792}
793
794// SetURI initializes request URI
795// Use this method if a single URI may be reused across multiple requests.
796// Otherwise, you can just use SetRequestURI() and it will be parsed as new URI.
797// The URI is copied and can be safely modified later.
798func (req *Request) SetURI(newUri *URI) {
799 if newUri != nil {
800 newUri.CopyTo(&req.uri)
801 req.parsedURI = true
802 return
803 }
804 req.uri.Reset()
805 req.parsedURI = false
806}
807
808func (req *Request) parseURI() error {
809 if req.parsedURI {
810 return nil
811 }
812 req.parsedURI = true
813
814 return req.uri.parse(req.Header.Host(), req.Header.RequestURI(), req.isTLS)
815}
816
817// PostArgs returns POST arguments.
818func (req *Request) PostArgs() *Args {
819 req.parsePostArgs()
820 return &req.postArgs
821}
822
823func (req *Request) parsePostArgs() {
824 if req.parsedPostArgs {
825 return
826 }
827 req.parsedPostArgs = true
828
829 if !bytes.HasPrefix(req.Header.ContentType(), strPostArgsContentType) {
830 return
831 }
832 req.postArgs.ParseBytes(req.bodyBytes())
833}
834
835// ErrNoMultipartForm means that the request's Content-Type
836// isn't 'multipart/form-data'.
837var ErrNoMultipartForm = errors.New("request has no multipart/form-data Content-Type")
838
839// MultipartForm returns requests's multipart form.
840//
841// Returns ErrNoMultipartForm if request's Content-Type
842// isn't 'multipart/form-data'.
843//
844// RemoveMultipartFormFiles must be called after returned multipart form
845// is processed.
846func (req *Request) MultipartForm() (*multipart.Form, error) {
847 if req.multipartForm != nil {
848 return req.multipartForm, nil
849 }
850
851 req.multipartFormBoundary = string(req.Header.MultipartFormBoundary())
852 if len(req.multipartFormBoundary) == 0 {
853 return nil, ErrNoMultipartForm
854 }
855
856 var err error
857 ce := req.Header.peek(strContentEncoding)
858
859 if req.bodyStream != nil {
860 bodyStream := req.bodyStream
861 if bytes.Equal(ce, strGzip) {
862 // Do not care about memory usage here.
863 if bodyStream, err = gzip.NewReader(bodyStream); err != nil {
864 return nil, fmt.Errorf("cannot gunzip request body: %w", err)
865 }
866 } else if len(ce) > 0 {
867 return nil, fmt.Errorf("unsupported Content-Encoding: %q", ce)
868 }
869
870 mr := multipart.NewReader(bodyStream, req.multipartFormBoundary)
871 req.multipartForm, err = mr.ReadForm(8 * 1024)
872 if err != nil {
873 return nil, fmt.Errorf("cannot read multipart/form-data body: %w", err)
874 }
875 } else {
876 body := req.bodyBytes()
877 if bytes.Equal(ce, strGzip) {
878 // Do not care about memory usage here.
879 if body, err = AppendGunzipBytes(nil, body); err != nil {
880 return nil, fmt.Errorf("cannot gunzip request body: %w", err)
881 }
882 } else if len(ce) > 0 {
883 return nil, fmt.Errorf("unsupported Content-Encoding: %q", ce)
884 }
885
886 req.multipartForm, err = readMultipartForm(bytes.NewReader(body), req.multipartFormBoundary, len(body), len(body))
887 if err != nil {
888 return nil, err
889 }
890 }
891
892 return req.multipartForm, nil
893}
894
895func marshalMultipartForm(f *multipart.Form, boundary string) ([]byte, error) {
896 var buf bytebufferpool.ByteBuffer
897 if err := WriteMultipartForm(&buf, f, boundary); err != nil {
898 return nil, err
899 }
900 return buf.B, nil
901}
902
903// WriteMultipartForm writes the given multipart form f with the given
904// boundary to w.
905func WriteMultipartForm(w io.Writer, f *multipart.Form, boundary string) error {
906 // Do not care about memory allocations here, since multipart
907 // form processing is slow.
908 if len(boundary) == 0 {
909 panic("BUG: form boundary cannot be empty")
910 }
911
912 mw := multipart.NewWriter(w)
913 if err := mw.SetBoundary(boundary); err != nil {
914 return fmt.Errorf("cannot use form boundary %q: %w", boundary, err)
915 }
916
917 // marshal values
918 for k, vv := range f.Value {
919 for _, v := range vv {
920 if err := mw.WriteField(k, v); err != nil {
921 return fmt.Errorf("cannot write form field %q value %q: %w", k, v, err)
922 }
923 }
924 }
925
926 // marshal files
927 for k, fvv := range f.File {
928 for _, fv := range fvv {
929 vw, err := mw.CreatePart(fv.Header)
930 if err != nil {
931 return fmt.Errorf("cannot create form file %q (%q): %w", k, fv.Filename, err)
932 }
933 fh, err := fv.Open()
934 if err != nil {
935 return fmt.Errorf("cannot open form file %q (%q): %s", k, fv.Filename, err)
936 }
937 if _, err = copyZeroAlloc(vw, fh); err != nil {
938 return fmt.Errorf("error when copying form file %q (%q): %w", k, fv.Filename, err)
939 }
940 if err = fh.Close(); err != nil {
941 return fmt.Errorf("cannot close form file %q (%q): %w", k, fv.Filename, err)
942 }
943 }
944 }
945
946 if err := mw.Close(); err != nil {
947 return fmt.Errorf("error when closing multipart form writer: %w", err)
948 }
949
950 return nil
951}
952
953func readMultipartForm(r io.Reader, boundary string, size, maxInMemoryFileSize int) (*multipart.Form, error) {
954 // Do not care about memory allocations here, since they are tiny
955 // compared to multipart data (aka multi-MB files) usually sent
956 // in multipart/form-data requests.
957
958 if size <= 0 {
959 return nil, fmt.Errorf("form size must be greater than 0. Given %d", size)
960 }
961 lr := io.LimitReader(r, int64(size))
962 mr := multipart.NewReader(lr, boundary)
963 f, err := mr.ReadForm(int64(maxInMemoryFileSize))
964 if err != nil {
965 return nil, fmt.Errorf("cannot read multipart/form-data body: %w", err)
966 }
967 return f, nil
968}
969
970// Reset clears request contents.
971func (req *Request) Reset() {
972 if requestBodyPoolSizeLimit >= 0 && req.body != nil {
973 req.ReleaseBody(requestBodyPoolSizeLimit)
974 }
975 req.Header.Reset()
976 req.resetSkipHeader()
977 req.timeout = 0
978 req.UseHostHeader = false
979}
980
981func (req *Request) resetSkipHeader() {
982 req.ResetBody()
983 req.uri.Reset()
984 req.parsedURI = false
985 req.postArgs.Reset()
986 req.parsedPostArgs = false
987 req.isTLS = false
988}
989
990// RemoveMultipartFormFiles removes multipart/form-data temporary files
991// associated with the request.
992func (req *Request) RemoveMultipartFormFiles() {
993 if req.multipartForm != nil {
994 // Do not check for error, since these files may be deleted or moved
995 // to new places by user code.
996 req.multipartForm.RemoveAll() //nolint:errcheck
997 req.multipartForm = nil
998 }
999 req.multipartFormBoundary = ""
1000}
1001
1002// Reset clears response contents.
1003func (resp *Response) Reset() {
1004 if responseBodyPoolSizeLimit >= 0 && resp.body != nil {
1005 resp.ReleaseBody(responseBodyPoolSizeLimit)
1006 }
1007 resp.Header.Reset()
1008 resp.resetSkipHeader()
1009 resp.SkipBody = false
1010 resp.raddr = nil
1011 resp.laddr = nil
1012 resp.ImmediateHeaderFlush = false
1013}
1014
1015func (resp *Response) resetSkipHeader() {
1016 resp.ResetBody()
1017}
1018
1019// Read reads request (including body) from the given r.
1020//
1021// RemoveMultipartFormFiles or Reset must be called after
1022// reading multipart/form-data request in order to delete temporarily
1023// uploaded files.
1024//
1025// If MayContinue returns true, the caller must:
1026//
1027// - Either send StatusExpectationFailed response if request headers don't
1028// satisfy the caller.
1029// - Or send StatusContinue response before reading request body
1030// with ContinueReadBody.
1031// - Or close the connection.
1032//
1033// io.EOF is returned if r is closed before reading the first header byte.
1034func (req *Request) Read(r *bufio.Reader) error {
1035 return req.ReadLimitBody(r, 0)
1036}
1037
1038const defaultMaxInMemoryFileSize = 16 * 1024 * 1024
1039
1040// ErrGetOnly is returned when server expects only GET requests,
1041// but some other type of request came (Server.GetOnly option is true).
1042var ErrGetOnly = errors.New("non-GET request received")
1043
1044// ReadLimitBody reads request from the given r, limiting the body size.
1045//
1046// If maxBodySize > 0 and the body size exceeds maxBodySize,
1047// then ErrBodyTooLarge is returned.
1048//
1049// RemoveMultipartFormFiles or Reset must be called after
1050// reading multipart/form-data request in order to delete temporarily
1051// uploaded files.
1052//
1053// If MayContinue returns true, the caller must:
1054//
1055// - Either send StatusExpectationFailed response if request headers don't
1056// satisfy the caller.
1057// - Or send StatusContinue response before reading request body
1058// with ContinueReadBody.
1059// - Or close the connection.
1060//
1061// io.EOF is returned if r is closed before reading the first header byte.
1062func (req *Request) ReadLimitBody(r *bufio.Reader, maxBodySize int) error {
1063 req.resetSkipHeader()
1064 if err := req.Header.Read(r); err != nil {
1065 return err
1066 }
1067
1068 return req.readLimitBody(r, maxBodySize, false, true)
1069}
1070
1071func (req *Request) readLimitBody(r *bufio.Reader, maxBodySize int, getOnly bool, preParseMultipartForm bool) error {
1072 // Do not reset the request here - the caller must reset it before
1073 // calling this method.
1074
1075 if getOnly && !req.Header.IsGet() {
1076 return ErrGetOnly
1077 }
1078
1079 if req.MayContinue() {
1080 // 'Expect: 100-continue' header found. Let the caller deciding
1081 // whether to read request body or
1082 // to return StatusExpectationFailed.
1083 return nil
1084 }
1085
1086 return req.ContinueReadBody(r, maxBodySize, preParseMultipartForm)
1087}
1088
1089func (req *Request) readBodyStream(r *bufio.Reader, maxBodySize int, getOnly bool, preParseMultipartForm bool) error {
1090 // Do not reset the request here - the caller must reset it before
1091 // calling this method.
1092
1093 if getOnly && !req.Header.IsGet() {
1094 return ErrGetOnly
1095 }
1096
1097 if req.MayContinue() {
1098 // 'Expect: 100-continue' header found. Let the caller deciding
1099 // whether to read request body or
1100 // to return StatusExpectationFailed.
1101 return nil
1102 }
1103
1104 return req.ContinueReadBodyStream(r, maxBodySize, preParseMultipartForm)
1105}
1106
1107// MayContinue returns true if the request contains
1108// 'Expect: 100-continue' header.
1109//
1110// The caller must do one of the following actions if MayContinue returns true:
1111//
1112// - Either send StatusExpectationFailed response if request headers don't
1113// satisfy the caller.
1114// - Or send StatusContinue response before reading request body
1115// with ContinueReadBody.
1116// - Or close the connection.
1117func (req *Request) MayContinue() bool {
1118 return bytes.Equal(req.Header.peek(strExpect), str100Continue)
1119}
1120
1121// ContinueReadBody reads request body if request header contains
1122// 'Expect: 100-continue'.
1123//
1124// The caller must send StatusContinue response before calling this method.
1125//
1126// If maxBodySize > 0 and the body size exceeds maxBodySize,
1127// then ErrBodyTooLarge is returned.
1128func (req *Request) ContinueReadBody(r *bufio.Reader, maxBodySize int, preParseMultipartForm ...bool) error {
1129 var err error
1130 contentLength := req.Header.realContentLength()
1131 if contentLength > 0 {
1132 if maxBodySize > 0 && contentLength > maxBodySize {
1133 return ErrBodyTooLarge
1134 }
1135
1136 if len(preParseMultipartForm) == 0 || preParseMultipartForm[0] {
1137 // Pre-read multipart form data of known length.
1138 // This way we limit memory usage for large file uploads, since their contents
1139 // is streamed into temporary files if file size exceeds defaultMaxInMemoryFileSize.
1140 req.multipartFormBoundary = string(req.Header.MultipartFormBoundary())
1141 if len(req.multipartFormBoundary) > 0 && len(req.Header.peek(strContentEncoding)) == 0 {
1142 req.multipartForm, err = readMultipartForm(r, req.multipartFormBoundary, contentLength, defaultMaxInMemoryFileSize)
1143 if err != nil {
1144 req.Reset()
1145 }
1146 return err
1147 }
1148 }
1149 }
1150
1151 if contentLength == -2 {
1152 // identity body has no sense for http requests, since
1153 // the end of body is determined by connection close.
1154 // So just ignore request body for requests without
1155 // 'Content-Length' and 'Transfer-Encoding' headers.
1156 // refer to https://tools.ietf.org/html/rfc7230#section-3.3.2
1157 if !req.Header.ignoreBody() {
1158 req.Header.SetContentLength(0)
1159 }
1160 return nil
1161 }
1162
1163 if err = req.ReadBody(r, contentLength, maxBodySize); err != nil {
1164 return err
1165 }
1166
1167 if req.Header.ContentLength() == -1 {
1168 err = req.Header.ReadTrailer(r)
1169 if err != nil && err != io.EOF {
1170 return err
1171 }
1172 }
1173 return nil
1174}
1175
1176// ReadBody reads request body from the given r, limiting the body size.
1177//
1178// If maxBodySize > 0 and the body size exceeds maxBodySize,
1179// then ErrBodyTooLarge is returned.
1180func (req *Request) ReadBody(r *bufio.Reader, contentLength int, maxBodySize int) (err error) {
1181 bodyBuf := req.bodyBuffer()
1182 bodyBuf.Reset()
1183
1184 if contentLength >= 0 {
1185 bodyBuf.B, err = readBody(r, contentLength, maxBodySize, bodyBuf.B)
1186
1187 } else if contentLength == -1 {
1188 bodyBuf.B, err = readBodyChunked(r, maxBodySize, bodyBuf.B)
1189
1190 } else {
1191 bodyBuf.B, err = readBodyIdentity(r, maxBodySize, bodyBuf.B)
1192 req.Header.SetContentLength(len(bodyBuf.B))
1193 }
1194
1195 if err != nil {
1196 req.Reset()
1197 return err
1198 }
1199 return nil
1200}
1201
1202// ContinueReadBodyStream reads request body if request header contains
1203// 'Expect: 100-continue'.
1204//
1205// The caller must send StatusContinue response before calling this method.
1206//
1207// If maxBodySize > 0 and the body size exceeds maxBodySize,
1208// then ErrBodyTooLarge is returned.
1209func (req *Request) ContinueReadBodyStream(r *bufio.Reader, maxBodySize int, preParseMultipartForm ...bool) error {
1210 var err error
1211 contentLength := req.Header.realContentLength()
1212 if contentLength > 0 {
1213 if len(preParseMultipartForm) == 0 || preParseMultipartForm[0] {
1214 // Pre-read multipart form data of known length.
1215 // This way we limit memory usage for large file uploads, since their contents
1216 // is streamed into temporary files if file size exceeds defaultMaxInMemoryFileSize.
1217 req.multipartFormBoundary = b2s(req.Header.MultipartFormBoundary())
1218 if len(req.multipartFormBoundary) > 0 && len(req.Header.peek(strContentEncoding)) == 0 {
1219 req.multipartForm, err = readMultipartForm(r, req.multipartFormBoundary, contentLength, defaultMaxInMemoryFileSize)
1220 if err != nil {
1221 req.Reset()
1222 }
1223 return err
1224 }
1225 }
1226 }
1227
1228 if contentLength == -2 {
1229 // identity body has no sense for http requests, since
1230 // the end of body is determined by connection close.
1231 // So just ignore request body for requests without
1232 // 'Content-Length' and 'Transfer-Encoding' headers.
1233 req.Header.SetContentLength(0)
1234 return nil
1235 }
1236
1237 bodyBuf := req.bodyBuffer()
1238 bodyBuf.Reset()
1239 bodyBuf.B, err = readBodyWithStreaming(r, contentLength, maxBodySize, bodyBuf.B)
1240 if err != nil {
1241 if err == ErrBodyTooLarge {
1242 req.Header.SetContentLength(contentLength)
1243 req.body = bodyBuf
1244 req.bodyStream = acquireRequestStream(bodyBuf, r, &req.Header)
1245 return nil
1246 }
1247 if err == errChunkedStream {
1248 req.body = bodyBuf
1249 req.bodyStream = acquireRequestStream(bodyBuf, r, &req.Header)
1250 return nil
1251 }
1252 req.Reset()
1253 return err
1254 }
1255
1256 req.body = bodyBuf
1257 req.bodyStream = acquireRequestStream(bodyBuf, r, &req.Header)
1258 req.Header.SetContentLength(contentLength)
1259 return nil
1260}
1261
1262// Read reads response (including body) from the given r.
1263//
1264// io.EOF is returned if r is closed before reading the first header byte.
1265func (resp *Response) Read(r *bufio.Reader) error {
1266 return resp.ReadLimitBody(r, 0)
1267}
1268
1269// ReadLimitBody reads response headers from the given r,
1270// then reads the body using the ReadBody function and limiting the body size.
1271//
1272// If resp.SkipBody is true then it skips reading the response body.
1273//
1274// If maxBodySize > 0 and the body size exceeds maxBodySize,
1275// then ErrBodyTooLarge is returned.
1276//
1277// io.EOF is returned if r is closed before reading the first header byte.
1278func (resp *Response) ReadLimitBody(r *bufio.Reader, maxBodySize int) error {
1279 resp.resetSkipHeader()
1280 err := resp.Header.Read(r)
1281 if err != nil {
1282 return err
1283 }
1284 if resp.Header.StatusCode() == StatusContinue {
1285 // Read the next response according to http://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html .
1286 if err = resp.Header.Read(r); err != nil {
1287 return err
1288 }
1289 }
1290
1291 if !resp.mustSkipBody() {
1292 err = resp.ReadBody(r, maxBodySize)
1293 if err != nil {
1294 return err
1295 }
1296 }
1297
1298 if resp.Header.ContentLength() == -1 {
1299 err = resp.Header.ReadTrailer(r)
1300 if err != nil && err != io.EOF {
1301 return err
1302 }
1303 }
1304 return nil
1305}
1306
1307// ReadBody reads response body from the given r, limiting the body size.
1308//
1309// If maxBodySize > 0 and the body size exceeds maxBodySize,
1310// then ErrBodyTooLarge is returned.
1311func (resp *Response) ReadBody(r *bufio.Reader, maxBodySize int) (err error) {
1312 bodyBuf := resp.bodyBuffer()
1313 bodyBuf.Reset()
1314
1315 contentLength := resp.Header.ContentLength()
1316 if contentLength >= 0 {
1317 bodyBuf.B, err = readBody(r, contentLength, maxBodySize, bodyBuf.B)
1318
1319 } else if contentLength == -1 {
1320 bodyBuf.B, err = readBodyChunked(r, maxBodySize, bodyBuf.B)
1321
1322 } else {
1323 bodyBuf.B, err = readBodyIdentity(r, maxBodySize, bodyBuf.B)
1324 resp.Header.SetContentLength(len(bodyBuf.B))
1325 }
1326 return err
1327}
1328
1329func (resp *Response) mustSkipBody() bool {
1330 return resp.SkipBody || resp.Header.mustSkipContentLength()
1331}
1332
1333var errRequestHostRequired = errors.New("missing required Host header in request")
1334
1335// WriteTo writes request to w. It implements io.WriterTo.
1336func (req *Request) WriteTo(w io.Writer) (int64, error) {
1337 return writeBufio(req, w)
1338}
1339
1340// WriteTo writes response to w. It implements io.WriterTo.
1341func (resp *Response) WriteTo(w io.Writer) (int64, error) {
1342 return writeBufio(resp, w)
1343}
1344
1345func writeBufio(hw httpWriter, w io.Writer) (int64, error) {
1346 sw := acquireStatsWriter(w)
1347 bw := acquireBufioWriter(sw)
1348 err1 := hw.Write(bw)
1349 err2 := bw.Flush()
1350 releaseBufioWriter(bw)
1351 n := sw.bytesWritten
1352 releaseStatsWriter(sw)
1353
1354 err := err1
1355 if err == nil {
1356 err = err2
1357 }
1358 return n, err
1359}
1360
1361type statsWriter struct {
1362 w io.Writer
1363 bytesWritten int64
1364}
1365
1366func (w *statsWriter) Write(p []byte) (int, error) {
1367 n, err := w.w.Write(p)
1368 w.bytesWritten += int64(n)
1369 return n, err
1370}
1371
1372func acquireStatsWriter(w io.Writer) *statsWriter {
1373 v := statsWriterPool.Get()
1374 if v == nil {
1375 return &statsWriter{
1376 w: w,
1377 }
1378 }
1379 sw := v.(*statsWriter)
1380 sw.w = w
1381 return sw
1382}
1383
1384func releaseStatsWriter(sw *statsWriter) {
1385 sw.w = nil
1386 sw.bytesWritten = 0
1387 statsWriterPool.Put(sw)
1388}
1389
1390var statsWriterPool sync.Pool
1391
1392func acquireBufioWriter(w io.Writer) *bufio.Writer {
1393 v := bufioWriterPool.Get()
1394 if v == nil {
1395 return bufio.NewWriter(w)
1396 }
1397 bw := v.(*bufio.Writer)
1398 bw.Reset(w)
1399 return bw
1400}
1401
1402func releaseBufioWriter(bw *bufio.Writer) {
1403 bufioWriterPool.Put(bw)
1404}
1405
1406var bufioWriterPool sync.Pool
1407
1408func (req *Request) onlyMultipartForm() bool {
1409 return req.multipartForm != nil && (req.body == nil || len(req.body.B) == 0)
1410}
1411
1412// Write writes request to w.
1413//
1414// Write doesn't flush request to w for performance reasons.
1415//
1416// See also WriteTo.
1417func (req *Request) Write(w *bufio.Writer) error {
1418 if len(req.Header.Host()) == 0 || req.parsedURI {
1419 uri := req.URI()
1420 host := uri.Host()
1421 if len(req.Header.Host()) == 0 {
1422 if len(host) == 0 {
1423 return errRequestHostRequired
1424 } else {
1425 req.Header.SetHostBytes(host)
1426 }
1427 } else if !req.UseHostHeader {
1428 req.Header.SetHostBytes(host)
1429 }
1430 req.Header.SetRequestURIBytes(uri.RequestURI())
1431
1432 if len(uri.username) > 0 {
1433 // RequestHeader.SetBytesKV only uses RequestHeader.bufKV.key
1434 // So we are free to use RequestHeader.bufKV.value as a scratch pad for
1435 // the base64 encoding.
1436 nl := len(uri.username) + len(uri.password) + 1
1437 nb := nl + len(strBasicSpace)
1438 tl := nb + base64.StdEncoding.EncodedLen(nl)
1439 if tl > cap(req.Header.bufKV.value) {
1440 req.Header.bufKV.value = make([]byte, 0, tl)
1441 }
1442 buf := req.Header.bufKV.value[:0]
1443 buf = append(buf, uri.username...)
1444 buf = append(buf, strColon...)
1445 buf = append(buf, uri.password...)
1446 buf = append(buf, strBasicSpace...)
1447 base64.StdEncoding.Encode(buf[nb:tl], buf[:nl])
1448 req.Header.SetBytesKV(strAuthorization, buf[nl:tl])
1449 }
1450 }
1451
1452 if req.bodyStream != nil {
1453 return req.writeBodyStream(w)
1454 }
1455
1456 body := req.bodyBytes()
1457 var err error
1458 if req.onlyMultipartForm() {
1459 body, err = marshalMultipartForm(req.multipartForm, req.multipartFormBoundary)
1460 if err != nil {
1461 return fmt.Errorf("error when marshaling multipart form: %w", err)
1462 }
1463 req.Header.SetMultipartFormBoundary(req.multipartFormBoundary)
1464 }
1465
1466 hasBody := false
1467 if len(body) == 0 {
1468 body = req.postArgs.QueryString()
1469 }
1470 if len(body) != 0 || !req.Header.ignoreBody() {
1471 hasBody = true
1472 req.Header.SetContentLength(len(body))
1473 }
1474 if err = req.Header.Write(w); err != nil {
1475 return err
1476 }
1477 if hasBody {
1478 _, err = w.Write(body)
1479 } else if len(body) > 0 {
1480 if req.secureErrorLogMessage {
1481 return fmt.Errorf("non-zero body for non-POST request")
1482 }
1483 return fmt.Errorf("non-zero body for non-POST request. body=%q", body)
1484 }
1485 return err
1486}
1487
1488// WriteGzip writes response with gzipped body to w.
1489//
1490// The method gzips response body and sets 'Content-Encoding: gzip'
1491// header before writing response to w.
1492//
1493// WriteGzip doesn't flush response to w for performance reasons.
1494func (resp *Response) WriteGzip(w *bufio.Writer) error {
1495 return resp.WriteGzipLevel(w, CompressDefaultCompression)
1496}
1497
1498// WriteGzipLevel writes response with gzipped body to w.
1499//
1500// Level is the desired compression level:
1501//
1502// * CompressNoCompression
1503// * CompressBestSpeed
1504// * CompressBestCompression
1505// * CompressDefaultCompression
1506// * CompressHuffmanOnly
1507//
1508// The method gzips response body and sets 'Content-Encoding: gzip'
1509// header before writing response to w.
1510//
1511// WriteGzipLevel doesn't flush response to w for performance reasons.
1512func (resp *Response) WriteGzipLevel(w *bufio.Writer, level int) error {
1513 if err := resp.gzipBody(level); err != nil {
1514 return err
1515 }
1516 return resp.Write(w)
1517}
1518
1519// WriteDeflate writes response with deflated body to w.
1520//
1521// The method deflates response body and sets 'Content-Encoding: deflate'
1522// header before writing response to w.
1523//
1524// WriteDeflate doesn't flush response to w for performance reasons.
1525func (resp *Response) WriteDeflate(w *bufio.Writer) error {
1526 return resp.WriteDeflateLevel(w, CompressDefaultCompression)
1527}
1528
1529// WriteDeflateLevel writes response with deflated body to w.
1530//
1531// Level is the desired compression level:
1532//
1533// * CompressNoCompression
1534// * CompressBestSpeed
1535// * CompressBestCompression
1536// * CompressDefaultCompression
1537// * CompressHuffmanOnly
1538//
1539// The method deflates response body and sets 'Content-Encoding: deflate'
1540// header before writing response to w.
1541//
1542// WriteDeflateLevel doesn't flush response to w for performance reasons.
1543func (resp *Response) WriteDeflateLevel(w *bufio.Writer, level int) error {
1544 if err := resp.deflateBody(level); err != nil {
1545 return err
1546 }
1547 return resp.Write(w)
1548}
1549
1550func (resp *Response) brotliBody(level int) error {
1551 if len(resp.Header.peek(strContentEncoding)) > 0 {
1552 // It looks like the body is already compressed.
1553 // Do not compress it again.
1554 return nil
1555 }
1556
1557 if !resp.Header.isCompressibleContentType() {
1558 // The content-type cannot be compressed.
1559 return nil
1560 }
1561
1562 if resp.bodyStream != nil {
1563 // Reset Content-Length to -1, since it is impossible
1564 // to determine body size beforehand of streamed compression.
1565 // For https://github.com/valyala/fasthttp/issues/176 .
1566 resp.Header.SetContentLength(-1)
1567
1568 // Do not care about memory allocations here, since brotli is slow
1569 // and allocates a lot of memory by itself.
1570 bs := resp.bodyStream
1571 resp.bodyStream = NewStreamReader(func(sw *bufio.Writer) {
1572 zw := acquireStacklessBrotliWriter(sw, level)
1573 fw := &flushWriter{
1574 wf: zw,
1575 bw: sw,
1576 }
1577 copyZeroAlloc(fw, bs) //nolint:errcheck
1578 releaseStacklessBrotliWriter(zw, level)
1579 if bsc, ok := bs.(io.Closer); ok {
1580 bsc.Close()
1581 }
1582 })
1583 } else {
1584 bodyBytes := resp.bodyBytes()
1585 if len(bodyBytes) < minCompressLen {
1586 // There is no sense in spending CPU time on small body compression,
1587 // since there is a very high probability that the compressed
1588 // body size will be bigger than the original body size.
1589 return nil
1590 }
1591 w := responseBodyPool.Get()
1592 w.B = AppendBrotliBytesLevel(w.B, bodyBytes, level)
1593
1594 // Hack: swap resp.body with w.
1595 if resp.body != nil {
1596 responseBodyPool.Put(resp.body)
1597 }
1598 resp.body = w
1599 resp.bodyRaw = nil
1600 }
1601 resp.Header.SetCanonical(strContentEncoding, strBr)
1602 return nil
1603}
1604
1605func (resp *Response) gzipBody(level int) error {
1606 if len(resp.Header.peek(strContentEncoding)) > 0 {
1607 // It looks like the body is already compressed.
1608 // Do not compress it again.
1609 return nil
1610 }
1611
1612 if !resp.Header.isCompressibleContentType() {
1613 // The content-type cannot be compressed.
1614 return nil
1615 }
1616
1617 if resp.bodyStream != nil {
1618 // Reset Content-Length to -1, since it is impossible
1619 // to determine body size beforehand of streamed compression.
1620 // For https://github.com/valyala/fasthttp/issues/176 .
1621 resp.Header.SetContentLength(-1)
1622
1623 // Do not care about memory allocations here, since gzip is slow
1624 // and allocates a lot of memory by itself.
1625 bs := resp.bodyStream
1626 resp.bodyStream = NewStreamReader(func(sw *bufio.Writer) {
1627 zw := acquireStacklessGzipWriter(sw, level)
1628 fw := &flushWriter{
1629 wf: zw,
1630 bw: sw,
1631 }
1632 copyZeroAlloc(fw, bs) //nolint:errcheck
1633 releaseStacklessGzipWriter(zw, level)
1634 if bsc, ok := bs.(io.Closer); ok {
1635 bsc.Close()
1636 }
1637 })
1638 } else {
1639 bodyBytes := resp.bodyBytes()
1640 if len(bodyBytes) < minCompressLen {
1641 // There is no sense in spending CPU time on small body compression,
1642 // since there is a very high probability that the compressed
1643 // body size will be bigger than the original body size.
1644 return nil
1645 }
1646 w := responseBodyPool.Get()
1647 w.B = AppendGzipBytesLevel(w.B, bodyBytes, level)
1648
1649 // Hack: swap resp.body with w.
1650 if resp.body != nil {
1651 responseBodyPool.Put(resp.body)
1652 }
1653 resp.body = w
1654 resp.bodyRaw = nil
1655 }
1656 resp.Header.SetCanonical(strContentEncoding, strGzip)
1657 return nil
1658}
1659
1660func (resp *Response) deflateBody(level int) error {
1661 if len(resp.Header.peek(strContentEncoding)) > 0 {
1662 // It looks like the body is already compressed.
1663 // Do not compress it again.
1664 return nil
1665 }
1666
1667 if !resp.Header.isCompressibleContentType() {
1668 // The content-type cannot be compressed.
1669 return nil
1670 }
1671
1672 if resp.bodyStream != nil {
1673 // Reset Content-Length to -1, since it is impossible
1674 // to determine body size beforehand of streamed compression.
1675 // For https://github.com/valyala/fasthttp/issues/176 .
1676 resp.Header.SetContentLength(-1)
1677
1678 // Do not care about memory allocations here, since flate is slow
1679 // and allocates a lot of memory by itself.
1680 bs := resp.bodyStream
1681 resp.bodyStream = NewStreamReader(func(sw *bufio.Writer) {
1682 zw := acquireStacklessDeflateWriter(sw, level)
1683 fw := &flushWriter{
1684 wf: zw,
1685 bw: sw,
1686 }
1687 copyZeroAlloc(fw, bs) //nolint:errcheck
1688 releaseStacklessDeflateWriter(zw, level)
1689 if bsc, ok := bs.(io.Closer); ok {
1690 bsc.Close()
1691 }
1692 })
1693 } else {
1694 bodyBytes := resp.bodyBytes()
1695 if len(bodyBytes) < minCompressLen {
1696 // There is no sense in spending CPU time on small body compression,
1697 // since there is a very high probability that the compressed
1698 // body size will be bigger than the original body size.
1699 return nil
1700 }
1701 w := responseBodyPool.Get()
1702 w.B = AppendDeflateBytesLevel(w.B, bodyBytes, level)
1703
1704 // Hack: swap resp.body with w.
1705 if resp.body != nil {
1706 responseBodyPool.Put(resp.body)
1707 }
1708 resp.body = w
1709 resp.bodyRaw = nil
1710 }
1711 resp.Header.SetCanonical(strContentEncoding, strDeflate)
1712 return nil
1713}
1714
1715// Bodies with sizes smaller than minCompressLen aren't compressed at all
1716const minCompressLen = 200
1717
1718type writeFlusher interface {
1719 io.Writer
1720 Flush() error
1721}
1722
1723type flushWriter struct {
1724 wf writeFlusher
1725 bw *bufio.Writer
1726}
1727
1728func (w *flushWriter) Write(p []byte) (int, error) {
1729 n, err := w.wf.Write(p)
1730 if err != nil {
1731 return 0, err
1732 }
1733 if err = w.wf.Flush(); err != nil {
1734 return 0, err
1735 }
1736 if err = w.bw.Flush(); err != nil {
1737 return 0, err
1738 }
1739 return n, nil
1740}
1741
1742// Write writes response to w.
1743//
1744// Write doesn't flush response to w for performance reasons.
1745//
1746// See also WriteTo.
1747func (resp *Response) Write(w *bufio.Writer) error {
1748 sendBody := !resp.mustSkipBody()
1749
1750 if resp.bodyStream != nil {
1751 return resp.writeBodyStream(w, sendBody)
1752 }
1753
1754 body := resp.bodyBytes()
1755 bodyLen := len(body)
1756 if sendBody || bodyLen > 0 {
1757 resp.Header.SetContentLength(bodyLen)
1758 }
1759 if err := resp.Header.Write(w); err != nil {
1760 return err
1761 }
1762 if sendBody {
1763 if _, err := w.Write(body); err != nil {
1764 return err
1765 }
1766 }
1767 return nil
1768}
1769
1770func (req *Request) writeBodyStream(w *bufio.Writer) error {
1771 var err error
1772
1773 contentLength := req.Header.ContentLength()
1774 if contentLength < 0 {
1775 lrSize := limitedReaderSize(req.bodyStream)
1776 if lrSize >= 0 {
1777 contentLength = int(lrSize)
1778 if int64(contentLength) != lrSize {
1779 contentLength = -1
1780 }
1781 if contentLength >= 0 {
1782 req.Header.SetContentLength(contentLength)
1783 }
1784 }
1785 }
1786 if contentLength >= 0 {
1787 if err = req.Header.Write(w); err == nil {
1788 err = writeBodyFixedSize(w, req.bodyStream, int64(contentLength))
1789 }
1790 } else {
1791 req.Header.SetContentLength(-1)
1792 err = req.Header.Write(w)
1793 if err == nil {
1794 err = writeBodyChunked(w, req.bodyStream)
1795 }
1796 if err == nil {
1797 err = req.Header.writeTrailer(w)
1798 }
1799 }
1800 err1 := req.closeBodyStream()
1801 if err == nil {
1802 err = err1
1803 }
1804 return err
1805}
1806
1807// ErrBodyStreamWritePanic is returned when panic happens during writing body stream.
1808type ErrBodyStreamWritePanic struct {
1809 error
1810}
1811
1812func (resp *Response) writeBodyStream(w *bufio.Writer, sendBody bool) (err error) {
1813 defer func() {
1814 if r := recover(); r != nil {
1815 err = &ErrBodyStreamWritePanic{
1816 error: fmt.Errorf("panic while writing body stream: %+v", r),
1817 }
1818 }
1819 }()
1820
1821 contentLength := resp.Header.ContentLength()
1822 if contentLength < 0 {
1823 lrSize := limitedReaderSize(resp.bodyStream)
1824 if lrSize >= 0 {
1825 contentLength = int(lrSize)
1826 if int64(contentLength) != lrSize {
1827 contentLength = -1
1828 }
1829 if contentLength >= 0 {
1830 resp.Header.SetContentLength(contentLength)
1831 }
1832 }
1833 }
1834 if contentLength >= 0 {
1835 if err = resp.Header.Write(w); err == nil {
1836 if resp.ImmediateHeaderFlush {
1837 err = w.Flush()
1838 }
1839 if err == nil && sendBody {
1840 err = writeBodyFixedSize(w, resp.bodyStream, int64(contentLength))
1841 }
1842 }
1843 } else {
1844 resp.Header.SetContentLength(-1)
1845 if err = resp.Header.Write(w); err == nil {
1846 if resp.ImmediateHeaderFlush {
1847 err = w.Flush()
1848 }
1849 if err == nil && sendBody {
1850 err = writeBodyChunked(w, resp.bodyStream)
1851 }
1852 if err == nil {
1853 err = resp.Header.writeTrailer(w)
1854 }
1855 }
1856 }
1857 err1 := resp.closeBodyStream()
1858 if err == nil {
1859 err = err1
1860 }
1861 return err
1862}
1863
1864func (req *Request) closeBodyStream() error {
1865 if req.bodyStream == nil {
1866 return nil
1867 }
1868 var err error
1869 if bsc, ok := req.bodyStream.(io.Closer); ok {
1870 err = bsc.Close()
1871 }
1872 req.bodyStream = nil
1873 return err
1874}
1875
1876func (resp *Response) closeBodyStream() error {
1877 if resp.bodyStream == nil {
1878 return nil
1879 }
1880 var err error
1881 if bsc, ok := resp.bodyStream.(io.Closer); ok {
1882 err = bsc.Close()
1883 }
1884 resp.bodyStream = nil
1885 return err
1886}
1887
1888// String returns request representation.
1889//
1890// Returns error message instead of request representation on error.
1891//
1892// Use Write instead of String for performance-critical code.
1893func (req *Request) String() string {
1894 return getHTTPString(req)
1895}
1896
1897// String returns response representation.
1898//
1899// Returns error message instead of response representation on error.
1900//
1901// Use Write instead of String for performance-critical code.
1902func (resp *Response) String() string {
1903 return getHTTPString(resp)
1904}
1905
1906func getHTTPString(hw httpWriter) string {
1907 w := bytebufferpool.Get()
1908 bw := bufio.NewWriter(w)
1909 if err := hw.Write(bw); err != nil {
1910 return err.Error()
1911 }
1912 if err := bw.Flush(); err != nil {
1913 return err.Error()
1914 }
1915 s := string(w.B)
1916 bytebufferpool.Put(w)
1917 return s
1918}
1919
1920type httpWriter interface {
1921 Write(w *bufio.Writer) error
1922}
1923
1924func writeBodyChunked(w *bufio.Writer, r io.Reader) error {
1925 vbuf := copyBufPool.Get()
1926 buf := vbuf.([]byte)
1927
1928 var err error
1929 var n int
1930 for {
1931 n, err = r.Read(buf)
1932 if n == 0 {
1933 if err == nil {
1934 panic("BUG: io.Reader returned 0, nil")
1935 }
1936 if err == io.EOF {
1937 if err = writeChunk(w, buf[:0]); err != nil {
1938 break
1939 }
1940 err = nil
1941 }
1942 break
1943 }
1944 if err = writeChunk(w, buf[:n]); err != nil {
1945 break
1946 }
1947 }
1948
1949 copyBufPool.Put(vbuf)
1950 return err
1951}
1952
1953func limitedReaderSize(r io.Reader) int64 {
1954 lr, ok := r.(*io.LimitedReader)
1955 if !ok {
1956 return -1
1957 }
1958 return lr.N
1959}
1960
1961func writeBodyFixedSize(w *bufio.Writer, r io.Reader, size int64) error {
1962 if size > maxSmallFileSize {
1963 // w buffer must be empty for triggering
1964 // sendfile path in bufio.Writer.ReadFrom.
1965 if err := w.Flush(); err != nil {
1966 return err
1967 }
1968 }
1969
1970 n, err := copyZeroAlloc(w, r)
1971
1972 if n != size && err == nil {
1973 err = fmt.Errorf("copied %d bytes from body stream instead of %d bytes", n, size)
1974 }
1975 return err
1976}
1977
1978func copyZeroAlloc(w io.Writer, r io.Reader) (int64, error) {
1979 vbuf := copyBufPool.Get()
1980 buf := vbuf.([]byte)
1981 n, err := io.CopyBuffer(w, r, buf)
1982 copyBufPool.Put(vbuf)
1983 return n, err
1984}
1985
1986var copyBufPool = sync.Pool{
1987 New: func() interface{} {
1988 return make([]byte, 4096)
1989 },
1990}
1991
1992func writeChunk(w *bufio.Writer, b []byte) error {
1993 n := len(b)
1994 if err := writeHexInt(w, n); err != nil {
1995 return err
1996 }
1997 if _, err := w.Write(strCRLF); err != nil {
1998 return err
1999 }
2000 if _, err := w.Write(b); err != nil {
2001 return err
2002 }
2003 // If is end chunk, write CRLF after writing trailer
2004 if n > 0 {
2005 if _, err := w.Write(strCRLF); err != nil {
2006 return err
2007 }
2008 }
2009 return w.Flush()
2010}
2011
2012// ErrBodyTooLarge is returned if either request or response body exceeds
2013// the given limit.
2014var ErrBodyTooLarge = errors.New("body size exceeds the given limit")
2015
2016func readBody(r *bufio.Reader, contentLength int, maxBodySize int, dst []byte) ([]byte, error) {
2017 if maxBodySize > 0 && contentLength > maxBodySize {
2018 return dst, ErrBodyTooLarge
2019 }
2020 return appendBodyFixedSize(r, dst, contentLength)
2021}
2022
2023var errChunkedStream = errors.New("chunked stream")
2024
2025func readBodyWithStreaming(r *bufio.Reader, contentLength int, maxBodySize int, dst []byte) (b []byte, err error) {
2026 if contentLength == -1 {
2027 // handled in requestStream.Read()
2028 return b, errChunkedStream
2029 }
2030
2031 dst = dst[:0]
2032
2033 readN := maxBodySize
2034 if readN > contentLength {
2035 readN = contentLength
2036 }
2037 if readN > 8*1024 {
2038 readN = 8 * 1024
2039 }
2040
2041 if contentLength >= 0 && maxBodySize >= contentLength {
2042 b, err = appendBodyFixedSize(r, dst, readN)
2043 } else {
2044 b, err = readBodyIdentity(r, readN, dst)
2045 }
2046
2047 if err != nil {
2048 return b, err
2049 }
2050 if contentLength > maxBodySize {
2051 return b, ErrBodyTooLarge
2052 }
2053 return b, nil
2054}
2055
2056func readBodyIdentity(r *bufio.Reader, maxBodySize int, dst []byte) ([]byte, error) {
2057 dst = dst[:cap(dst)]
2058 if len(dst) == 0 {
2059 dst = make([]byte, 1024)
2060 }
2061 offset := 0
2062 for {
2063 nn, err := r.Read(dst[offset:])
2064 if nn <= 0 {
2065 if err != nil {
2066 if err == io.EOF {
2067 return dst[:offset], nil
2068 }
2069 return dst[:offset], err
2070 }
2071 panic(fmt.Sprintf("BUG: bufio.Read() returned (%d, nil)", nn))
2072 }
2073 offset += nn
2074 if maxBodySize > 0 && offset > maxBodySize {
2075 return dst[:offset], ErrBodyTooLarge
2076 }
2077 if len(dst) == offset {
2078 n := round2(2 * offset)
2079 if maxBodySize > 0 && n > maxBodySize {
2080 n = maxBodySize + 1
2081 }
2082 b := make([]byte, n)
2083 copy(b, dst)
2084 dst = b
2085 }
2086 }
2087}
2088
2089func appendBodyFixedSize(r *bufio.Reader, dst []byte, n int) ([]byte, error) {
2090 if n == 0 {
2091 return dst, nil
2092 }
2093
2094 offset := len(dst)
2095 dstLen := offset + n
2096 if cap(dst) < dstLen {
2097 b := make([]byte, round2(dstLen))
2098 copy(b, dst)
2099 dst = b
2100 }
2101 dst = dst[:dstLen]
2102
2103 for {
2104 nn, err := r.Read(dst[offset:])
2105 if nn <= 0 {
2106 if err != nil {
2107 if err == io.EOF {
2108 err = io.ErrUnexpectedEOF
2109 }
2110 return dst[:offset], err
2111 }
2112 panic(fmt.Sprintf("BUG: bufio.Read() returned (%d, nil)", nn))
2113 }
2114 offset += nn
2115 if offset == dstLen {
2116 return dst, nil
2117 }
2118 }
2119}
2120
2121// ErrBrokenChunk is returned when server receives a broken chunked body (Transfer-Encoding: chunked).
2122type ErrBrokenChunk struct {
2123 error
2124}
2125
2126func readBodyChunked(r *bufio.Reader, maxBodySize int, dst []byte) ([]byte, error) {
2127 if len(dst) > 0 {
2128 panic("BUG: expected zero-length buffer")
2129 }
2130
2131 strCRLFLen := len(strCRLF)
2132 for {
2133 chunkSize, err := parseChunkSize(r)
2134 if err != nil {
2135 return dst, err
2136 }
2137 if chunkSize == 0 {
2138 return dst, err
2139 }
2140 if maxBodySize > 0 && len(dst)+chunkSize > maxBodySize {
2141 return dst, ErrBodyTooLarge
2142 }
2143 dst, err = appendBodyFixedSize(r, dst, chunkSize+strCRLFLen)
2144 if err != nil {
2145 return dst, err
2146 }
2147 if !bytes.Equal(dst[len(dst)-strCRLFLen:], strCRLF) {
2148 return dst, ErrBrokenChunk{
2149 error: fmt.Errorf("cannot find crlf at the end of chunk"),
2150 }
2151 }
2152 dst = dst[:len(dst)-strCRLFLen]
2153 }
2154}
2155
2156func parseChunkSize(r *bufio.Reader) (int, error) {
2157 n, err := readHexInt(r)
2158 if err != nil {
2159 return -1, err
2160 }
2161 for {
2162 c, err := r.ReadByte()
2163 if err != nil {
2164 return -1, ErrBrokenChunk{
2165 error: fmt.Errorf("cannot read '\r' char at the end of chunk size: %s", err),
2166 }
2167 }
2168 // Skip chunk extension after chunk size.
2169 // Add support later if anyone needs it.
2170 if c != '\r' {
2171 continue
2172 }
2173 if err := r.UnreadByte(); err != nil {
2174 return -1, ErrBrokenChunk{
2175 error: fmt.Errorf("cannot unread '\r' char at the end of chunk size: %w", err),
2176 }
2177 }
2178 break
2179 }
2180 err = readCrLf(r)
2181 if err != nil {
2182 return -1, err
2183 }
2184 return n, nil
2185}
2186
2187func readCrLf(r *bufio.Reader) error {
2188 for _, exp := range []byte{'\r', '\n'} {
2189 c, err := r.ReadByte()
2190 if err != nil {
2191 return ErrBrokenChunk{
2192 error: fmt.Errorf("cannot read %q char at the end of chunk size: %w", exp, err),
2193 }
2194 }
2195 if c != exp {
2196 return ErrBrokenChunk{
2197 error: fmt.Errorf("unexpected char %q at the end of chunk size. Expected %q", c, exp),
2198 }
2199 }
2200 }
2201 return nil
2202}
2203
2204func round2(n int) int {
2205 if n <= 0 {
2206 return 0
2207 }
2208
2209 x := uint32(n - 1)
2210 x |= x >> 1
2211 x |= x >> 2
2212 x |= x >> 4
2213 x |= x >> 8
2214 x |= x >> 16
2215
2216 return int(x + 1)
2217}
Note: See TracBrowser for help on using the repository browser.