package fasthttp

import (
	
	
	
	
	
	
	
	
	
	
	
	

	
)

var (
	requestBodyPoolSizeLimit  = -1
	responseBodyPoolSizeLimit = -1
)

// SetBodySizePoolLimit set the max body size for bodies to be returned to the pool.
// If the body size is larger it will be released instead of put back into the pool for reuse.
func (,  int) {
	requestBodyPoolSizeLimit = 
	responseBodyPoolSizeLimit = 
}

// Request represents HTTP request.
//
// It is forbidden copying Request instances. Create new instances
// and use CopyTo instead.
//
// Request instance MUST NOT be used from concurrently running goroutines.
type Request struct {
	noCopy noCopy

	// Request header
	//
	// Copying Header by value is forbidden. Use pointer to Header instead.
	Header RequestHeader

	uri      URI
	postArgs Args

	bodyStream io.Reader
	w          requestBodyWriter
	body       *bytebufferpool.ByteBuffer
	bodyRaw    []byte

	multipartForm         *multipart.Form
	multipartFormBoundary string
	secureErrorLogMessage bool

	// Group bool members in order to reduce Request object size.
	parsedURI      bool
	parsedPostArgs bool

	keepBodyBuffer bool

	// Used by Server to indicate the request was received on a HTTPS endpoint.
	// Client/HostClient shouldn't use this field but should depend on the uri.scheme instead.
	isTLS bool

	// Request timeout. Usually set by DoDeadline or DoTimeout
	// if <= 0, means not set
	timeout time.Duration

	// Use Host header (request.Header.SetHost) instead of the host from SetRequestURI, SetHost, or URI().SetHost
	UseHostHeader bool
}

// Response represents HTTP response.
//
// It is forbidden copying Response instances. Create new instances
// and use CopyTo instead.
//
// Response instance MUST NOT be used from concurrently running goroutines.
type Response struct {
	noCopy noCopy

	// Response header
	//
	// Copying Header by value is forbidden. Use pointer to Header instead.
	Header ResponseHeader

	// Flush headers as soon as possible without waiting for first body bytes.
	// Relevant for bodyStream only.
	ImmediateHeaderFlush bool

	// StreamBody enables response body streaming.
	// Use SetBodyStream to set the body stream.
	StreamBody bool

	bodyStream io.Reader
	w          responseBodyWriter
	body       *bytebufferpool.ByteBuffer
	bodyRaw    []byte

	// Response.Read() skips reading body if set to true.
	// Use it for reading HEAD responses.
	//
	// Response.Write() skips writing body if set to true.
	// Use it for writing HEAD responses.
	SkipBody bool

	keepBodyBuffer        bool
	secureErrorLogMessage bool

	// Remote TCPAddr from concurrently net.Conn
	raddr net.Addr
	// Local TCPAddr from concurrently net.Conn
	laddr net.Addr
}

// SetHost sets host for the request.
func ( *Request) ( string) {
	.URI().SetHost()
}

// SetHostBytes sets host for the request.
func ( *Request) ( []byte) {
	.URI().SetHostBytes()
}

// Host returns the host for the given request.
func ( *Request) () []byte {
	return .URI().Host()
}

// SetRequestURI sets RequestURI.
func ( *Request) ( string) {
	.Header.SetRequestURI()
	.parsedURI = false
}

// SetRequestURIBytes sets RequestURI.
func ( *Request) ( []byte) {
	.Header.SetRequestURIBytes()
	.parsedURI = false
}

// RequestURI returns request's URI.
func ( *Request) () []byte {
	if .parsedURI {
		 := .uri.RequestURI()
		.SetRequestURIBytes()
	}
	return .Header.RequestURI()
}

// StatusCode returns response status code.
func ( *Response) () int {
	return .Header.StatusCode()
}

// SetStatusCode sets response status code.
func ( *Response) ( int) {
	.Header.SetStatusCode()
}

// ConnectionClose returns true if 'Connection: close' header is set.
func ( *Response) () bool {
	return .Header.ConnectionClose()
}

// SetConnectionClose sets 'Connection: close' header.
func ( *Response) () {
	.Header.SetConnectionClose()
}

// ConnectionClose returns true if 'Connection: close' header is set.
func ( *Request) () bool {
	return .Header.ConnectionClose()
}

// SetConnectionClose sets 'Connection: close' header.
func ( *Request) () {
	.Header.SetConnectionClose()
}

// SendFile registers file on the given path to be used as response body
// when Write is called.
//
// Note that SendFile doesn't set Content-Type, so set it yourself
// with Header.SetContentType.
func ( *Response) ( string) error {
	,  := os.Open()
	if  != nil {
		return 
	}
	,  := .Stat()
	if  != nil {
		.Close()
		return 
	}
	 := .Size()
	 := int()
	if int64() !=  {
		 = -1
	}

	.Header.SetLastModified(.ModTime())
	.SetBodyStream(, )
	return nil
}

// SetBodyStream sets request body stream and, optionally body size.
//
// If bodySize is >= 0, then the bodyStream must provide exactly bodySize bytes
// before returning io.EOF.
//
// If bodySize < 0, then bodyStream is read until io.EOF.
//
// bodyStream.Close() is called after finishing reading all body data
// if it implements io.Closer.
//
// Note that GET and HEAD requests cannot have body.
//
// See also SetBodyStreamWriter.
func ( *Request) ( io.Reader,  int) {
	.ResetBody()
	.bodyStream = 
	.Header.SetContentLength()
}

// SetBodyStream sets response body stream and, optionally body size.
//
// If bodySize is >= 0, then the bodyStream must provide exactly bodySize bytes
// before returning io.EOF.
//
// If bodySize < 0, then bodyStream is read until io.EOF.
//
// bodyStream.Close() is called after finishing reading all body data
// if it implements io.Closer.
//
// See also SetBodyStreamWriter.
func ( *Response) ( io.Reader,  int) {
	.ResetBody()
	.bodyStream = 
	.Header.SetContentLength()
}

// IsBodyStream returns true if body is set via SetBodyStream*
func ( *Request) () bool {
	return .bodyStream != nil
}

// IsBodyStream returns true if body is set via SetBodyStream*
func ( *Response) () bool {
	return .bodyStream != nil
}

// SetBodyStreamWriter registers the given sw for populating request body.
//
// This function may be used in the following cases:
//
//   - if request body is too big (more than 10MB).
//   - if request body is streamed from slow external sources.
//   - if request body must be streamed to the server in chunks
//     (aka `http client push` or `chunked transfer-encoding`).
//
// Note that GET and HEAD requests cannot have body.
//
// See also SetBodyStream.
func ( *Request) ( StreamWriter) {
	 := NewStreamReader()
	.SetBodyStream(, -1)
}

// SetBodyStreamWriter registers the given sw for populating response body.
//
// This function may be used in the following cases:
//
//   - if response body is too big (more than 10MB).
//   - if response body is streamed from slow external sources.
//   - if response body must be streamed to the client in chunks
//     (aka `http server push` or `chunked transfer-encoding`).
//
// See also SetBodyStream.
func ( *Response) ( StreamWriter) {
	 := NewStreamReader()
	.SetBodyStream(, -1)
}

// BodyWriter returns writer for populating response body.
//
// If used inside RequestHandler, the returned writer must not be used
// after returning from RequestHandler. Use RequestCtx.Write
// or SetBodyStreamWriter in this case.
func ( *Response) () io.Writer {
	.w.r = 
	return &.w
}

// BodyStream returns io.Reader
//
// You must CloseBodyStream or ReleaseRequest after you use it.
func ( *Request) () io.Reader {
	return .bodyStream
}

func ( *Request) () error {
	return .closeBodyStream()
}

// BodyStream returns io.Reader
//
// You must CloseBodyStream or ReleaseResponse after you use it.
func ( *Response) () io.Reader {
	return .bodyStream
}

func ( *Response) () error {
	return .closeBodyStream()
}

type closeReader struct {
	io.Reader
	closeFunc func() error
}

func newCloseReader( io.Reader,  func() error) io.ReadCloser {
	if  == nil {
		panic(`BUG: reader is nil`)
	}
	return &closeReader{Reader: , closeFunc: }
}

func ( *closeReader) () error {
	if .closeFunc == nil {
		return nil
	}
	return .closeFunc()
}

// BodyWriter returns writer for populating request body.
func ( *Request) () io.Writer {
	.w.r = 
	return &.w
}

type responseBodyWriter struct {
	r *Response
}

func ( *responseBodyWriter) ( []byte) (int, error) {
	.r.AppendBody()
	return len(), nil
}

type requestBodyWriter struct {
	r *Request
}

func ( *requestBodyWriter) ( []byte) (int, error) {
	.r.AppendBody()
	return len(), nil
}

func ( *Response) ( net.Conn) {
	.raddr = .RemoteAddr()
	.laddr = .LocalAddr()
}

// RemoteAddr returns the remote network address. The Addr returned is shared
// by all invocations of RemoteAddr, so do not modify it.
func ( *Response) () net.Addr {
	return .raddr
}

// LocalAddr returns the local network address. The Addr returned is shared
// by all invocations of LocalAddr, so do not modify it.
func ( *Response) () net.Addr {
	return .laddr
}

// Body returns response body.
//
// The returned value is valid until the response is released,
// either though ReleaseResponse or your request handler returning.
// Do not store references to returned value. Make copies instead.
func ( *Response) () []byte {
	if .bodyStream != nil {
		 := .bodyBuffer()
		.Reset()
		,  := copyZeroAlloc(, .bodyStream)
		.closeBodyStream() //nolint:errcheck
		if  != nil {
			.SetString(.Error())
		}
	}
	return .bodyBytes()
}

func ( *Response) () []byte {
	if .bodyRaw != nil {
		return .bodyRaw
	}
	if .body == nil {
		return nil
	}
	return .body.B
}

func ( *Request) () []byte {
	if .bodyRaw != nil {
		return .bodyRaw
	}
	if .bodyStream != nil {
		 := .bodyBuffer()
		.Reset()
		,  := copyZeroAlloc(, .bodyStream)
		.closeBodyStream() //nolint:errcheck
		if  != nil {
			.SetString(.Error())
		}
	}
	if .body == nil {
		return nil
	}
	return .body.B
}

func ( *Response) () *bytebufferpool.ByteBuffer {
	if .body == nil {
		.body = responseBodyPool.Get()
	}
	.bodyRaw = nil
	return .body
}

func ( *Request) () *bytebufferpool.ByteBuffer {
	if .body == nil {
		.body = requestBodyPool.Get()
	}
	.bodyRaw = nil
	return .body
}

var (
	responseBodyPool bytebufferpool.Pool
	requestBodyPool  bytebufferpool.Pool
)

// BodyGunzip returns un-gzipped body data.
//
// This method may be used if the request header contains
// 'Content-Encoding: gzip' for reading un-gzipped body.
// Use Body for reading gzipped request body.
func ( *Request) () ([]byte, error) {
	return gunzipData(.Body())
}

// BodyGunzip returns un-gzipped body data.
//
// This method may be used if the response header contains
// 'Content-Encoding: gzip' for reading un-gzipped body.
// Use Body for reading gzipped response body.
func ( *Response) () ([]byte, error) {
	return gunzipData(.Body())
}

func gunzipData( []byte) ([]byte, error) {
	var  bytebufferpool.ByteBuffer
	,  := WriteGunzip(&, )
	if  != nil {
		return nil, 
	}
	return .B, nil
}

// BodyUnbrotli returns un-brotlied body data.
//
// This method may be used if the request header contains
// 'Content-Encoding: br' for reading un-brotlied body.
// Use Body for reading brotlied request body.
func ( *Request) () ([]byte, error) {
	return unBrotliData(.Body())
}

// BodyUnbrotli returns un-brotlied body data.
//
// This method may be used if the response header contains
// 'Content-Encoding: br' for reading un-brotlied body.
// Use Body for reading brotlied response body.
func ( *Response) () ([]byte, error) {
	return unBrotliData(.Body())
}

func unBrotliData( []byte) ([]byte, error) {
	var  bytebufferpool.ByteBuffer
	,  := WriteUnbrotli(&, )
	if  != nil {
		return nil, 
	}
	return .B, nil
}

// BodyInflate returns inflated body data.
//
// This method may be used if the response header contains
// 'Content-Encoding: deflate' for reading inflated request body.
// Use Body for reading deflated request body.
func ( *Request) () ([]byte, error) {
	return inflateData(.Body())
}

// BodyInflate returns inflated body data.
//
// This method may be used if the response header contains
// 'Content-Encoding: deflate' for reading inflated response body.
// Use Body for reading deflated response body.
func ( *Response) () ([]byte, error) {
	return inflateData(.Body())
}

func ( *RequestCtx) () io.Reader {
	return .Request.bodyStream
}

func inflateData( []byte) ([]byte, error) {
	var  bytebufferpool.ByteBuffer
	,  := WriteInflate(&, )
	if  != nil {
		return nil, 
	}
	return .B, nil
}

var ErrContentEncodingUnsupported = errors.New("unsupported Content-Encoding")

// BodyUncompressed returns body data and if needed decompress it from gzip, deflate or Brotli.
//
// This method may be used if the response header contains
// 'Content-Encoding' for reading uncompressed request body.
// Use Body for reading the raw request body.
func ( *Request) () ([]byte, error) {
	switch string(.Header.ContentEncoding()) {
	case "":
		return .Body(), nil
	case "deflate":
		return .BodyInflate()
	case "gzip":
		return .BodyGunzip()
	case "br":
		return .BodyUnbrotli()
	default:
		return nil, ErrContentEncodingUnsupported
	}
}

// BodyUncompressed returns body data and if needed decompress it from gzip, deflate or Brotli.
//
// This method may be used if the response header contains
// 'Content-Encoding' for reading uncompressed response body.
// Use Body for reading the raw response body.
func ( *Response) () ([]byte, error) {
	switch string(.Header.ContentEncoding()) {
	case "":
		return .Body(), nil
	case "deflate":
		return .BodyInflate()
	case "gzip":
		return .BodyGunzip()
	case "br":
		return .BodyUnbrotli()
	default:
		return nil, ErrContentEncodingUnsupported
	}
}

// BodyWriteTo writes request body to w.
func ( *Request) ( io.Writer) error {
	if .bodyStream != nil {
		,  := copyZeroAlloc(, .bodyStream)
		.closeBodyStream() //nolint:errcheck
		return 
	}
	if .onlyMultipartForm() {
		return WriteMultipartForm(, .multipartForm, .multipartFormBoundary)
	}
	,  := .Write(.bodyBytes())
	return 
}

// BodyWriteTo writes response body to w.
func ( *Response) ( io.Writer) error {
	if .bodyStream != nil {
		,  := copyZeroAlloc(, .bodyStream)
		.closeBodyStream() //nolint:errcheck
		return 
	}
	,  := .Write(.bodyBytes())
	return 
}

// AppendBody appends p to response body.
//
// It is safe re-using p after the function returns.
func ( *Response) ( []byte) {
	.closeBodyStream()     //nolint:errcheck
	.bodyBuffer().Write() //nolint:errcheck
}

// AppendBodyString appends s to response body.
func ( *Response) ( string) {
	.closeBodyStream()           //nolint:errcheck
	.bodyBuffer().WriteString() //nolint:errcheck
}

// SetBody sets response body.
//
// It is safe re-using body argument after the function returns.
func ( *Response) ( []byte) {
	.closeBodyStream() //nolint:errcheck
	 := .bodyBuffer()
	.Reset()
	.Write() //nolint:errcheck
}

// SetBodyString sets response body.
func ( *Response) ( string) {
	.closeBodyStream() //nolint:errcheck
	 := .bodyBuffer()
	.Reset()
	.WriteString() //nolint:errcheck
}

// ResetBody resets response body.
func ( *Response) () {
	.bodyRaw = nil
	.closeBodyStream() //nolint:errcheck
	if .body != nil {
		if .keepBodyBuffer {
			.body.Reset()
		} else {
			responseBodyPool.Put(.body)
			.body = nil
		}
	}
}

// SetBodyRaw sets response body, but without copying it.
//
// From this point onward the body argument must not be changed.
func ( *Response) ( []byte) {
	.ResetBody()
	.bodyRaw = 
}

// SetBodyRaw sets response body, but without copying it.
//
// From this point onward the body argument must not be changed.
func ( *Request) ( []byte) {
	.ResetBody()
	.bodyRaw = 
}

// ReleaseBody retires the response body if it is greater than "size" bytes.
//
// This permits GC to reclaim the large buffer.  If used, must be before
// ReleaseResponse.
//
// Use this method only if you really understand how it works.
// The majority of workloads don't need this method.
func ( *Response) ( int) {
	.bodyRaw = nil
	if .body == nil {
		return
	}
	if cap(.body.B) >  {
		.closeBodyStream() //nolint:errcheck
		.body = nil
	}
}

// ReleaseBody retires the request body if it is greater than "size" bytes.
//
// This permits GC to reclaim the large buffer.  If used, must be before
// ReleaseRequest.
//
// Use this method only if you really understand how it works.
// The majority of workloads don't need this method.
func ( *Request) ( int) {
	.bodyRaw = nil
	if .body == nil {
		return
	}
	if cap(.body.B) >  {
		.closeBodyStream() //nolint:errcheck
		.body = nil
	}
}

// SwapBody swaps response body with the given body and returns
// the previous response body.
//
// It is forbidden to use the body passed to SwapBody after
// the function returns.
func ( *Response) ( []byte) []byte {
	 := .bodyBuffer()

	if .bodyStream != nil {
		.Reset()
		,  := copyZeroAlloc(, .bodyStream)
		.closeBodyStream() //nolint:errcheck
		if  != nil {
			.Reset()
			.SetString(.Error())
		}
	}

	.bodyRaw = nil

	 := .B
	.B = 
	return 
}

// SwapBody swaps request body with the given body and returns
// the previous request body.
//
// It is forbidden to use the body passed to SwapBody after
// the function returns.
func ( *Request) ( []byte) []byte {
	 := .bodyBuffer()

	if .bodyStream != nil {
		.Reset()
		,  := copyZeroAlloc(, .bodyStream)
		.closeBodyStream() //nolint:errcheck
		if  != nil {
			.Reset()
			.SetString(.Error())
		}
	}

	.bodyRaw = nil

	 := .B
	.B = 
	return 
}

// Body returns request body.
//
// The returned value is valid until the request is released,
// either though ReleaseRequest or your request handler returning.
// Do not store references to returned value. Make copies instead.
func ( *Request) () []byte {
	if .bodyRaw != nil {
		return .bodyRaw
	} else if .onlyMultipartForm() {
		,  := marshalMultipartForm(.multipartForm, .multipartFormBoundary)
		if  != nil {
			return []byte(.Error())
		}
		return 
	}
	return .bodyBytes()
}

// AppendBody appends p to request body.
//
// It is safe re-using p after the function returns.
func ( *Request) ( []byte) {
	.RemoveMultipartFormFiles()
	.closeBodyStream()     //nolint:errcheck
	.bodyBuffer().Write() //nolint:errcheck
}

// AppendBodyString appends s to request body.
func ( *Request) ( string) {
	.RemoveMultipartFormFiles()
	.closeBodyStream()           //nolint:errcheck
	.bodyBuffer().WriteString() //nolint:errcheck
}

// SetBody sets request body.
//
// It is safe re-using body argument after the function returns.
func ( *Request) ( []byte) {
	.RemoveMultipartFormFiles()
	.closeBodyStream() //nolint:errcheck
	.bodyBuffer().Set()
}

// SetBodyString sets request body.
func ( *Request) ( string) {
	.RemoveMultipartFormFiles()
	.closeBodyStream() //nolint:errcheck
	.bodyBuffer().SetString()
}

// ResetBody resets request body.
func ( *Request) () {
	.bodyRaw = nil
	.RemoveMultipartFormFiles()
	.closeBodyStream() //nolint:errcheck
	if .body != nil {
		if .keepBodyBuffer {
			.body.Reset()
		} else {
			requestBodyPool.Put(.body)
			.body = nil
		}
	}
}

// CopyTo copies req contents to dst except of body stream.
func ( *Request) ( *Request) {
	.copyToSkipBody()
	switch {
	case .bodyRaw != nil:
		.bodyRaw = append(.bodyRaw[:0], .bodyRaw...)
		if .body != nil {
			.body.Reset()
		}
	case .body != nil:
		.bodyBuffer().Set(.body.B)
	case .body != nil:
		.body.Reset()
	}
}

func ( *Request) ( *Request) {
	.Reset()
	.Header.CopyTo(&.Header)

	.uri.CopyTo(&.uri)
	.parsedURI = .parsedURI

	.postArgs.CopyTo(&.postArgs)
	.parsedPostArgs = .parsedPostArgs
	.isTLS = .isTLS

	.UseHostHeader = .UseHostHeader

	// do not copy multipartForm - it will be automatically
	// re-created on the first call to MultipartForm.
}

// CopyTo copies resp contents to dst except of body stream.
func ( *Response) ( *Response) {
	.copyToSkipBody()
	switch {
	case .bodyRaw != nil:
		.bodyRaw = append(.bodyRaw, .bodyRaw...)
		if .body != nil {
			.body.Reset()
		}
	case .body != nil:
		.bodyBuffer().Set(.body.B)
	case .body != nil:
		.body.Reset()
	}
}

func ( *Response) ( *Response) {
	.Reset()
	.Header.CopyTo(&.Header)
	.SkipBody = .SkipBody
	.raddr = .raddr
	.laddr = .laddr
}

func swapRequestBody(,  *Request) {
	.body, .body = .body, .body
	.bodyRaw, .bodyRaw = .bodyRaw, .bodyRaw
	.bodyStream, .bodyStream = .bodyStream, .bodyStream

	// This code assumes that if a requestStream was swapped the headers are also swapped or copied.
	if ,  := .bodyStream.(*requestStream);  {
		.header = &.Header
	}
	if ,  := .bodyStream.(*requestStream);  {
		.header = &.Header
	}
}

func swapResponseBody(,  *Response) {
	.body, .body = .body, .body
	.bodyRaw, .bodyRaw = .bodyRaw, .bodyRaw
	.bodyStream, .bodyStream = .bodyStream, .bodyStream
}

// URI returns request URI
func ( *Request) () *URI {
	.parseURI() //nolint:errcheck
	return &.uri
}

// SetURI initializes request URI
// Use this method if a single URI may be reused across multiple requests.
// Otherwise, you can just use SetRequestURI() and it will be parsed as new URI.
// The URI is copied and can be safely modified later.
func ( *Request) ( *URI) {
	if  != nil {
		.CopyTo(&.uri)
		.parsedURI = true
		return
	}
	.uri.Reset()
	.parsedURI = false
}

func ( *Request) () error {
	if .parsedURI {
		return nil
	}
	.parsedURI = true

	return .uri.parse(.Header.Host(), .Header.RequestURI(), .isTLS)
}

// PostArgs returns POST arguments.
func ( *Request) () *Args {
	.parsePostArgs()
	return &.postArgs
}

func ( *Request) () {
	if .parsedPostArgs {
		return
	}
	.parsedPostArgs = true

	if !bytes.HasPrefix(.Header.ContentType(), strPostArgsContentType) {
		return
	}
	.postArgs.ParseBytes(.bodyBytes())
}

// ErrNoMultipartForm means that the request's Content-Type
// isn't 'multipart/form-data'.
var ErrNoMultipartForm = errors.New("request Content-Type has bad boundary or is not multipart/form-data")

// MultipartForm returns request's multipart form.
//
// Returns ErrNoMultipartForm if request's Content-Type
// isn't 'multipart/form-data'.
//
// RemoveMultipartFormFiles must be called after returned multipart form
// is processed.
func ( *Request) () (*multipart.Form, error) {
	if .multipartForm != nil {
		return .multipartForm, nil
	}

	.multipartFormBoundary = string(.Header.MultipartFormBoundary())
	if len(.multipartFormBoundary) == 0 {
		return nil, ErrNoMultipartForm
	}

	var  error
	 := .Header.peek(strContentEncoding)

	if .bodyStream != nil {
		 := .bodyStream
		if bytes.Equal(, strGzip) {
			// Do not care about memory usage here.
			if ,  = gzip.NewReader();  != nil {
				return nil, fmt.Errorf("cannot gunzip request body: %w", )
			}
		} else if len() > 0 {
			return nil, fmt.Errorf("unsupported Content-Encoding: %q", )
		}

		 := multipart.NewReader(, .multipartFormBoundary)
		.multipartForm,  = .ReadForm(8 * 1024)
		if  != nil {
			return nil, fmt.Errorf("cannot read multipart/form-data body: %w", )
		}
	} else {
		 := .bodyBytes()
		if bytes.Equal(, strGzip) {
			// Do not care about memory usage here.
			if ,  = AppendGunzipBytes(nil, );  != nil {
				return nil, fmt.Errorf("cannot gunzip request body: %w", )
			}
		} else if len() > 0 {
			return nil, fmt.Errorf("unsupported Content-Encoding: %q", )
		}

		.multipartForm,  = readMultipartForm(bytes.NewReader(), .multipartFormBoundary, len(), len())
		if  != nil {
			return nil, 
		}
	}

	return .multipartForm, nil
}

func marshalMultipartForm( *multipart.Form,  string) ([]byte, error) {
	var  bytebufferpool.ByteBuffer
	if  := WriteMultipartForm(&, , );  != nil {
		return nil, 
	}
	return .B, nil
}

// WriteMultipartForm writes the given multipart form f with the given
// boundary to w.
func ( io.Writer,  *multipart.Form,  string) error {
	// Do not care about memory allocations here, since multipart
	// form processing is slow.
	if len() == 0 {
		return errors.New("form boundary cannot be empty")
	}

	 := multipart.NewWriter()
	if  := .SetBoundary();  != nil {
		return fmt.Errorf("cannot use form boundary %q: %w", , )
	}

	// marshal values
	for ,  := range .Value {
		for ,  := range  {
			if  := .WriteField(, );  != nil {
				return fmt.Errorf("cannot write form field %q value %q: %w", , , )
			}
		}
	}

	// marshal files
	for ,  := range .File {
		for ,  := range  {
			,  := .CreatePart(.Header)
			if  != nil {
				return fmt.Errorf("cannot create form file %q (%q): %w", , .Filename, )
			}
			,  := .Open()
			if  != nil {
				return fmt.Errorf("cannot open form file %q (%q): %w", , .Filename, )
			}
			if _,  = copyZeroAlloc(, );  != nil {
				_ = .Close()
				return fmt.Errorf("error when copying form file %q (%q): %w", , .Filename, )
			}
			if  = .Close();  != nil {
				return fmt.Errorf("cannot close form file %q (%q): %w", , .Filename, )
			}
		}
	}

	if  := .Close();  != nil {
		return fmt.Errorf("error when closing multipart form writer: %w", )
	}

	return nil
}

func readMultipartForm( io.Reader,  string, ,  int) (*multipart.Form, error) {
	// Do not care about memory allocations here, since they are tiny
	// compared to multipart data (aka multi-MB files) usually sent
	// in multipart/form-data requests.

	if  <= 0 {
		return nil, fmt.Errorf("form size must be greater than 0. Given %d", )
	}
	 := io.LimitReader(, int64())
	 := multipart.NewReader(, )
	,  := .ReadForm(int64())
	if  != nil {
		return nil, fmt.Errorf("cannot read multipart/form-data body: %w", )
	}
	return , nil
}

// Reset clears request contents.
func ( *Request) () {
	if requestBodyPoolSizeLimit >= 0 && .body != nil {
		.ReleaseBody(requestBodyPoolSizeLimit)
	}
	.Header.Reset()
	.resetSkipHeader()
	.timeout = 0
	.UseHostHeader = false
}

func ( *Request) () {
	.ResetBody()
	.uri.Reset()
	.parsedURI = false
	.postArgs.Reset()
	.parsedPostArgs = false
	.isTLS = false
}

// RemoveMultipartFormFiles removes multipart/form-data temporary files
// associated with the request.
func ( *Request) () {
	if .multipartForm != nil {
		// Do not check for error, since these files may be deleted or moved
		// to new places by user code.
		.multipartForm.RemoveAll() //nolint:errcheck
		.multipartForm = nil
	}
	.multipartFormBoundary = ""
}

// Reset clears response contents.
func ( *Response) () {
	if responseBodyPoolSizeLimit >= 0 && .body != nil {
		.ReleaseBody(responseBodyPoolSizeLimit)
	}
	.resetSkipHeader()
	.Header.Reset()
	.SkipBody = false
	.raddr = nil
	.laddr = nil
	.ImmediateHeaderFlush = false
	.StreamBody = false
}

func ( *Response) () {
	.ResetBody()
}

// Read reads request (including body) from the given r.
//
// RemoveMultipartFormFiles or Reset must be called after
// reading multipart/form-data request in order to delete temporarily
// uploaded files.
//
// If MayContinue returns true, the caller must:
//
//   - Either send StatusExpectationFailed response if request headers don't
//     satisfy the caller.
//   - Or send StatusContinue response before reading request body
//     with ContinueReadBody.
//   - Or close the connection.
//
// io.EOF is returned if r is closed before reading the first header byte.
func ( *Request) ( *bufio.Reader) error {
	return .ReadLimitBody(, 0)
}

const defaultMaxInMemoryFileSize = 16 * 1024 * 1024

// ErrGetOnly is returned when server expects only GET requests,
// but some other type of request came (Server.GetOnly option is true).
var ErrGetOnly = errors.New("non-GET request received")

// ReadLimitBody reads request from the given r, limiting the body size.
//
// If maxBodySize > 0 and the body size exceeds maxBodySize,
// then ErrBodyTooLarge is returned.
//
// RemoveMultipartFormFiles or Reset must be called after
// reading multipart/form-data request in order to delete temporarily
// uploaded files.
//
// If MayContinue returns true, the caller must:
//
//   - Either send StatusExpectationFailed response if request headers don't
//     satisfy the caller.
//   - Or send StatusContinue response before reading request body
//     with ContinueReadBody.
//   - Or close the connection.
//
// io.EOF is returned if r is closed before reading the first header byte.
func ( *Request) ( *bufio.Reader,  int) error {
	.resetSkipHeader()
	if  := .Header.Read();  != nil {
		return 
	}

	return .readLimitBody(, , false, true)
}

func ( *Request) ( *bufio.Reader,  int,  bool,  bool) error {
	// Do not reset the request here - the caller must reset it before
	// calling this method.

	if  && !.Header.IsGet() && !.Header.IsHead() {
		return ErrGetOnly
	}

	if .MayContinue() {
		// 'Expect: 100-continue' header found. Let the caller deciding
		// whether to read request body or
		// to return StatusExpectationFailed.
		return nil
	}

	return .ContinueReadBody(, , )
}

func ( *Request) ( *bufio.Reader,  int,  bool,  bool) error {
	// Do not reset the request here - the caller must reset it before
	// calling this method.

	if  && !.Header.IsGet() && !.Header.IsHead() {
		return ErrGetOnly
	}

	if .MayContinue() {
		// 'Expect: 100-continue' header found. Let the caller deciding
		// whether to read request body or
		// to return StatusExpectationFailed.
		return nil
	}

	return .ContinueReadBodyStream(, , )
}

// MayContinue returns true if the request contains
// 'Expect: 100-continue' header.
//
// The caller must do one of the following actions if MayContinue returns true:
//
//   - Either send StatusExpectationFailed response if request headers don't
//     satisfy the caller.
//   - Or send StatusContinue response before reading request body
//     with ContinueReadBody.
//   - Or close the connection.
func ( *Request) () bool {
	return bytes.Equal(.Header.peek(strExpect), str100Continue)
}

// ContinueReadBody reads request body if request header contains
// 'Expect: 100-continue'.
//
// The caller must send StatusContinue response before calling this method.
//
// If maxBodySize > 0 and the body size exceeds maxBodySize,
// then ErrBodyTooLarge is returned.
func ( *Request) ( *bufio.Reader,  int,  ...bool) error {
	var  error
	 := .Header.realContentLength()
	if  > 0 {
		if  > 0 &&  >  {
			return ErrBodyTooLarge
		}

		if len() == 0 || [0] {
			// Pre-read multipart form data of known length.
			// This way we limit memory usage for large file uploads, since their contents
			// is streamed into temporary files if file size exceeds defaultMaxInMemoryFileSize.
			.multipartFormBoundary = string(.Header.MultipartFormBoundary())
			if len(.multipartFormBoundary) > 0 && len(.Header.peek(strContentEncoding)) == 0 {
				.multipartForm,  = readMultipartForm(, .multipartFormBoundary, , defaultMaxInMemoryFileSize)
				if  != nil {
					.Reset()
				}
				return 
			}
		}
	}

	if  == -2 {
		// identity body has no sense for http requests, since
		// the end of body is determined by connection close.
		// So just ignore request body for requests without
		// 'Content-Length' and 'Transfer-Encoding' headers.
		// refer to https://tools.ietf.org/html/rfc7230#section-3.3.2
		if !.Header.ignoreBody() {
			.Header.SetContentLength(0)
		}
		return nil
	}

	if  = .ReadBody(, , );  != nil {
		return 
	}

	if  == -1 {
		 = .Header.ReadTrailer()
		if  != nil &&  != io.EOF {
			return 
		}
	}
	return nil
}

// ReadBody reads request body from the given r, limiting the body size.
//
// If maxBodySize > 0 and the body size exceeds maxBodySize,
// then ErrBodyTooLarge is returned.
func ( *Request) ( *bufio.Reader,  int,  int) ( error) {
	 := .bodyBuffer()
	.Reset()

	switch {
	case  >= 0:
		.B,  = readBody(, , , .B)
	case  == -1:
		.B,  = readBodyChunked(, , .B)
		if  == nil && len(.B) == 0 {
			.Header.SetContentLength(0)
		}
	default:
		.B,  = readBodyIdentity(, , .B)
		.Header.SetContentLength(len(.B))
	}

	if  != nil {
		.Reset()
		return 
	}
	return nil
}

// ContinueReadBodyStream reads request body if request header contains
// 'Expect: 100-continue'.
//
// The caller must send StatusContinue response before calling this method.
//
// If maxBodySize > 0 and the body size exceeds maxBodySize,
// then ErrBodyTooLarge is returned.
func ( *Request) ( *bufio.Reader,  int,  ...bool) error {
	var  error
	 := .Header.realContentLength()
	if  > 0 {
		if len() == 0 || [0] {
			// Pre-read multipart form data of known length.
			// This way we limit memory usage for large file uploads, since their contents
			// is streamed into temporary files if file size exceeds defaultMaxInMemoryFileSize.
			.multipartFormBoundary = b2s(.Header.MultipartFormBoundary())
			if len(.multipartFormBoundary) > 0 && len(.Header.peek(strContentEncoding)) == 0 {
				.multipartForm,  = readMultipartForm(, .multipartFormBoundary, , defaultMaxInMemoryFileSize)
				if  != nil {
					.Reset()
				}
				return 
			}
		}
	}

	if  == -2 {
		// identity body has no sense for http requests, since
		// the end of body is determined by connection close.
		// So just ignore request body for requests without
		// 'Content-Length' and 'Transfer-Encoding' headers.

		// refer to https://tools.ietf.org/html/rfc7230#section-3.3.2
		if !.Header.ignoreBody() {
			.Header.SetContentLength(0)
		}
		return nil
	}

	 := .bodyBuffer()
	.Reset()
	.B,  = readBodyWithStreaming(, , , .B)
	if  != nil {
		if  == ErrBodyTooLarge {
			.Header.SetContentLength()
			.body = 
			.bodyStream = acquireRequestStream(, , &.Header)
			return nil
		}
		if  == errChunkedStream {
			.body = 
			.bodyStream = acquireRequestStream(, , &.Header)
			return nil
		}
		.Reset()
		return 
	}

	.body = 
	.bodyStream = acquireRequestStream(, , &.Header)
	.Header.SetContentLength()
	return nil
}

// Read reads response (including body) from the given r.
//
// io.EOF is returned if r is closed before reading the first header byte.
func ( *Response) ( *bufio.Reader) error {
	return .ReadLimitBody(, 0)
}

// ReadLimitBody reads response headers from the given r,
// then reads the body using the ReadBody function and limiting the body size.
//
// If resp.SkipBody is true then it skips reading the response body.
//
// If maxBodySize > 0 and the body size exceeds maxBodySize,
// then ErrBodyTooLarge is returned.
//
// io.EOF is returned if r is closed before reading the first header byte.
func ( *Response) ( *bufio.Reader,  int) error {
	.resetSkipHeader()
	 := .Header.Read()
	if  != nil {
		return 
	}
	if .Header.StatusCode() == StatusContinue {
		// Read the next response according to http://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html .
		if  = .Header.Read();  != nil {
			return 
		}
	}

	if !.mustSkipBody() {
		 = .ReadBody(, )
		if  != nil {
			if isConnectionReset() {
				return nil
			}
			return 
		}
	}

	if .Header.ContentLength() == -1 && !.StreamBody {
		 = .Header.ReadTrailer()
		if  != nil &&  != io.EOF {
			if isConnectionReset() {
				return nil
			}
			return 
		}
	}
	return nil
}

// ReadBody reads response body from the given r, limiting the body size.
//
// If maxBodySize > 0 and the body size exceeds maxBodySize,
// then ErrBodyTooLarge is returned.
func ( *Response) ( *bufio.Reader,  int) ( error) {
	 := .bodyBuffer()
	.Reset()

	 := .Header.ContentLength()
	switch {
	case  >= 0:
		.B,  = readBody(, , , .B)
		if  == ErrBodyTooLarge && .StreamBody {
			.bodyStream = acquireRequestStream(, , &.Header)
			 = nil
		}
	case  == -1:
		if .StreamBody {
			.bodyStream = acquireRequestStream(, , &.Header)
		} else {
			.B,  = readBodyChunked(, , .B)
		}
	default:
		.B,  = readBodyIdentity(, , .B)
		.Header.SetContentLength(len(.B))
	}
	if  == nil && .StreamBody && .bodyStream == nil {
		.bodyStream = bytes.NewReader(.B)
	}
	return 
}

func ( *Response) () bool {
	return .SkipBody || .Header.mustSkipContentLength()
}

var errRequestHostRequired = errors.New("missing required Host header in request")

// WriteTo writes request to w. It implements io.WriterTo.
func ( *Request) ( io.Writer) (int64, error) {
	return writeBufio(, )
}

// WriteTo writes response to w. It implements io.WriterTo.
func ( *Response) ( io.Writer) (int64, error) {
	return writeBufio(, )
}

func writeBufio( httpWriter,  io.Writer) (int64, error) {
	 := acquireStatsWriter()
	 := acquireBufioWriter()
	 := .Write()
	 := .Flush()
	releaseBufioWriter()
	 := .bytesWritten
	releaseStatsWriter()

	 := 
	if  == nil {
		 = 
	}
	return , 
}

type statsWriter struct {
	w            io.Writer
	bytesWritten int64
}

func ( *statsWriter) ( []byte) (int, error) {
	,  := .w.Write()
	.bytesWritten += int64()
	return , 
}

func acquireStatsWriter( io.Writer) *statsWriter {
	 := statsWriterPool.Get()
	if  == nil {
		return &statsWriter{
			w: ,
		}
	}
	 := .(*statsWriter)
	.w = 
	return 
}

func releaseStatsWriter( *statsWriter) {
	.w = nil
	.bytesWritten = 0
	statsWriterPool.Put()
}

var statsWriterPool sync.Pool

func acquireBufioWriter( io.Writer) *bufio.Writer {
	 := bufioWriterPool.Get()
	if  == nil {
		return bufio.NewWriter()
	}
	 := .(*bufio.Writer)
	.Reset()
	return 
}

func releaseBufioWriter( *bufio.Writer) {
	bufioWriterPool.Put()
}

var bufioWriterPool sync.Pool

func ( *Request) () bool {
	return .multipartForm != nil && (.body == nil || len(.body.B) == 0)
}

// Write writes request to w.
//
// Write doesn't flush request to w for performance reasons.
//
// See also WriteTo.
func ( *Request) ( *bufio.Writer) error {
	if len(.Header.Host()) == 0 || .parsedURI {
		 := .URI()
		 := .Host()
		if len(.Header.Host()) == 0 {
			if len() == 0 {
				return errRequestHostRequired
			} else {
				.Header.SetHostBytes()
			}
		} else if !.UseHostHeader {
			.Header.SetHostBytes()
		}
		.Header.SetRequestURIBytes(.RequestURI())

		if len(.username) > 0 {
			// RequestHeader.SetBytesKV only uses RequestHeader.bufKV.key
			// So we are free to use RequestHeader.bufKV.value as a scratch pad for
			// the base64 encoding.
			 := len(.username) + len(.password) + 1
			 :=  + len(strBasicSpace)
			 :=  + base64.StdEncoding.EncodedLen()
			if  > cap(.Header.bufKV.value) {
				.Header.bufKV.value = make([]byte, 0, )
			}
			 := .Header.bufKV.value[:0]
			 = append(, .username...)
			 = append(, strColon...)
			 = append(, .password...)
			 = append(, strBasicSpace...)
			base64.StdEncoding.Encode([:], [:])
			.Header.SetBytesKV(strAuthorization, [:])
		}
	}

	if .bodyStream != nil {
		return .writeBodyStream()
	}

	 := .bodyBytes()
	var  error
	if .onlyMultipartForm() {
		,  = marshalMultipartForm(.multipartForm, .multipartFormBoundary)
		if  != nil {
			return fmt.Errorf("error when marshaling multipart form: %w", )
		}
		.Header.SetMultipartFormBoundary(.multipartFormBoundary)
	}

	 := false
	if len() == 0 {
		 = .postArgs.QueryString()
	}
	if len() != 0 || !.Header.ignoreBody() {
		 = true
		.Header.SetContentLength(len())
	}
	if  = .Header.Write();  != nil {
		return 
	}
	if  {
		_,  = .Write()
	} else if len() > 0 {
		if .secureErrorLogMessage {
			return fmt.Errorf("non-zero body for non-POST request")
		}
		return fmt.Errorf("non-zero body for non-POST request. body=%q", )
	}
	return 
}

// WriteGzip writes response with gzipped body to w.
//
// The method gzips response body and sets 'Content-Encoding: gzip'
// header before writing response to w.
//
// WriteGzip doesn't flush response to w for performance reasons.
func ( *Response) ( *bufio.Writer) error {
	return .WriteGzipLevel(, CompressDefaultCompression)
}

// WriteGzipLevel writes response with gzipped body to w.
//
// Level is the desired compression level:
//
//   - CompressNoCompression
//   - CompressBestSpeed
//   - CompressBestCompression
//   - CompressDefaultCompression
//   - CompressHuffmanOnly
//
// The method gzips response body and sets 'Content-Encoding: gzip'
// header before writing response to w.
//
// WriteGzipLevel doesn't flush response to w for performance reasons.
func ( *Response) ( *bufio.Writer,  int) error {
	if  := .gzipBody();  != nil {
		return 
	}
	return .Write()
}

// WriteDeflate writes response with deflated body to w.
//
// The method deflates response body and sets 'Content-Encoding: deflate'
// header before writing response to w.
//
// WriteDeflate doesn't flush response to w for performance reasons.
func ( *Response) ( *bufio.Writer) error {
	return .WriteDeflateLevel(, CompressDefaultCompression)
}

// WriteDeflateLevel writes response with deflated body to w.
//
// Level is the desired compression level:
//
//   - CompressNoCompression
//   - CompressBestSpeed
//   - CompressBestCompression
//   - CompressDefaultCompression
//   - CompressHuffmanOnly
//
// The method deflates response body and sets 'Content-Encoding: deflate'
// header before writing response to w.
//
// WriteDeflateLevel doesn't flush response to w for performance reasons.
func ( *Response) ( *bufio.Writer,  int) error {
	if  := .deflateBody();  != nil {
		return 
	}
	return .Write()
}

func ( *Response) ( int) error {
	if len(.Header.ContentEncoding()) > 0 {
		// It looks like the body is already compressed.
		// Do not compress it again.
		return nil
	}

	if !.Header.isCompressibleContentType() {
		// The content-type cannot be compressed.
		return nil
	}

	if .bodyStream != nil {
		// Reset Content-Length to -1, since it is impossible
		// to determine body size beforehand of streamed compression.
		// For https://github.com/valyala/fasthttp/issues/176 .
		.Header.SetContentLength(-1)

		// Do not care about memory allocations here, since brotli is slow
		// and allocates a lot of memory by itself.
		 := .bodyStream
		.bodyStream = NewStreamReader(func( *bufio.Writer) {
			 := acquireStacklessBrotliWriter(, )
			 := &flushWriter{
				wf: ,
				bw: ,
			}
			copyZeroAlloc(, ) //nolint:errcheck
			releaseStacklessBrotliWriter(, )
			if ,  := .(io.Closer);  {
				.Close()
			}
		})
	} else {
		 := .bodyBytes()
		if len() < minCompressLen {
			// There is no sense in spending CPU time on small body compression,
			// since there is a very high probability that the compressed
			// body size will be bigger than the original body size.
			return nil
		}
		 := responseBodyPool.Get()
		.B = AppendBrotliBytesLevel(.B, , )

		// Hack: swap resp.body with w.
		if .body != nil {
			responseBodyPool.Put(.body)
		}
		.body = 
		.bodyRaw = nil
	}
	.Header.SetContentEncodingBytes(strBr)
	.Header.addVaryBytes(strAcceptEncoding)
	return nil
}

func ( *Response) ( int) error {
	if len(.Header.ContentEncoding()) > 0 {
		// It looks like the body is already compressed.
		// Do not compress it again.
		return nil
	}

	if !.Header.isCompressibleContentType() {
		// The content-type cannot be compressed.
		return nil
	}

	if .bodyStream != nil {
		// Reset Content-Length to -1, since it is impossible
		// to determine body size beforehand of streamed compression.
		// For https://github.com/valyala/fasthttp/issues/176 .
		.Header.SetContentLength(-1)

		// Do not care about memory allocations here, since gzip is slow
		// and allocates a lot of memory by itself.
		 := .bodyStream
		.bodyStream = NewStreamReader(func( *bufio.Writer) {
			 := acquireStacklessGzipWriter(, )
			 := &flushWriter{
				wf: ,
				bw: ,
			}
			copyZeroAlloc(, ) //nolint:errcheck
			releaseStacklessGzipWriter(, )
			if ,  := .(io.Closer);  {
				.Close()
			}
		})
	} else {
		 := .bodyBytes()
		if len() < minCompressLen {
			// There is no sense in spending CPU time on small body compression,
			// since there is a very high probability that the compressed
			// body size will be bigger than the original body size.
			return nil
		}
		 := responseBodyPool.Get()
		.B = AppendGzipBytesLevel(.B, , )

		// Hack: swap resp.body with w.
		if .body != nil {
			responseBodyPool.Put(.body)
		}
		.body = 
		.bodyRaw = nil
	}
	.Header.SetContentEncodingBytes(strGzip)
	.Header.addVaryBytes(strAcceptEncoding)
	return nil
}

func ( *Response) ( int) error {
	if len(.Header.ContentEncoding()) > 0 {
		// It looks like the body is already compressed.
		// Do not compress it again.
		return nil
	}

	if !.Header.isCompressibleContentType() {
		// The content-type cannot be compressed.
		return nil
	}

	if .bodyStream != nil {
		// Reset Content-Length to -1, since it is impossible
		// to determine body size beforehand of streamed compression.
		// For https://github.com/valyala/fasthttp/issues/176 .
		.Header.SetContentLength(-1)

		// Do not care about memory allocations here, since flate is slow
		// and allocates a lot of memory by itself.
		 := .bodyStream
		.bodyStream = NewStreamReader(func( *bufio.Writer) {
			 := acquireStacklessDeflateWriter(, )
			 := &flushWriter{
				wf: ,
				bw: ,
			}
			copyZeroAlloc(, ) //nolint:errcheck
			releaseStacklessDeflateWriter(, )
			if ,  := .(io.Closer);  {
				.Close()
			}
		})
	} else {
		 := .bodyBytes()
		if len() < minCompressLen {
			// There is no sense in spending CPU time on small body compression,
			// since there is a very high probability that the compressed
			// body size will be bigger than the original body size.
			return nil
		}
		 := responseBodyPool.Get()
		.B = AppendDeflateBytesLevel(.B, , )

		// Hack: swap resp.body with w.
		if .body != nil {
			responseBodyPool.Put(.body)
		}
		.body = 
		.bodyRaw = nil
	}
	.Header.SetContentEncodingBytes(strDeflate)
	.Header.addVaryBytes(strAcceptEncoding)
	return nil
}

// Bodies with sizes smaller than minCompressLen aren't compressed at all
const minCompressLen = 200

type writeFlusher interface {
	io.Writer
	Flush() error
}

type flushWriter struct {
	wf writeFlusher
	bw *bufio.Writer
}

func ( *flushWriter) ( []byte) (int, error) {
	,  := .wf.Write()
	if  != nil {
		return 0, 
	}
	if  = .wf.Flush();  != nil {
		return 0, 
	}
	if  = .bw.Flush();  != nil {
		return 0, 
	}
	return , nil
}

// Write writes response to w.
//
// Write doesn't flush response to w for performance reasons.
//
// See also WriteTo.
func ( *Response) ( *bufio.Writer) error {
	 := !.mustSkipBody()

	if .bodyStream != nil {
		return .writeBodyStream(, )
	}

	 := .bodyBytes()
	 := len()
	if  ||  > 0 {
		.Header.SetContentLength()
	}
	if  := .Header.Write();  != nil {
		return 
	}
	if  {
		if ,  := .Write();  != nil {
			return 
		}
	}
	return nil
}

func ( *Request) ( *bufio.Writer) error {
	var  error

	 := .Header.ContentLength()
	if  < 0 {
		 := limitedReaderSize(.bodyStream)
		if  >= 0 {
			 = int()
			if int64() !=  {
				 = -1
			}
			if  >= 0 {
				.Header.SetContentLength()
			}
		}
	}
	if  >= 0 {
		if  = .Header.Write();  == nil {
			 = writeBodyFixedSize(, .bodyStream, int64())
		}
	} else {
		.Header.SetContentLength(-1)
		 = .Header.Write()
		if  == nil {
			 = writeBodyChunked(, .bodyStream)
		}
		if  == nil {
			 = .Header.writeTrailer()
		}
	}
	 := .closeBodyStream()
	if  == nil {
		 = 
	}
	return 
}

// ErrBodyStreamWritePanic is returned when panic happens during writing body stream.
type ErrBodyStreamWritePanic struct {
	error
}

func ( *Response) ( *bufio.Writer,  bool) ( error) {
	defer func() {
		if  := recover();  != nil {
			 = &ErrBodyStreamWritePanic{
				error: fmt.Errorf("panic while writing body stream: %+v", ),
			}
		}
	}()

	 := .Header.ContentLength()
	if  < 0 {
		 := limitedReaderSize(.bodyStream)
		if  >= 0 {
			 = int()
			if int64() !=  {
				 = -1
			}
			if  >= 0 {
				.Header.SetContentLength()
			}
		}
	}
	if  >= 0 {
		if  = .Header.Write();  == nil {
			if .ImmediateHeaderFlush {
				 = .Flush()
			}
			if  == nil &&  {
				 = writeBodyFixedSize(, .bodyStream, int64())
			}
		}
	} else {
		.Header.SetContentLength(-1)
		if  = .Header.Write();  == nil {
			if .ImmediateHeaderFlush {
				 = .Flush()
			}
			if  == nil &&  {
				 = writeBodyChunked(, .bodyStream)
			}
			if  == nil {
				 = .Header.writeTrailer()
			}
		}
	}
	 := .closeBodyStream()
	if  == nil {
		 = 
	}
	return 
}

func ( *Request) () error {
	if .bodyStream == nil {
		return nil
	}
	var  error
	if ,  := .bodyStream.(io.Closer);  {
		 = .Close()
	}
	if ,  := .bodyStream.(*requestStream);  {
		releaseRequestStream()
	}
	.bodyStream = nil
	return 
}

func ( *Response) () error {
	if .bodyStream == nil {
		return nil
	}
	var  error
	if ,  := .bodyStream.(io.Closer);  {
		 = .Close()
	}
	if ,  := .bodyStream.(*requestStream);  {
		releaseRequestStream()
	}
	.bodyStream = nil
	return 
}

// String returns request representation.
//
// Returns error message instead of request representation on error.
//
// Use Write instead of String for performance-critical code.
func ( *Request) () string {
	return getHTTPString()
}

// String returns response representation.
//
// Returns error message instead of response representation on error.
//
// Use Write instead of String for performance-critical code.
func ( *Response) () string {
	return getHTTPString()
}

func getHTTPString( httpWriter) string {
	 := bytebufferpool.Get()
	defer bytebufferpool.Put()

	 := bufio.NewWriter()
	if  := .Write();  != nil {
		return .Error()
	}
	if  := .Flush();  != nil {
		return .Error()
	}
	 := string(.B)
	return 
}

type httpWriter interface {
	Write(w *bufio.Writer) error
}

func writeBodyChunked( *bufio.Writer,  io.Reader) error {
	 := copyBufPool.Get()
	 := .([]byte)

	var  error
	var  int
	for {
		,  = .Read()
		if  == 0 {
			if  == nil {
				continue
			}
			if  == io.EOF {
				if  = writeChunk(, [:0]);  != nil {
					break
				}
				 = nil
			}
			break
		}
		if  = writeChunk(, [:]);  != nil {
			break
		}
	}

	copyBufPool.Put()
	return 
}

func limitedReaderSize( io.Reader) int64 {
	,  := .(*io.LimitedReader)
	if ! {
		return -1
	}
	return .N
}

func writeBodyFixedSize( *bufio.Writer,  io.Reader,  int64) error {
	if  > maxSmallFileSize {
		// w buffer must be empty for triggering
		// sendfile path in bufio.Writer.ReadFrom.
		if  := .Flush();  != nil {
			return 
		}
	}

	,  := copyZeroAlloc(, )

	if  !=  &&  == nil {
		 = fmt.Errorf("copied %d bytes from body stream instead of %d bytes", , )
	}
	return 
}

func copyZeroAlloc( io.Writer,  io.Reader) (int64, error) {
	 := copyBufPool.Get()
	 := .([]byte)
	,  := io.CopyBuffer(, , )
	copyBufPool.Put()
	return , 
}

var copyBufPool = sync.Pool{
	New: func() interface{} {
		return make([]byte, 4096)
	},
}

func writeChunk( *bufio.Writer,  []byte) error {
	 := len()
	if  := writeHexInt(, );  != nil {
		return 
	}
	if ,  := .Write(strCRLF);  != nil {
		return 
	}
	if ,  := .Write();  != nil {
		return 
	}
	// If is end chunk, write CRLF after writing trailer
	if  > 0 {
		if ,  := .Write(strCRLF);  != nil {
			return 
		}
	}
	return .Flush()
}

// ErrBodyTooLarge is returned if either request or response body exceeds
// the given limit.
var ErrBodyTooLarge = errors.New("body size exceeds the given limit")

func readBody( *bufio.Reader,  int,  int,  []byte) ([]byte, error) {
	if  > 0 &&  >  {
		return , ErrBodyTooLarge
	}
	return appendBodyFixedSize(, , )
}

var errChunkedStream = errors.New("chunked stream")

func readBodyWithStreaming( *bufio.Reader,  int,  int,  []byte) ( []byte,  error) {
	if  == -1 {
		// handled in requestStream.Read()
		return , errChunkedStream
	}

	 = [:0]

	 := 
	if  >  {
		 = 
	}
	if  > 8*1024 {
		 = 8 * 1024
	}

	if  >= 0 &&  >=  {
		,  = appendBodyFixedSize(, , )
	} else {
		,  = readBodyIdentity(, , )
	}

	if  != nil {
		return , 
	}
	if  >  {
		return , ErrBodyTooLarge
	}
	return , nil
}

func readBodyIdentity( *bufio.Reader,  int,  []byte) ([]byte, error) {
	 = [:cap()]
	if len() == 0 {
		 = make([]byte, 1024)
	}
	 := 0
	for {
		,  := .Read([:])
		if  <= 0 {
			switch {
			case errors.Is(, io.EOF):
				return [:], nil
			case  != nil:
				return [:], 
			default:
				return [:], fmt.Errorf("bufio.Read() returned (%d, nil)", )
			}
		}
		 += 
		if  > 0 &&  >  {
			return [:], ErrBodyTooLarge
		}
		if len() ==  {
			 := roundUpForSliceCap(2 * )
			if  > 0 &&  >  {
				 =  + 1
			}
			 := make([]byte, )
			copy(, )
			 = 
		}
	}
}

func appendBodyFixedSize( *bufio.Reader,  []byte,  int) ([]byte, error) {
	if  == 0 {
		return , nil
	}

	 := len()
	 :=  + 
	if cap() <  {
		 := make([]byte, roundUpForSliceCap())
		copy(, )
		 = 
	}
	 = [:]

	for {
		,  := .Read([:])
		if  <= 0 {
			switch {
			case errors.Is(, io.EOF):
				return [:], io.ErrUnexpectedEOF
			case  != nil:
				return [:], 
			default:
				return [:], fmt.Errorf("bufio.Read() returned (%d, nil)", )
			}
		}
		 += 
		if  ==  {
			return , nil
		}
	}
}

// ErrBrokenChunk is returned when server receives a broken chunked body (Transfer-Encoding: chunked).
type ErrBrokenChunk struct {
	error
}

func readBodyChunked( *bufio.Reader,  int,  []byte) ([]byte, error) {
	if len() > 0 {
		// data integrity might be in danger. No idea what we received,
		// but nothing we should write to.
		panic("BUG: expected zero-length buffer")
	}

	 := len(strCRLF)
	for {
		,  := parseChunkSize()
		if  != nil {
			return , 
		}
		if  == 0 {
			return , 
		}
		if  > 0 && len()+ >  {
			return , ErrBodyTooLarge
		}
		,  = appendBodyFixedSize(, , +)
		if  != nil {
			return , 
		}
		if !bytes.Equal([len()-:], strCRLF) {
			return , ErrBrokenChunk{
				error: fmt.Errorf("cannot find crlf at the end of chunk"),
			}
		}
		 = [:len()-]
	}
}

func parseChunkSize( *bufio.Reader) (int, error) {
	,  := readHexInt()
	if  != nil {
		return -1, 
	}
	for {
		,  := .ReadByte()
		if  != nil {
			return -1, ErrBrokenChunk{
				error: fmt.Errorf("cannot read '\r' char at the end of chunk size: %w", ),
			}
		}
		// Skip chunk extension after chunk size.
		// Add support later if anyone needs it.
		if  != '\r' {
			continue
		}
		if  := .UnreadByte();  != nil {
			return -1, ErrBrokenChunk{
				error: fmt.Errorf("cannot unread '\r' char at the end of chunk size: %w", ),
			}
		}
		break
	}
	 = readCrLf()
	if  != nil {
		return -1, 
	}
	return , nil
}

func readCrLf( *bufio.Reader) error {
	for ,  := range []byte{'\r', '\n'} {
		,  := .ReadByte()
		if  != nil {
			return ErrBrokenChunk{
				error: fmt.Errorf("cannot read %q char at the end of chunk size: %w", , ),
			}
		}
		if  !=  {
			return ErrBrokenChunk{
				error: fmt.Errorf("unexpected char %q at the end of chunk size. Expected %q", , ),
			}
		}
	}
	return nil
}

// SetTimeout sets timeout for the request.
//
// req.SetTimeout(t); c.Do(&req, &resp) is equivalent to
// c.DoTimeout(&req, &resp, t)
func ( *Request) ( time.Duration) {
	.timeout = 
}