package fasthttp

import (
	
	
	
	
	
	
	
	
)

const (
	rChar = byte('\r')
	nChar = byte('\n')
)

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

	disableNormalizing   bool
	noHTTP11             bool
	connectionClose      bool
	noDefaultContentType bool
	noDefaultDate        bool

	statusCode            int
	statusMessage         []byte
	protocol              []byte
	contentLength         int
	contentLengthBytes    []byte
	secureErrorLogMessage bool

	contentType     []byte
	contentEncoding []byte
	server          []byte
	mulHeader       [][]byte

	h       []argsKV
	trailer []argsKV
	bufKV   argsKV

	cookies []argsKV
}

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

	disableNormalizing   bool
	noHTTP11             bool
	connectionClose      bool
	noDefaultContentType bool
	disableSpecialHeader bool

	// These two fields have been moved close to other bool fields
	// for reducing RequestHeader object size.
	cookiesCollected bool

	contentLength         int
	contentLengthBytes    []byte
	secureErrorLogMessage bool

	method      []byte
	requestURI  []byte
	proto       []byte
	host        []byte
	contentType []byte
	userAgent   []byte
	mulHeader   [][]byte

	h       []argsKV
	trailer []argsKV
	bufKV   argsKV

	cookies []argsKV

	// stores an immutable copy of headers as they were received from the
	// wire.
	rawHeaders []byte
}

// SetContentRange sets 'Content-Range: bytes startPos-endPos/contentLength'
// header.
func ( *ResponseHeader) (, ,  int) {
	 := .bufKV.value[:0]
	 = append(, strBytes...)
	 = append(, ' ')
	 = AppendUint(, )
	 = append(, '-')
	 = AppendUint(, )
	 = append(, '/')
	 = AppendUint(, )
	.bufKV.value = 

	.setNonSpecial(strContentRange, .bufKV.value)
}

// SetByteRange sets 'Range: bytes=startPos-endPos' header.
//
//   - If startPos is negative, then 'bytes=-startPos' value is set.
//   - If endPos is negative, then 'bytes=startPos-' value is set.
func ( *RequestHeader) (,  int) {
	 := .bufKV.value[:0]
	 = append(, strBytes...)
	 = append(, '=')
	if  >= 0 {
		 = AppendUint(, )
	} else {
		 = -
	}
	 = append(, '-')
	if  >= 0 {
		 = AppendUint(, )
	}
	.bufKV.value = 

	.setNonSpecial(strRange, .bufKV.value)
}

// StatusCode returns response status code.
func ( *ResponseHeader) () int {
	if .statusCode == 0 {
		return StatusOK
	}
	return .statusCode
}

// SetStatusCode sets response status code.
func ( *ResponseHeader) ( int) {
	.statusCode = 
}

// StatusMessage returns response status message.
func ( *ResponseHeader) () []byte {
	return .statusMessage
}

// SetStatusMessage sets response status message bytes.
func ( *ResponseHeader) ( []byte) {
	.statusMessage = append(.statusMessage[:0], ...)
}

// Protocol returns response protocol bytes.
func ( *ResponseHeader) () []byte {
	if len(.protocol) > 0 {
		return .protocol
	}
	return strHTTP11
}

// SetProtocol sets response protocol bytes.
func ( *ResponseHeader) ( []byte) {
	.protocol = append(.protocol[:0], ...)
}

// SetLastModified sets 'Last-Modified' header to the given value.
func ( *ResponseHeader) ( time.Time) {
	.bufKV.value = AppendHTTPDate(.bufKV.value[:0], )
	.setNonSpecial(strLastModified, .bufKV.value)
}

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

// SetConnectionClose sets 'Connection: close' header.
func ( *ResponseHeader) () {
	.connectionClose = true
}

// ResetConnectionClose clears 'Connection: close' header if it exists.
func ( *ResponseHeader) () {
	if .connectionClose {
		.connectionClose = false
		.h = delAllArgsBytes(.h, strConnection)
	}
}

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

// SetConnectionClose sets 'Connection: close' header.
func ( *RequestHeader) () {
	.connectionClose = true
}

// ResetConnectionClose clears 'Connection: close' header if it exists.
func ( *RequestHeader) () {
	if .connectionClose {
		.connectionClose = false
		.h = delAllArgsBytes(.h, strConnection)
	}
}

// ConnectionUpgrade returns true if 'Connection: Upgrade' header is set.
func ( *ResponseHeader) () bool {
	return hasHeaderValue(.Peek(HeaderConnection), strUpgrade)
}

// ConnectionUpgrade returns true if 'Connection: Upgrade' header is set.
func ( *RequestHeader) () bool {
	return hasHeaderValue(.Peek(HeaderConnection), strUpgrade)
}

// PeekCookie is able to returns cookie by a given key from response.
func ( *ResponseHeader) ( string) []byte {
	return peekArgStr(.cookies, )
}

// ContentLength returns Content-Length header value.
//
// It may be negative:
// -1 means Transfer-Encoding: chunked.
// -2 means Transfer-Encoding: identity.
func ( *ResponseHeader) () int {
	return .contentLength
}

// SetContentLength sets Content-Length header value.
//
// Content-Length may be negative:
// -1 means Transfer-Encoding: chunked.
// -2 means Transfer-Encoding: identity.
func ( *ResponseHeader) ( int) {
	if .mustSkipContentLength() {
		return
	}
	.contentLength = 
	if  >= 0 {
		.contentLengthBytes = AppendUint(.contentLengthBytes[:0], )
		.h = delAllArgsBytes(.h, strTransferEncoding)
	} else {
		.contentLengthBytes = .contentLengthBytes[:0]
		 := strChunked
		if  == -2 {
			.SetConnectionClose()
			 = strIdentity
		}
		.h = setArgBytes(.h, strTransferEncoding, , argsHasValue)
	}
}

func ( *ResponseHeader) () bool {
	// From http/1.1 specs:
	// All 1xx (informational), 204 (no content), and 304 (not modified) responses MUST NOT include a message-body
	 := .StatusCode()

	// Fast path.
	if  < 100 ||  == StatusOK {
		return false
	}

	// Slow path.
	return  == StatusNotModified ||  == StatusNoContent ||  < 200
}

// ContentLength returns Content-Length header value.
//
// It may be negative:
// -1 means Transfer-Encoding: chunked.
func ( *RequestHeader) () int {
	return .realContentLength()
}

// realContentLength returns the actual Content-Length set in the request,
// including positive lengths for GET/HEAD requests.
func ( *RequestHeader) () int {
	return .contentLength
}

// SetContentLength sets Content-Length header value.
//
// Negative content-length sets 'Transfer-Encoding: chunked' header.
func ( *RequestHeader) ( int) {
	.contentLength = 
	if  >= 0 {
		.contentLengthBytes = AppendUint(.contentLengthBytes[:0], )
		.h = delAllArgsBytes(.h, strTransferEncoding)
	} else {
		.contentLengthBytes = .contentLengthBytes[:0]
		.h = setArgBytes(.h, strTransferEncoding, strChunked, argsHasValue)
	}
}

func ( *ResponseHeader) () bool {
	 := .ContentType()
	return bytes.HasPrefix(, strTextSlash) ||
		bytes.HasPrefix(, strApplicationSlash) ||
		bytes.HasPrefix(, strImageSVG) ||
		bytes.HasPrefix(, strImageIcon) ||
		bytes.HasPrefix(, strFontSlash) ||
		bytes.HasPrefix(, strMultipartSlash)
}

// ContentType returns Content-Type header value.
func ( *ResponseHeader) () []byte {
	 := .contentType
	if !.noDefaultContentType && len(.contentType) == 0 {
		 = defaultContentType
	}
	return 
}

// SetContentType sets Content-Type header value.
func ( *ResponseHeader) ( string) {
	.contentType = append(.contentType[:0], ...)
}

// SetContentTypeBytes sets Content-Type header value.
func ( *ResponseHeader) ( []byte) {
	.contentType = append(.contentType[:0], ...)
}

// ContentEncoding returns Content-Encoding header value.
func ( *ResponseHeader) () []byte {
	return .contentEncoding
}

// SetContentEncoding sets Content-Encoding header value.
func ( *ResponseHeader) ( string) {
	.contentEncoding = append(.contentEncoding[:0], ...)
}

// SetContentEncodingBytes sets Content-Encoding header value.
func ( *ResponseHeader) ( []byte) {
	.contentEncoding = append(.contentEncoding[:0], ...)
}

// addVaryBytes add value to the 'Vary' header if it's not included
func ( *ResponseHeader) ( []byte) {
	 := .peek(strVary)
	if len() == 0 {
		// 'Vary' is not set
		.SetBytesV(HeaderVary, )
	} else if !bytes.Contains(, ) {
		// 'Vary' is set and not contains target value
		.SetBytesV(HeaderVary, append(append(, ','), ...))
	} // else: 'Vary' is set and contains target value
}

// Server returns Server header value.
func ( *ResponseHeader) () []byte {
	return .server
}

// SetServer sets Server header value.
func ( *ResponseHeader) ( string) {
	.server = append(.server[:0], ...)
}

// SetServerBytes sets Server header value.
func ( *ResponseHeader) ( []byte) {
	.server = append(.server[:0], ...)
}

// ContentType returns Content-Type header value.
func ( *RequestHeader) () []byte {
	if .disableSpecialHeader {
		return peekArgBytes(.h, []byte(HeaderContentType))
	}
	return .contentType
}

// SetContentType sets Content-Type header value.
func ( *RequestHeader) ( string) {
	.contentType = append(.contentType[:0], ...)
}

// SetContentTypeBytes sets Content-Type header value.
func ( *RequestHeader) ( []byte) {
	.contentType = append(.contentType[:0], ...)
}

// ContentEncoding returns Content-Encoding header value.
func ( *RequestHeader) () []byte {
	return peekArgBytes(.h, strContentEncoding)
}

// SetContentEncoding sets Content-Encoding header value.
func ( *RequestHeader) ( string) {
	.SetBytesK(strContentEncoding, )
}

// SetContentEncodingBytes sets Content-Encoding header value.
func ( *RequestHeader) ( []byte) {
	.setNonSpecial(strContentEncoding, )
}

// SetMultipartFormBoundary sets the following Content-Type:
// 'multipart/form-data; boundary=...'
// where ... is substituted by the given boundary.
func ( *RequestHeader) ( string) {
	 := .bufKV.value[:0]
	 = append(, strMultipartFormData...)
	 = append(, ';', ' ')
	 = append(, strBoundary...)
	 = append(, '=')
	 = append(, ...)
	.bufKV.value = 

	.SetContentTypeBytes(.bufKV.value)
}

// SetMultipartFormBoundaryBytes sets the following Content-Type:
// 'multipart/form-data; boundary=...'
// where ... is substituted by the given boundary.
func ( *RequestHeader) ( []byte) {
	 := .bufKV.value[:0]
	 = append(, strMultipartFormData...)
	 = append(, ';', ' ')
	 = append(, strBoundary...)
	 = append(, '=')
	 = append(, ...)
	.bufKV.value = 

	.SetContentTypeBytes(.bufKV.value)
}

// SetTrailer sets header Trailer value for chunked response
// to indicate which headers will be sent after the body.
//
// Use Set to set the trailer header later.
//
// Trailers are only supported with chunked transfer.
// Trailers allow the sender to include additional headers at the end of chunked messages.
//
// The following trailers are forbidden:
// 1. necessary for message framing (e.g., Transfer-Encoding and Content-Length),
// 2. routing (e.g., Host),
// 3. request modifiers (e.g., controls and conditionals in Section 5 of [RFC7231]),
// 4. authentication (e.g., see [RFC7235] and [RFC6265]),
// 5. response control data (e.g., see Section 7.1 of [RFC7231]),
// 6. determining how to process the payload (e.g., Content-Encoding, Content-Type, Content-Range, and Trailer)
//
// Return ErrBadTrailer if contain any forbidden trailers.
func ( *ResponseHeader) ( string) error {
	return .SetTrailerBytes(s2b())
}

// SetTrailerBytes sets Trailer header value for chunked response
// to indicate which headers will be sent after the body.
//
// Use Set to set the trailer header later.
//
// Trailers are only supported with chunked transfer.
// Trailers allow the sender to include additional headers at the end of chunked messages.
//
// The following trailers are forbidden:
// 1. necessary for message framing (e.g., Transfer-Encoding and Content-Length),
// 2. routing (e.g., Host),
// 3. request modifiers (e.g., controls and conditionals in Section 5 of [RFC7231]),
// 4. authentication (e.g., see [RFC7235] and [RFC6265]),
// 5. response control data (e.g., see Section 7.1 of [RFC7231]),
// 6. determining how to process the payload (e.g., Content-Encoding, Content-Type, Content-Range, and Trailer)
//
// Return ErrBadTrailer if contain any forbidden trailers.
func ( *ResponseHeader) ( []byte) error {
	.trailer = .trailer[:0]
	return .AddTrailerBytes()
}

// AddTrailer add Trailer header value for chunked response
// to indicate which headers will be sent after the body.
//
// Use Set to set the trailer header later.
//
// Trailers are only supported with chunked transfer.
// Trailers allow the sender to include additional headers at the end of chunked messages.
//
// The following trailers are forbidden:
// 1. necessary for message framing (e.g., Transfer-Encoding and Content-Length),
// 2. routing (e.g., Host),
// 3. request modifiers (e.g., controls and conditionals in Section 5 of [RFC7231]),
// 4. authentication (e.g., see [RFC7235] and [RFC6265]),
// 5. response control data (e.g., see Section 7.1 of [RFC7231]),
// 6. determining how to process the payload (e.g., Content-Encoding, Content-Type, Content-Range, and Trailer)
//
// Return ErrBadTrailer if contain any forbidden trailers.
func ( *ResponseHeader) ( string) error {
	return .AddTrailerBytes(s2b())
}

var ErrBadTrailer = errors.New("contain forbidden trailer")

// AddTrailerBytes add Trailer header value for chunked response
// to indicate which headers will be sent after the body.
//
// Use Set to set the trailer header later.
//
// Trailers are only supported with chunked transfer.
// Trailers allow the sender to include additional headers at the end of chunked messages.
//
// The following trailers are forbidden:
// 1. necessary for message framing (e.g., Transfer-Encoding and Content-Length),
// 2. routing (e.g., Host),
// 3. request modifiers (e.g., controls and conditionals in Section 5 of [RFC7231]),
// 4. authentication (e.g., see [RFC7235] and [RFC6265]),
// 5. response control data (e.g., see Section 7.1 of [RFC7231]),
// 6. determining how to process the payload (e.g., Content-Encoding, Content-Type, Content-Range, and Trailer)
//
// Return ErrBadTrailer if contain any forbidden trailers.
func ( *ResponseHeader) ( []byte) error {
	var  error
	for  := -1; +1 < len(); {
		 = [+1:]
		 = bytes.IndexByte(, ',')
		if  < 0 {
			 = len()
		}
		 := [:]
		for len() > 0 && [0] == ' ' {
			 = [1:]
		}
		for len() > 0 && [len()-1] == ' ' {
			 = [:len()-1]
		}
		// Forbidden by RFC 7230, section 4.1.2
		if isBadTrailer() {
			 = ErrBadTrailer
			continue
		}
		.bufKV.key = append(.bufKV.key[:0], ...)
		normalizeHeaderKey(.bufKV.key, .disableNormalizing)
		.trailer = appendArgBytes(.trailer, .bufKV.key, nil, argsNoValue)
	}

	return 
}

// MultipartFormBoundary returns boundary part
// from 'multipart/form-data; boundary=...' Content-Type.
func ( *RequestHeader) () []byte {
	 := .ContentType()
	if !bytes.HasPrefix(, strMultipartFormData) {
		return nil
	}
	 = [len(strMultipartFormData):]
	if len() == 0 || [0] != ';' {
		return nil
	}

	var  int
	for len() > 0 {
		++
		for len() >  && [] == ' ' {
			++
		}
		 = [:]
		if !bytes.HasPrefix(, strBoundary) {
			if  = bytes.IndexByte(, ';');  < 0 {
				return nil
			}
			continue
		}

		 = [len(strBoundary):]
		if len() == 0 || [0] != '=' {
			return nil
		}
		 = [1:]
		if  = bytes.IndexByte(, ';');  >= 0 {
			 = [:]
		}
		if len() > 1 && [0] == '"' && [len()-1] == '"' {
			 = [1 : len()-1]
		}
		return 
	}
	return nil
}

// Host returns Host header value.
func ( *RequestHeader) () []byte {
	if .disableSpecialHeader {
		return peekArgBytes(.h, []byte(HeaderHost))
	}
	return .host
}

// SetHost sets Host header value.
func ( *RequestHeader) ( string) {
	.host = append(.host[:0], ...)
}

// SetHostBytes sets Host header value.
func ( *RequestHeader) ( []byte) {
	.host = append(.host[:0], ...)
}

// UserAgent returns User-Agent header value.
func ( *RequestHeader) () []byte {
	if .disableSpecialHeader {
		return peekArgBytes(.h, []byte(HeaderUserAgent))
	}
	return .userAgent
}

// SetUserAgent sets User-Agent header value.
func ( *RequestHeader) ( string) {
	.userAgent = append(.userAgent[:0], ...)
}

// SetUserAgentBytes sets User-Agent header value.
func ( *RequestHeader) ( []byte) {
	.userAgent = append(.userAgent[:0], ...)
}

// Referer returns Referer header value.
func ( *RequestHeader) () []byte {
	return peekArgBytes(.h, strReferer)
}

// SetReferer sets Referer header value.
func ( *RequestHeader) ( string) {
	.SetBytesK(strReferer, )
}

// SetRefererBytes sets Referer header value.
func ( *RequestHeader) ( []byte) {
	.setNonSpecial(strReferer, )
}

// Method returns HTTP request method.
func ( *RequestHeader) () []byte {
	if len(.method) == 0 {
		return []byte(MethodGet)
	}
	return .method
}

// SetMethod sets HTTP request method.
func ( *RequestHeader) ( string) {
	.method = append(.method[:0], ...)
}

// SetMethodBytes sets HTTP request method.
func ( *RequestHeader) ( []byte) {
	.method = append(.method[:0], ...)
}

// Protocol returns HTTP protocol.
func ( *RequestHeader) () []byte {
	if len(.proto) == 0 {
		return strHTTP11
	}
	return .proto
}

// SetProtocol sets HTTP request protocol.
func ( *RequestHeader) ( string) {
	.proto = append(.proto[:0], ...)
	.noHTTP11 = !bytes.Equal(.proto, strHTTP11)
}

// SetProtocolBytes sets HTTP request protocol.
func ( *RequestHeader) ( []byte) {
	.proto = append(.proto[:0], ...)
	.noHTTP11 = !bytes.Equal(.proto, strHTTP11)
}

// RequestURI returns RequestURI from the first HTTP request line.
func ( *RequestHeader) () []byte {
	 := .requestURI
	if len() == 0 {
		 = strSlash
	}
	return 
}

// SetRequestURI sets RequestURI for the first HTTP request line.
// RequestURI must be properly encoded.
// Use URI.RequestURI for constructing proper RequestURI if unsure.
func ( *RequestHeader) ( string) {
	.requestURI = append(.requestURI[:0], ...)
}

// SetRequestURIBytes sets RequestURI for the first HTTP request line.
// RequestURI must be properly encoded.
// Use URI.RequestURI for constructing proper RequestURI if unsure.
func ( *RequestHeader) ( []byte) {
	.requestURI = append(.requestURI[:0], ...)
}

// SetTrailer sets Trailer header value for chunked request
// to indicate which headers will be sent after the body.
//
// Use Set to set the trailer header later.
//
// Trailers are only supported with chunked transfer.
// Trailers allow the sender to include additional headers at the end of chunked messages.
//
// The following trailers are forbidden:
// 1. necessary for message framing (e.g., Transfer-Encoding and Content-Length),
// 2. routing (e.g., Host),
// 3. request modifiers (e.g., controls and conditionals in Section 5 of [RFC7231]),
// 4. authentication (e.g., see [RFC7235] and [RFC6265]),
// 5. response control data (e.g., see Section 7.1 of [RFC7231]),
// 6. determining how to process the payload (e.g., Content-Encoding, Content-Type, Content-Range, and Trailer)
//
// Return ErrBadTrailer if contain any forbidden trailers.
func ( *RequestHeader) ( string) error {
	return .SetTrailerBytes(s2b())
}

// SetTrailerBytes sets Trailer header value for chunked request
// to indicate which headers will be sent after the body.
//
// Use Set to set the trailer header later.
//
// Trailers are only supported with chunked transfer.
// Trailers allow the sender to include additional headers at the end of chunked messages.
//
// The following trailers are forbidden:
// 1. necessary for message framing (e.g., Transfer-Encoding and Content-Length),
// 2. routing (e.g., Host),
// 3. request modifiers (e.g., controls and conditionals in Section 5 of [RFC7231]),
// 4. authentication (e.g., see [RFC7235] and [RFC6265]),
// 5. response control data (e.g., see Section 7.1 of [RFC7231]),
// 6. determining how to process the payload (e.g., Content-Encoding, Content-Type, Content-Range, and Trailer)
//
// Return ErrBadTrailer if contain any forbidden trailers.
func ( *RequestHeader) ( []byte) error {
	.trailer = .trailer[:0]
	return .AddTrailerBytes()
}

// AddTrailer add Trailer header value for chunked request
// to indicate which headers will be sent after the body.
//
// Use Set to set the trailer header later.
//
// Trailers are only supported with chunked transfer.
// Trailers allow the sender to include additional headers at the end of chunked messages.
//
// The following trailers are forbidden:
// 1. necessary for message framing (e.g., Transfer-Encoding and Content-Length),
// 2. routing (e.g., Host),
// 3. request modifiers (e.g., controls and conditionals in Section 5 of [RFC7231]),
// 4. authentication (e.g., see [RFC7235] and [RFC6265]),
// 5. response control data (e.g., see Section 7.1 of [RFC7231]),
// 6. determining how to process the payload (e.g., Content-Encoding, Content-Type, Content-Range, and Trailer)
//
// Return ErrBadTrailer if contain any forbidden trailers.
func ( *RequestHeader) ( string) error {
	return .AddTrailerBytes(s2b())
}

// AddTrailerBytes add Trailer header value for chunked request
// to indicate which headers will be sent after the body.
//
// Use Set to set the trailer header later.
//
// Trailers are only supported with chunked transfer.
// Trailers allow the sender to include additional headers at the end of chunked messages.
//
// The following trailers are forbidden:
// 1. necessary for message framing (e.g., Transfer-Encoding and Content-Length),
// 2. routing (e.g., Host),
// 3. request modifiers (e.g., controls and conditionals in Section 5 of [RFC7231]),
// 4. authentication (e.g., see [RFC7235] and [RFC6265]),
// 5. response control data (e.g., see Section 7.1 of [RFC7231]),
// 6. determining how to process the payload (e.g., Content-Encoding, Content-Type, Content-Range, and Trailer)
//
// Return ErrBadTrailer if contain any forbidden trailers.
func ( *RequestHeader) ( []byte) error {
	var  error
	for  := -1; +1 < len(); {
		 = [+1:]
		 = bytes.IndexByte(, ',')
		if  < 0 {
			 = len()
		}
		 := [:]
		for len() > 0 && [0] == ' ' {
			 = [1:]
		}
		for len() > 0 && [len()-1] == ' ' {
			 = [:len()-1]
		}
		// Forbidden by RFC 7230, section 4.1.2
		if isBadTrailer() {
			 = ErrBadTrailer
			continue
		}
		.bufKV.key = append(.bufKV.key[:0], ...)
		normalizeHeaderKey(.bufKV.key, .disableNormalizing)
		.trailer = appendArgBytes(.trailer, .bufKV.key, nil, argsNoValue)
	}

	return 
}

// IsGet returns true if request method is GET.
func ( *RequestHeader) () bool {
	return string(.Method()) == MethodGet
}

// IsPost returns true if request method is POST.
func ( *RequestHeader) () bool {
	return string(.Method()) == MethodPost
}

// IsPut returns true if request method is PUT.
func ( *RequestHeader) () bool {
	return string(.Method()) == MethodPut
}

// IsHead returns true if request method is HEAD.
func ( *RequestHeader) () bool {
	return string(.Method()) == MethodHead
}

// IsDelete returns true if request method is DELETE.
func ( *RequestHeader) () bool {
	return string(.Method()) == MethodDelete
}

// IsConnect returns true if request method is CONNECT.
func ( *RequestHeader) () bool {
	return string(.Method()) == MethodConnect
}

// IsOptions returns true if request method is OPTIONS.
func ( *RequestHeader) () bool {
	return string(.Method()) == MethodOptions
}

// IsTrace returns true if request method is TRACE.
func ( *RequestHeader) () bool {
	return string(.Method()) == MethodTrace
}

// IsPatch returns true if request method is PATCH.
func ( *RequestHeader) () bool {
	return string(.Method()) == MethodPatch
}

// IsHTTP11 returns true if the request is HTTP/1.1.
func ( *RequestHeader) () bool {
	return !.noHTTP11
}

// IsHTTP11 returns true if the response is HTTP/1.1.
func ( *ResponseHeader) () bool {
	return !.noHTTP11
}

// HasAcceptEncoding returns true if the header contains
// the given Accept-Encoding value.
func ( *RequestHeader) ( string) bool {
	.bufKV.value = append(.bufKV.value[:0], ...)
	return .HasAcceptEncodingBytes(.bufKV.value)
}

// HasAcceptEncodingBytes returns true if the header contains
// the given Accept-Encoding value.
func ( *RequestHeader) ( []byte) bool {
	 := .peek(strAcceptEncoding)
	 := bytes.Index(, )
	if  < 0 {
		return false
	}
	 := [+len():]
	if len() > 0 && [0] != ',' {
		return false
	}
	if  == 0 {
		return true
	}
	return [-1] == ' '
}

// Len returns the number of headers set,
// i.e. the number of times f is called in VisitAll.
func ( *ResponseHeader) () int {
	 := 0
	.VisitAll(func(,  []byte) { ++ })
	return 
}

// Len returns the number of headers set,
// i.e. the number of times f is called in VisitAll.
func ( *RequestHeader) () int {
	 := 0
	.VisitAll(func(,  []byte) { ++ })
	return 
}

// DisableSpecialHeader disables special header processing.
// fasthttp will not set any special headers for you, such as Host, Content-Type, User-Agent, etc.
// You must set everything yourself.
// If RequestHeader.Read() is called, special headers will be ignored.
// This can be used to control case and order of special headers.
// This is generally not recommended.
func ( *RequestHeader) () {
	.disableSpecialHeader = true
}

// EnableSpecialHeader enables special header processing.
// fasthttp will send Host, Content-Type, User-Agent, etc headers for you.
// This is suggested and enabled by default.
func ( *RequestHeader) () {
	.disableSpecialHeader = false
}

// DisableNormalizing disables header names' normalization.
//
// By default all the header names are normalized by uppercasing
// the first letter and all the first letters following dashes,
// while lowercasing all the other letters.
// Examples:
//
//   - CONNECTION -> Connection
//   - conteNT-tYPE -> Content-Type
//   - foo-bar-baz -> Foo-Bar-Baz
//
// Disable header names' normalization only if know what are you doing.
func ( *RequestHeader) () {
	.disableNormalizing = true
}

// EnableNormalizing enables header names' normalization.
//
// Header names are normalized by uppercasing the first letter and
// all the first letters following dashes, while lowercasing all
// the other letters.
// Examples:
//
//   - CONNECTION -> Connection
//   - conteNT-tYPE -> Content-Type
//   - foo-bar-baz -> Foo-Bar-Baz
//
// This is enabled by default unless disabled using DisableNormalizing()
func ( *RequestHeader) () {
	.disableNormalizing = false
}

// DisableNormalizing disables header names' normalization.
//
// By default all the header names are normalized by uppercasing
// the first letter and all the first letters following dashes,
// while lowercasing all the other letters.
// Examples:
//
//   - CONNECTION -> Connection
//   - conteNT-tYPE -> Content-Type
//   - foo-bar-baz -> Foo-Bar-Baz
//
// Disable header names' normalization only if know what are you doing.
func ( *ResponseHeader) () {
	.disableNormalizing = true
}

// EnableNormalizing enables header names' normalization.
//
// Header names are normalized by uppercasing the first letter and
// all the first letters following dashes, while lowercasing all
// the other letters.
// Examples:
//
//   - CONNECTION -> Connection
//   - conteNT-tYPE -> Content-Type
//   - foo-bar-baz -> Foo-Bar-Baz
//
// This is enabled by default unless disabled using DisableNormalizing()
func ( *ResponseHeader) () {
	.disableNormalizing = false
}

// SetNoDefaultContentType allows you to control if a default Content-Type header will be set (false) or not (true).
func ( *ResponseHeader) ( bool) {
	.noDefaultContentType = 
}

// Reset clears response header.
func ( *ResponseHeader) () {
	.disableNormalizing = false
	.SetNoDefaultContentType(false)
	.noDefaultDate = false
	.resetSkipNormalize()
}

func ( *ResponseHeader) () {
	.noHTTP11 = false
	.connectionClose = false

	.statusCode = 0
	.statusMessage = .statusMessage[:0]
	.protocol = .protocol[:0]
	.contentLength = 0
	.contentLengthBytes = .contentLengthBytes[:0]

	.contentType = .contentType[:0]
	.contentEncoding = .contentEncoding[:0]
	.server = .server[:0]

	.h = .h[:0]
	.cookies = .cookies[:0]
	.trailer = .trailer[:0]
	.mulHeader = .mulHeader[:0]
}

// SetNoDefaultContentType allows you to control if a default Content-Type header will be set (false) or not (true).
func ( *RequestHeader) ( bool) {
	.noDefaultContentType = 
}

// Reset clears request header.
func ( *RequestHeader) () {
	.disableNormalizing = false
	.SetNoDefaultContentType(false)
	.resetSkipNormalize()
}

func ( *RequestHeader) () {
	.noHTTP11 = false
	.connectionClose = false

	.contentLength = 0
	.contentLengthBytes = .contentLengthBytes[:0]

	.method = .method[:0]
	.proto = .proto[:0]
	.requestURI = .requestURI[:0]
	.host = .host[:0]
	.contentType = .contentType[:0]
	.userAgent = .userAgent[:0]
	.trailer = .trailer[:0]
	.mulHeader = .mulHeader[:0]

	.h = .h[:0]
	.cookies = .cookies[:0]
	.cookiesCollected = false

	.rawHeaders = .rawHeaders[:0]
}

// CopyTo copies all the headers to dst.
func ( *ResponseHeader) ( *ResponseHeader) {
	.Reset()

	.disableNormalizing = .disableNormalizing
	.noHTTP11 = .noHTTP11
	.connectionClose = .connectionClose
	.noDefaultContentType = .noDefaultContentType
	.noDefaultDate = .noDefaultDate

	.statusCode = .statusCode
	.statusMessage = append(.statusMessage, .statusMessage...)
	.protocol = append(.protocol, .protocol...)
	.contentLength = .contentLength
	.contentLengthBytes = append(.contentLengthBytes, .contentLengthBytes...)
	.contentType = append(.contentType, .contentType...)
	.contentEncoding = append(.contentEncoding, .contentEncoding...)
	.server = append(.server, .server...)
	.h = copyArgs(.h, .h)
	.cookies = copyArgs(.cookies, .cookies)
	.trailer = copyArgs(.trailer, .trailer)
}

// CopyTo copies all the headers to dst.
func ( *RequestHeader) ( *RequestHeader) {
	.Reset()

	.disableNormalizing = .disableNormalizing
	.noHTTP11 = .noHTTP11
	.connectionClose = .connectionClose
	.noDefaultContentType = .noDefaultContentType

	.contentLength = .contentLength
	.contentLengthBytes = append(.contentLengthBytes, .contentLengthBytes...)
	.method = append(.method, .method...)
	.proto = append(.proto, .proto...)
	.requestURI = append(.requestURI, .requestURI...)
	.host = append(.host, .host...)
	.contentType = append(.contentType, .contentType...)
	.userAgent = append(.userAgent, .userAgent...)
	.trailer = append(.trailer, .trailer...)
	.h = copyArgs(.h, .h)
	.cookies = copyArgs(.cookies, .cookies)
	.cookiesCollected = .cookiesCollected
	.rawHeaders = append(.rawHeaders, .rawHeaders...)
}

// VisitAll calls f for each header.
//
// f must not retain references to key and/or value after returning.
// Copy key and/or value contents before returning if you need retaining them.
func ( *ResponseHeader) ( func(,  []byte)) {
	if len(.contentLengthBytes) > 0 {
		(strContentLength, .contentLengthBytes)
	}
	 := .ContentType()
	if len() > 0 {
		(strContentType, )
	}
	 := .ContentEncoding()
	if len() > 0 {
		(strContentEncoding, )
	}
	 := .Server()
	if len() > 0 {
		(strServer, )
	}
	if len(.cookies) > 0 {
		visitArgs(.cookies, func(,  []byte) {
			(strSetCookie, )
		})
	}
	if len(.trailer) > 0 {
		(strTrailer, appendArgsKeyBytes(nil, .trailer, strCommaSpace))
	}
	visitArgs(.h, )
	if .ConnectionClose() {
		(strConnection, strClose)
	}
}

// VisitAllTrailer calls f for each response Trailer.
//
// f must not retain references to value after returning.
func ( *ResponseHeader) ( func( []byte)) {
	visitArgsKey(.trailer, )
}

// VisitAllTrailer calls f for each request Trailer.
//
// f must not retain references to value after returning.
func ( *RequestHeader) ( func( []byte)) {
	visitArgsKey(.trailer, )
}

// VisitAllCookie calls f for each response cookie.
//
// Cookie name is passed in key and the whole Set-Cookie header value
// is passed in value on each f invocation. Value may be parsed
// with Cookie.ParseBytes().
//
// f must not retain references to key and/or value after returning.
func ( *ResponseHeader) ( func(,  []byte)) {
	visitArgs(.cookies, )
}

// VisitAllCookie calls f for each request cookie.
//
// f must not retain references to key and/or value after returning.
func ( *RequestHeader) ( func(,  []byte)) {
	.collectCookies()
	visitArgs(.cookies, )
}

// VisitAll calls f for each header.
//
// f must not retain references to key and/or value after returning.
// Copy key and/or value contents before returning if you need retaining them.
//
// To get the headers in order they were received use VisitAllInOrder.
func ( *RequestHeader) ( func(,  []byte)) {
	 := .Host()
	if len() > 0 {
		(strHost, )
	}
	if len(.contentLengthBytes) > 0 {
		(strContentLength, .contentLengthBytes)
	}
	 := .ContentType()
	if len() > 0 {
		(strContentType, )
	}
	 := .UserAgent()
	if len() > 0 {
		(strUserAgent, )
	}
	if len(.trailer) > 0 {
		(strTrailer, appendArgsKeyBytes(nil, .trailer, strCommaSpace))
	}

	.collectCookies()
	if len(.cookies) > 0 {
		.bufKV.value = appendRequestCookieBytes(.bufKV.value[:0], .cookies)
		(strCookie, .bufKV.value)
	}
	visitArgs(.h, )
	if .ConnectionClose() {
		(strConnection, strClose)
	}
}

// VisitAllInOrder calls f for each header in the order they were received.
//
// f must not retain references to key and/or value after returning.
// Copy key and/or value contents before returning if you need retaining them.
//
// This function is slightly slower than VisitAll because it has to reparse the
// raw headers to get the order.
func ( *RequestHeader) ( func(,  []byte)) {
	var  headerScanner
	.b = .rawHeaders
	.disableNormalizing = .disableNormalizing
	for .next() {
		if len(.key) > 0 {
			(.key, .value)
		}
	}
}

// Del deletes header with the given key.
func ( *ResponseHeader) ( string) {
	 := getHeaderKeyBytes(&.bufKV, , .disableNormalizing)
	.del()
}

// DelBytes deletes header with the given key.
func ( *ResponseHeader) ( []byte) {
	.bufKV.key = append(.bufKV.key[:0], ...)
	normalizeHeaderKey(.bufKV.key, .disableNormalizing)
	.del(.bufKV.key)
}

func ( *ResponseHeader) ( []byte) {
	switch string() {
	case HeaderContentType:
		.contentType = .contentType[:0]
	case HeaderContentEncoding:
		.contentEncoding = .contentEncoding[:0]
	case HeaderServer:
		.server = .server[:0]
	case HeaderSetCookie:
		.cookies = .cookies[:0]
	case HeaderContentLength:
		.contentLength = 0
		.contentLengthBytes = .contentLengthBytes[:0]
	case HeaderConnection:
		.connectionClose = false
	case HeaderTrailer:
		.trailer = .trailer[:0]
	}
	.h = delAllArgsBytes(.h, )
}

// Del deletes header with the given key.
func ( *RequestHeader) ( string) {
	 := getHeaderKeyBytes(&.bufKV, , .disableNormalizing)
	.del()
}

// DelBytes deletes header with the given key.
func ( *RequestHeader) ( []byte) {
	.bufKV.key = append(.bufKV.key[:0], ...)
	normalizeHeaderKey(.bufKV.key, .disableNormalizing)
	.del(.bufKV.key)
}

func ( *RequestHeader) ( []byte) {
	switch string() {
	case HeaderHost:
		.host = .host[:0]
	case HeaderContentType:
		.contentType = .contentType[:0]
	case HeaderUserAgent:
		.userAgent = .userAgent[:0]
	case HeaderCookie:
		.cookies = .cookies[:0]
	case HeaderContentLength:
		.contentLength = 0
		.contentLengthBytes = .contentLengthBytes[:0]
	case HeaderConnection:
		.connectionClose = false
	case HeaderTrailer:
		.trailer = .trailer[:0]
	}
	.h = delAllArgsBytes(.h, )
}

// setSpecialHeader handles special headers and return true when a header is processed.
func ( *ResponseHeader) (,  []byte) bool {
	if len() == 0 {
		return false
	}

	switch [0] | 0x20 {
	case 'c':
		switch {
		case caseInsensitiveCompare(strContentType, ):
			.SetContentTypeBytes()
			return true
		case caseInsensitiveCompare(strContentLength, ):
			if ,  := parseContentLength();  == nil {
				.contentLength = 
				.contentLengthBytes = append(.contentLengthBytes[:0], ...)
			}
			return true
		case caseInsensitiveCompare(strContentEncoding, ):
			.SetContentEncodingBytes()
			return true
		case caseInsensitiveCompare(strConnection, ):
			if bytes.Equal(strClose, ) {
				.SetConnectionClose()
			} else {
				.ResetConnectionClose()
				.setNonSpecial(, )
			}
			return true
		}
	case 's':
		if caseInsensitiveCompare(strServer, ) {
			.SetServerBytes()
			return true
		} else if caseInsensitiveCompare(strSetCookie, ) {
			var  *argsKV
			.cookies,  = allocArg(.cookies)
			.key = getCookieKey(.key, )
			.value = append(.value[:0], ...)
			return true
		}
	case 't':
		if caseInsensitiveCompare(strTransferEncoding, ) {
			// Transfer-Encoding is managed automatically.
			return true
		} else if caseInsensitiveCompare(strTrailer, ) {
			_ = .SetTrailerBytes()
			return true
		}
	case 'd':
		if caseInsensitiveCompare(strDate, ) {
			// Date is managed automatically.
			return true
		}
	}

	return false
}

// setNonSpecial directly put into map i.e. not a basic header
func ( *ResponseHeader) ( []byte,  []byte) {
	.h = setArgBytes(.h, , , argsHasValue)
}

// setSpecialHeader handles special headers and return true when a header is processed.
func ( *RequestHeader) (,  []byte) bool {
	if len() == 0 || .disableSpecialHeader {
		return false
	}

	switch [0] | 0x20 {
	case 'c':
		switch {
		case caseInsensitiveCompare(strContentType, ):
			.SetContentTypeBytes()
			return true
		case caseInsensitiveCompare(strContentLength, ):
			if ,  := parseContentLength();  == nil {
				.contentLength = 
				.contentLengthBytes = append(.contentLengthBytes[:0], ...)
			}
			return true
		case caseInsensitiveCompare(strConnection, ):
			if bytes.Equal(strClose, ) {
				.SetConnectionClose()
			} else {
				.ResetConnectionClose()
				.setNonSpecial(, )
			}
			return true
		case caseInsensitiveCompare(strCookie, ):
			.collectCookies()
			.cookies = parseRequestCookies(.cookies, )
			return true
		}
	case 't':
		if caseInsensitiveCompare(strTransferEncoding, ) {
			// Transfer-Encoding is managed automatically.
			return true
		} else if caseInsensitiveCompare(strTrailer, ) {
			_ = .SetTrailerBytes()
			return true
		}
	case 'h':
		if caseInsensitiveCompare(strHost, ) {
			.SetHostBytes()
			return true
		}
	case 'u':
		if caseInsensitiveCompare(strUserAgent, ) {
			.SetUserAgentBytes()
			return true
		}
	}

	return false
}

// setNonSpecial directly put into map i.e. not a basic header
func ( *RequestHeader) ( []byte,  []byte) {
	.h = setArgBytes(.h, , , argsHasValue)
}

// Add adds the given 'key: value' header.
//
// Multiple headers with the same key may be added with this function.
// Use Set for setting a single header for the given key.
//
// the Content-Type, Content-Length, Connection, Server, Set-Cookie,
// Transfer-Encoding and Date headers can only be set once and will
// overwrite the previous value.
//
// If the header is set as a Trailer (forbidden trailers will not be set, see AddTrailer for more details),
// it will be sent after the chunked response body.
func ( *ResponseHeader) (,  string) {
	.AddBytesKV(s2b(), s2b())
}

// AddBytesK adds the given 'key: value' header.
//
// Multiple headers with the same key may be added with this function.
// Use SetBytesK for setting a single header for the given key.
//
// the Content-Type, Content-Length, Connection, Server, Set-Cookie,
// Transfer-Encoding and Date headers can only be set once and will
// overwrite the previous value.
//
// If the header is set as a Trailer (forbidden trailers will not be set, see AddTrailer for more details),
// it will be sent after the chunked response body.
func ( *ResponseHeader) ( []byte,  string) {
	.AddBytesKV(, s2b())
}

// AddBytesV adds the given 'key: value' header.
//
// Multiple headers with the same key may be added with this function.
// Use SetBytesV for setting a single header for the given key.
//
// the Content-Type, Content-Length, Connection, Server, Set-Cookie,
// Transfer-Encoding and Date headers can only be set once and will
// overwrite the previous value.
//
// If the header is set as a Trailer (forbidden trailers will not be set, see AddTrailer for more details),
// it will be sent after the chunked response body.
func ( *ResponseHeader) ( string,  []byte) {
	.AddBytesKV(s2b(), )
}

// AddBytesKV adds the given 'key: value' header.
//
// Multiple headers with the same key may be added with this function.
// Use SetBytesKV for setting a single header for the given key.
//
// the Content-Type, Content-Length, Connection, Server, Set-Cookie,
// Transfer-Encoding and Date headers can only be set once and will
// overwrite the previous value.
//
// If the header is set as a Trailer (forbidden trailers will not be set, see AddTrailer for more details),
// it will be sent after the chunked response body.
func ( *ResponseHeader) (,  []byte) {
	if .setSpecialHeader(, ) {
		return
	}

	 := getHeaderKeyBytes(&.bufKV, b2s(), .disableNormalizing)
	.h = appendArgBytes(.h, , , argsHasValue)
}

// Set sets the given 'key: value' header.
//
// If the header is set as a Trailer (forbidden trailers will not be set, see SetTrailer for more details),
// it will be sent after the chunked response body.
//
// Use Add for setting multiple header values under the same key.
func ( *ResponseHeader) (,  string) {
	initHeaderKV(&.bufKV, , , .disableNormalizing)
	.SetCanonical(.bufKV.key, .bufKV.value)
}

// SetBytesK sets the given 'key: value' header.
//
// If the header is set as a Trailer (forbidden trailers will not be set, see SetTrailer for more details),
// it will be sent after the chunked response body.
//
// Use AddBytesK for setting multiple header values under the same key.
func ( *ResponseHeader) ( []byte,  string) {
	.bufKV.value = append(.bufKV.value[:0], ...)
	.SetBytesKV(, .bufKV.value)
}

// SetBytesV sets the given 'key: value' header.
//
// If the header is set as a Trailer (forbidden trailers will not be set, see SetTrailer for more details),
// it will be sent after the chunked response body.
//
// Use AddBytesV for setting multiple header values under the same key.
func ( *ResponseHeader) ( string,  []byte) {
	 := getHeaderKeyBytes(&.bufKV, , .disableNormalizing)
	.SetCanonical(, )
}

// SetBytesKV sets the given 'key: value' header.
//
// If the header is set as a Trailer (forbidden trailers will not be set, see SetTrailer for more details),
// it will be sent after the chunked response body.
//
// Use AddBytesKV for setting multiple header values under the same key.
func ( *ResponseHeader) (,  []byte) {
	.bufKV.key = append(.bufKV.key[:0], ...)
	normalizeHeaderKey(.bufKV.key, .disableNormalizing)
	.SetCanonical(.bufKV.key, )
}

// SetCanonical sets the given 'key: value' header assuming that
// key is in canonical form.
//
// If the header is set as a Trailer (forbidden trailers will not be set, see SetTrailer for more details),
// it will be sent after the chunked response body.
func ( *ResponseHeader) (,  []byte) {
	if .setSpecialHeader(, ) {
		return
	}
	.setNonSpecial(, )
}

// SetCookie sets the given response cookie.
//
// It is safe re-using the cookie after the function returns.
func ( *ResponseHeader) ( *Cookie) {
	.cookies = setArgBytes(.cookies, .Key(), .Cookie(), argsHasValue)
}

// SetCookie sets 'key: value' cookies.
func ( *RequestHeader) (,  string) {
	.collectCookies()
	.cookies = setArg(.cookies, , , argsHasValue)
}

// SetCookieBytesK sets 'key: value' cookies.
func ( *RequestHeader) ( []byte,  string) {
	.SetCookie(b2s(), )
}

// SetCookieBytesKV sets 'key: value' cookies.
func ( *RequestHeader) (,  []byte) {
	.SetCookie(b2s(), b2s())
}

// DelClientCookie instructs the client to remove the given cookie.
// This doesn't work for a cookie with specific domain or path,
// you should delete it manually like:
//
//	c := AcquireCookie()
//	c.SetKey(key)
//	c.SetDomain("example.com")
//	c.SetPath("/path")
//	c.SetExpire(CookieExpireDelete)
//	h.SetCookie(c)
//	ReleaseCookie(c)
//
// Use DelCookie if you want just removing the cookie from response header.
func ( *ResponseHeader) ( string) {
	.DelCookie()

	 := AcquireCookie()
	.SetKey()
	.SetExpire(CookieExpireDelete)
	.SetCookie()
	ReleaseCookie()
}

// DelClientCookieBytes instructs the client to remove the given cookie.
// This doesn't work for a cookie with specific domain or path,
// you should delete it manually like:
//
//	c := AcquireCookie()
//	c.SetKey(key)
//	c.SetDomain("example.com")
//	c.SetPath("/path")
//	c.SetExpire(CookieExpireDelete)
//	h.SetCookie(c)
//	ReleaseCookie(c)
//
// Use DelCookieBytes if you want just removing the cookie from response header.
func ( *ResponseHeader) ( []byte) {
	.DelClientCookie(b2s())
}

// DelCookie removes cookie under the given key from response header.
//
// Note that DelCookie doesn't remove the cookie from the client.
// Use DelClientCookie instead.
func ( *ResponseHeader) ( string) {
	.cookies = delAllArgs(.cookies, )
}

// DelCookieBytes removes cookie under the given key from response header.
//
// Note that DelCookieBytes doesn't remove the cookie from the client.
// Use DelClientCookieBytes instead.
func ( *ResponseHeader) ( []byte) {
	.DelCookie(b2s())
}

// DelCookie removes cookie under the given key.
func ( *RequestHeader) ( string) {
	.collectCookies()
	.cookies = delAllArgs(.cookies, )
}

// DelCookieBytes removes cookie under the given key.
func ( *RequestHeader) ( []byte) {
	.DelCookie(b2s())
}

// DelAllCookies removes all the cookies from response headers.
func ( *ResponseHeader) () {
	.cookies = .cookies[:0]
}

// DelAllCookies removes all the cookies from request headers.
func ( *RequestHeader) () {
	.collectCookies()
	.cookies = .cookies[:0]
}

// Add adds the given 'key: value' header.
//
// Multiple headers with the same key may be added with this function.
// Use Set for setting a single header for the given key.
//
// If the header is set as a Trailer (forbidden trailers will not be set, see AddTrailer for more details),
// it will be sent after the chunked request body.
func ( *RequestHeader) (,  string) {
	.AddBytesKV(s2b(), s2b())
}

// AddBytesK adds the given 'key: value' header.
//
// Multiple headers with the same key may be added with this function.
// Use SetBytesK for setting a single header for the given key.
//
// If the header is set as a Trailer (forbidden trailers will not be set, see AddTrailer for more details),
// it will be sent after the chunked request body.
func ( *RequestHeader) ( []byte,  string) {
	.AddBytesKV(, s2b())
}

// AddBytesV adds the given 'key: value' header.
//
// Multiple headers with the same key may be added with this function.
// Use SetBytesV for setting a single header for the given key.
//
// If the header is set as a Trailer (forbidden trailers will not be set, see AddTrailer for more details),
// it will be sent after the chunked request body.
func ( *RequestHeader) ( string,  []byte) {
	.AddBytesKV(s2b(), )
}

// AddBytesKV adds the given 'key: value' header.
//
// Multiple headers with the same key may be added with this function.
// Use SetBytesKV for setting a single header for the given key.
//
// the Content-Type, Content-Length, Connection, Cookie,
// Transfer-Encoding, Host and User-Agent headers can only be set once
// and will overwrite the previous value.
//
// If the header is set as a Trailer (forbidden trailers will not be set, see AddTrailer for more details),
// it will be sent after the chunked request body.
func ( *RequestHeader) (,  []byte) {
	if .setSpecialHeader(, ) {
		return
	}

	 := getHeaderKeyBytes(&.bufKV, b2s(), .disableNormalizing)
	.h = appendArgBytes(.h, , , argsHasValue)
}

// Set sets the given 'key: value' header.
//
// If the header is set as a Trailer (forbidden trailers will not be set, see SetTrailer for more details),
// it will be sent after the chunked request body.
//
// Use Add for setting multiple header values under the same key.
func ( *RequestHeader) (,  string) {
	initHeaderKV(&.bufKV, , , .disableNormalizing)
	.SetCanonical(.bufKV.key, .bufKV.value)
}

// SetBytesK sets the given 'key: value' header.
//
// If the header is set as a Trailer (forbidden trailers will not be set, see SetTrailer for more details),
// it will be sent after the chunked request body.
//
// Use AddBytesK for setting multiple header values under the same key.
func ( *RequestHeader) ( []byte,  string) {
	.bufKV.value = append(.bufKV.value[:0], ...)
	.SetBytesKV(, .bufKV.value)
}

// SetBytesV sets the given 'key: value' header.
//
// If the header is set as a Trailer (forbidden trailers will not be set, see SetTrailer for more details),
// it will be sent after the chunked request body.
//
// Use AddBytesV for setting multiple header values under the same key.
func ( *RequestHeader) ( string,  []byte) {
	 := getHeaderKeyBytes(&.bufKV, , .disableNormalizing)
	.SetCanonical(, )
}

// SetBytesKV sets the given 'key: value' header.
//
// If the header is set as a Trailer (forbidden trailers will not be set, see SetTrailer for more details),
// it will be sent after the chunked request body.
//
// Use AddBytesKV for setting multiple header values under the same key.
func ( *RequestHeader) (,  []byte) {
	.bufKV.key = append(.bufKV.key[:0], ...)
	normalizeHeaderKey(.bufKV.key, .disableNormalizing)
	.SetCanonical(.bufKV.key, )
}

// SetCanonical sets the given 'key: value' header assuming that
// key is in canonical form.
//
// If the header is set as a Trailer (forbidden trailers will not be set, see SetTrailer for more details),
// it will be sent after the chunked request body.
func ( *RequestHeader) (,  []byte) {
	if .setSpecialHeader(, ) {
		return
	}
	.setNonSpecial(, )
}

// Peek returns header value for the given key.
//
// The returned value is valid until the response is released,
// either though ReleaseResponse or your request handler returning.
// Do not store references to the returned value. Make copies instead.
func ( *ResponseHeader) ( string) []byte {
	 := getHeaderKeyBytes(&.bufKV, , .disableNormalizing)
	return .peek()
}

// PeekBytes returns header value for the given key.
//
// 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 ( *ResponseHeader) ( []byte) []byte {
	.bufKV.key = append(.bufKV.key[:0], ...)
	normalizeHeaderKey(.bufKV.key, .disableNormalizing)
	return .peek(.bufKV.key)
}

// Peek returns header value for the given key.
//
// 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 ( *RequestHeader) ( string) []byte {
	 := getHeaderKeyBytes(&.bufKV, , .disableNormalizing)
	return .peek()
}

// PeekBytes returns header value for the given key.
//
// 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 ( *RequestHeader) ( []byte) []byte {
	.bufKV.key = append(.bufKV.key[:0], ...)
	normalizeHeaderKey(.bufKV.key, .disableNormalizing)
	return .peek(.bufKV.key)
}

func ( *ResponseHeader) ( []byte) []byte {
	switch string() {
	case HeaderContentType:
		return .ContentType()
	case HeaderContentEncoding:
		return .ContentEncoding()
	case HeaderServer:
		return .Server()
	case HeaderConnection:
		if .ConnectionClose() {
			return strClose
		}
		return peekArgBytes(.h, )
	case HeaderContentLength:
		return .contentLengthBytes
	case HeaderSetCookie:
		return appendResponseCookieBytes(nil, .cookies)
	case HeaderTrailer:
		return appendArgsKeyBytes(nil, .trailer, strCommaSpace)
	default:
		return peekArgBytes(.h, )
	}
}

func ( *RequestHeader) ( []byte) []byte {
	switch string() {
	case HeaderHost:
		return .Host()
	case HeaderContentType:
		return .ContentType()
	case HeaderUserAgent:
		return .UserAgent()
	case HeaderConnection:
		if .ConnectionClose() {
			return strClose
		}
		return peekArgBytes(.h, )
	case HeaderContentLength:
		return .contentLengthBytes
	case HeaderCookie:
		if .cookiesCollected {
			return appendRequestCookieBytes(nil, .cookies)
		}
		return peekArgBytes(.h, )
	case HeaderTrailer:
		return appendArgsKeyBytes(nil, .trailer, strCommaSpace)
	default:
		return peekArgBytes(.h, )
	}
}

// PeekAll returns all header value for the given key.
//
// The returned value is valid until the request is released,
// either though ReleaseRequest or your request handler returning.
// Any future calls to the Peek* will modify the returned value.
// Do not store references to returned value. Make copies instead.
func ( *RequestHeader) ( string) [][]byte {
	 := getHeaderKeyBytes(&.bufKV, , .disableNormalizing)
	return .peekAll()
}

func ( *RequestHeader) ( []byte) [][]byte {
	.mulHeader = .mulHeader[:0]
	switch string() {
	case HeaderHost:
		if  := .Host(); len() > 0 {
			.mulHeader = append(.mulHeader, )
		}
	case HeaderContentType:
		if  := .ContentType(); len() > 0 {
			.mulHeader = append(.mulHeader, )
		}
	case HeaderUserAgent:
		if  := .UserAgent(); len() > 0 {
			.mulHeader = append(.mulHeader, )
		}
	case HeaderConnection:
		if .ConnectionClose() {
			.mulHeader = append(.mulHeader, strClose)
		} else {
			.mulHeader = peekAllArgBytesToDst(.mulHeader, .h, )
		}
	case HeaderContentLength:
		.mulHeader = append(.mulHeader, .contentLengthBytes)
	case HeaderCookie:
		if .cookiesCollected {
			.mulHeader = append(.mulHeader, appendRequestCookieBytes(nil, .cookies))
		} else {
			.mulHeader = peekAllArgBytesToDst(.mulHeader, .h, )
		}
	case HeaderTrailer:
		.mulHeader = append(.mulHeader, appendArgsKeyBytes(nil, .trailer, strCommaSpace))
	default:
		.mulHeader = peekAllArgBytesToDst(.mulHeader, .h, )
	}
	return .mulHeader
}

// PeekAll returns all header value for the given key.
//
// The returned value is valid until the request is released,
// either though ReleaseResponse or your request handler returning.
// Any future calls to the Peek* will modify the returned value.
// Do not store references to returned value. Make copies instead.
func ( *ResponseHeader) ( string) [][]byte {
	 := getHeaderKeyBytes(&.bufKV, , .disableNormalizing)
	return .peekAll()
}

func ( *ResponseHeader) ( []byte) [][]byte {
	.mulHeader = .mulHeader[:0]
	switch string() {
	case HeaderContentType:
		if  := .ContentType(); len() > 0 {
			.mulHeader = append(.mulHeader, )
		}
	case HeaderContentEncoding:
		if  := .ContentEncoding(); len() > 0 {
			.mulHeader = append(.mulHeader, )
		}
	case HeaderServer:
		if  := .Server(); len() > 0 {
			.mulHeader = append(.mulHeader, )
		}
	case HeaderConnection:
		if .ConnectionClose() {
			.mulHeader = append(.mulHeader, strClose)
		} else {
			.mulHeader = peekAllArgBytesToDst(.mulHeader, .h, )
		}
	case HeaderContentLength:
		.mulHeader = append(.mulHeader, .contentLengthBytes)
	case HeaderSetCookie:
		.mulHeader = append(.mulHeader, appendResponseCookieBytes(nil, .cookies))
	case HeaderTrailer:
		.mulHeader = append(.mulHeader, appendArgsKeyBytes(nil, .trailer, strCommaSpace))
	default:
		.mulHeader = peekAllArgBytesToDst(.mulHeader, .h, )
	}
	return .mulHeader
}

// PeekKeys return all header keys.
//
// The returned value is valid until the request is released,
// either though ReleaseRequest or your request handler returning.
// Any future calls to the Peek* will modify the returned value.
// Do not store references to returned value. Make copies instead.
func ( *RequestHeader) () [][]byte {
	.mulHeader = .mulHeader[:0]
	.mulHeader = peekArgsKeys(.mulHeader, .h)
	return .mulHeader
}

// PeekTrailerKeys return all trailer keys.
//
// The returned value is valid until the request is released,
// either though ReleaseRequest or your request handler returning.
// Any future calls to the Peek* will modify the returned value.
// Do not store references to returned value. Make copies instead.
func ( *RequestHeader) () [][]byte {
	.mulHeader = .mulHeader[:0]
	.mulHeader = peekArgsKeys(.mulHeader, .trailer)
	return .mulHeader
}

// PeekKeys return all header keys.
//
// The returned value is valid until the request is released,
// either though ReleaseResponse or your request handler returning.
// Any future calls to the Peek* will modify the returned value.
// Do not store references to returned value. Make copies instead.
func ( *ResponseHeader) () [][]byte {
	.mulHeader = .mulHeader[:0]
	.mulHeader = peekArgsKeys(.mulHeader, .h)
	return .mulHeader
}

// PeekTrailerKeys return all trailer keys.
//
// The returned value is valid until the request is released,
// either though ReleaseResponse or your request handler returning.
// Any future calls to the Peek* will modify the returned value.
// Do not store references to returned value. Make copies instead.
func ( *ResponseHeader) () [][]byte {
	.mulHeader = .mulHeader[:0]
	.mulHeader = peekArgsKeys(.mulHeader, .trailer)
	return .mulHeader
}

// Cookie returns cookie for the given key.
func ( *RequestHeader) ( string) []byte {
	.collectCookies()
	return peekArgStr(.cookies, )
}

// CookieBytes returns cookie for the given key.
func ( *RequestHeader) ( []byte) []byte {
	.collectCookies()
	return peekArgBytes(.cookies, )
}

// Cookie fills cookie for the given cookie.Key.
//
// Returns false if cookie with the given cookie.Key is missing.
func ( *ResponseHeader) ( *Cookie) bool {
	 := peekArgBytes(.cookies, .Key())
	if  == nil {
		return false
	}
	.ParseBytes() //nolint:errcheck
	return true
}

// Read reads response header from r.
//
// io.EOF is returned if r is closed before reading the first header byte.
func ( *ResponseHeader) ( *bufio.Reader) error {
	 := 1
	for {
		 := .tryRead(, )
		if  == nil {
			return nil
		}
		if  != errNeedMore {
			.resetSkipNormalize()
			return 
		}
		 = .Buffered() + 1
	}
}

func ( *ResponseHeader) ( *bufio.Reader,  int) error {
	.resetSkipNormalize()
	,  := .Peek()
	if len() == 0 {
		// Return ErrTimeout on any timeout.
		if ,  := .(interface{ () bool });  && .() {
			return ErrTimeout
		}
		// treat all other errors on the first byte read as EOF
		if  == 1 ||  == io.EOF {
			return io.EOF
		}

		// This is for go 1.6 bug. See https://github.com/golang/go/issues/14121 .
		if  == bufio.ErrBufferFull {
			if .secureErrorLogMessage {
				return &ErrSmallBuffer{
					error: fmt.Errorf("error when reading response headers"),
				}
			}
			return &ErrSmallBuffer{
				error: fmt.Errorf("error when reading response headers: %w", errSmallBuffer),
			}
		}

		return fmt.Errorf("error when reading response headers: %w", )
	}
	 = mustPeekBuffered()
	,  := .parse()
	if  != nil {
		return headerError("response", , , , .secureErrorLogMessage)
	}
	mustDiscard(, )
	return nil
}

// ReadTrailer reads response trailer header from r.
//
// io.EOF is returned if r is closed before reading the first byte.
func ( *ResponseHeader) ( *bufio.Reader) error {
	 := 1
	for {
		 := .tryReadTrailer(, )
		if  == nil {
			return nil
		}
		if  != errNeedMore {
			return 
		}
		 = .Buffered() + 1
	}
}

func ( *ResponseHeader) ( *bufio.Reader,  int) error {
	,  := .Peek()
	if len() == 0 {
		// Return ErrTimeout on any timeout.
		if ,  := .(interface{ () bool });  && .() {
			return ErrTimeout
		}

		if  == 1 ||  == io.EOF {
			return io.EOF
		}

		// This is for go 1.6 bug. See https://github.com/golang/go/issues/14121 .
		if  == bufio.ErrBufferFull {
			if .secureErrorLogMessage {
				return &ErrSmallBuffer{
					error: fmt.Errorf("error when reading response trailer"),
				}
			}
			return &ErrSmallBuffer{
				error: fmt.Errorf("error when reading response trailer: %w", errSmallBuffer),
			}
		}

		return fmt.Errorf("error when reading response trailer: %w", )
	}
	 = mustPeekBuffered()
	,  := .parseTrailer()
	if  != nil {
		if  == io.EOF {
			return 
		}
		return headerError("response", , , , .secureErrorLogMessage)
	}
	mustDiscard(, )
	return nil
}

func headerError( string, ,  error,  []byte,  bool) error {
	if  != errNeedMore {
		return headerErrorMsg(, , , )
	}
	if  == nil {
		return errNeedMore
	}

	// Buggy servers may leave trailing CRLFs after http body.
	// Treat this case as EOF.
	if isOnlyCRLF() {
		return io.EOF
	}

	if  != bufio.ErrBufferFull {
		return headerErrorMsg(, , , )
	}
	return &ErrSmallBuffer{
		error: headerErrorMsg(, errSmallBuffer, , ),
	}
}

func headerErrorMsg( string,  error,  []byte,  bool) error {
	if  {
		return fmt.Errorf("error when reading %s headers: %w. Buffer size=%d", , , len())
	}
	return fmt.Errorf("error when reading %s headers: %w. Buffer size=%d, contents: %s", , , len(), bufferSnippet())
}

// Read reads request header from r.
//
// io.EOF is returned if r is closed before reading the first header byte.
func ( *RequestHeader) ( *bufio.Reader) error {
	return .readLoop(, true)
}

// readLoop reads request header from r optionally loops until it has enough data.
//
// io.EOF is returned if r is closed before reading the first header byte.
func ( *RequestHeader) ( *bufio.Reader,  bool) error {
	 := 1
	for {
		 := .tryRead(, )
		if  == nil {
			return nil
		}
		if ! ||  != errNeedMore {
			.resetSkipNormalize()
			return 
		}
		 = .Buffered() + 1
	}
}

// ReadTrailer reads request trailer header from r.
//
// io.EOF is returned if r is closed before reading the first byte.
func ( *RequestHeader) ( *bufio.Reader) error {
	 := 1
	for {
		 := .tryReadTrailer(, )
		if  == nil {
			return nil
		}
		if  != errNeedMore {
			return 
		}
		 = .Buffered() + 1
	}
}

func ( *RequestHeader) ( *bufio.Reader,  int) error {
	,  := .Peek()
	if len() == 0 {
		// Return ErrTimeout on any timeout.
		if ,  := .(interface{ () bool });  && .() {
			return ErrTimeout
		}

		if  == 1 ||  == io.EOF {
			return io.EOF
		}

		// This is for go 1.6 bug. See https://github.com/golang/go/issues/14121 .
		if  == bufio.ErrBufferFull {
			if .secureErrorLogMessage {
				return &ErrSmallBuffer{
					error: fmt.Errorf("error when reading request trailer"),
				}
			}
			return &ErrSmallBuffer{
				error: fmt.Errorf("error when reading request trailer: %w", errSmallBuffer),
			}
		}

		return fmt.Errorf("error when reading request trailer: %w", )
	}
	 = mustPeekBuffered()
	,  := .parseTrailer()
	if  != nil {
		if  == io.EOF {
			return 
		}
		return headerError("request", , , , .secureErrorLogMessage)
	}
	mustDiscard(, )
	return nil
}

func ( *RequestHeader) ( *bufio.Reader,  int) error {
	.resetSkipNormalize()
	,  := .Peek()
	if len() == 0 {
		if  == io.EOF {
			return 
		}

		if  == nil {
			panic("bufio.Reader.Peek() returned nil, nil")
		}

		// This is for go 1.6 bug. See https://github.com/golang/go/issues/14121 .
		if  == bufio.ErrBufferFull {
			return &ErrSmallBuffer{
				error: fmt.Errorf("error when reading request headers: %w (n=%d, r.Buffered()=%d)", errSmallBuffer, , .Buffered()),
			}
		}

		// n == 1 on the first read for the request.
		if  == 1 {
			// We didn't read a single byte.
			return ErrNothingRead{}
		}

		return fmt.Errorf("error when reading request headers: %w", )
	}
	 = mustPeekBuffered()
	,  := .parse()
	if  != nil {
		return headerError("request", , , , .secureErrorLogMessage)
	}
	mustDiscard(, )
	return nil
}

func bufferSnippet( []byte) string {
	 := len()
	 := 200
	 :=  - 
	if  >=  {
		 = 
		 = 
	}
	,  := [:], [:]
	if len() == 0 {
		return fmt.Sprintf("%q", )
	}
	return fmt.Sprintf("%q...%q", , )
}

func isOnlyCRLF( []byte) bool {
	for ,  := range  {
		if  != rChar &&  != nChar {
			return false
		}
	}
	return true
}

func updateServerDate() {
	refreshServerDate()
	go func() {
		for {
			time.Sleep(time.Second)
			refreshServerDate()
		}
	}()
}

var (
	serverDate     atomic.Value
	serverDateOnce sync.Once // serverDateOnce.Do(updateServerDate)
)

func refreshServerDate() {
	 := AppendHTTPDate(nil, time.Now())
	serverDate.Store()
}

// Write writes response header to w.
func ( *ResponseHeader) ( *bufio.Writer) error {
	,  := .Write(.Header())
	return 
}

// WriteTo writes response header to w.
//
// WriteTo implements io.WriterTo interface.
func ( *ResponseHeader) ( io.Writer) (int64, error) {
	,  := .Write(.Header())
	return int64(), 
}

// Header returns response header representation.
//
// Headers that set as Trailer will not represent. Use TrailerHeader for trailers.
//
// 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 ( *ResponseHeader) () []byte {
	.bufKV.value = .AppendBytes(.bufKV.value[:0])
	return .bufKV.value
}

// writeTrailer writes response trailer to w.
func ( *ResponseHeader) ( *bufio.Writer) error {
	,  := .Write(.TrailerHeader())
	return 
}

// TrailerHeader returns response trailer header representation.
//
// Trailers will only be received with chunked transfer.
//
// 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 ( *ResponseHeader) () []byte {
	.bufKV.value = .bufKV.value[:0]
	for ,  := range .trailer {
		 := .peek(.key)
		.bufKV.value = appendHeaderLine(.bufKV.value, .key, )
	}
	.bufKV.value = append(.bufKV.value, strCRLF...)
	return .bufKV.value
}

// String returns response header representation.
func ( *ResponseHeader) () string {
	return string(.Header())
}

// appendStatusLine appends the response status line to dst and returns
// the extended dst.
func ( *ResponseHeader) ( []byte) []byte {
	 := .StatusCode()
	if  < 0 {
		 = StatusOK
	}
	return formatStatusLine(, .Protocol(), , .StatusMessage())
}

// AppendBytes appends response header representation to dst and returns
// the extended dst.
func ( *ResponseHeader) ( []byte) []byte {
	 = .appendStatusLine([:0])

	 := .Server()
	if len() != 0 {
		 = appendHeaderLine(, strServer, )
	}

	if !.noDefaultDate {
		serverDateOnce.Do(updateServerDate)
		 = appendHeaderLine(, strDate, serverDate.Load().([]byte))
	}

	// Append Content-Type only for non-zero responses
	// or if it is explicitly set.
	// See https://github.com/valyala/fasthttp/issues/28 .
	if .ContentLength() != 0 || len(.contentType) > 0 {
		 := .ContentType()
		if len() > 0 {
			 = appendHeaderLine(, strContentType, )
		}
	}
	 := .ContentEncoding()
	if len() > 0 {
		 = appendHeaderLine(, strContentEncoding, )
	}

	if len(.contentLengthBytes) > 0 {
		 = appendHeaderLine(, strContentLength, .contentLengthBytes)
	}

	for ,  := 0, len(.h);  < ; ++ {
		 := &.h[]

		// Exclude trailer from header
		 := false
		for ,  := range .trailer {
			if bytes.Equal(.key, .key) {
				 = true
				break
			}
		}
		if ! && (.noDefaultDate || !bytes.Equal(.key, strDate)) {
			 = appendHeaderLine(, .key, .value)
		}
	}

	if len(.trailer) > 0 {
		 = appendHeaderLine(, strTrailer, appendArgsKeyBytes(nil, .trailer, strCommaSpace))
	}

	 := len(.cookies)
	if  > 0 {
		for  := 0;  < ; ++ {
			 := &.cookies[]
			 = appendHeaderLine(, strSetCookie, .value)
		}
	}

	if .ConnectionClose() {
		 = appendHeaderLine(, strConnection, strClose)
	}

	return append(, strCRLF...)
}

// Write writes request header to w.
func ( *RequestHeader) ( *bufio.Writer) error {
	,  := .Write(.Header())
	return 
}

// WriteTo writes request header to w.
//
// WriteTo implements io.WriterTo interface.
func ( *RequestHeader) ( io.Writer) (int64, error) {
	,  := .Write(.Header())
	return int64(), 
}

// Header returns request header representation.
//
// Headers that set as Trailer will not represent. Use TrailerHeader for trailers.
//
// 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 ( *RequestHeader) () []byte {
	.bufKV.value = .AppendBytes(.bufKV.value[:0])
	return .bufKV.value
}

// writeTrailer writes request trailer to w.
func ( *RequestHeader) ( *bufio.Writer) error {
	,  := .Write(.TrailerHeader())
	return 
}

// TrailerHeader returns request trailer header representation.
//
// Trailers will only be received with chunked transfer.
//
// 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 ( *RequestHeader) () []byte {
	.bufKV.value = .bufKV.value[:0]
	for ,  := range .trailer {
		 := .peek(.key)
		.bufKV.value = appendHeaderLine(.bufKV.value, .key, )
	}
	.bufKV.value = append(.bufKV.value, strCRLF...)
	return .bufKV.value
}

// RawHeaders returns raw header key/value bytes.
//
// Depending on server configuration, header keys may be normalized to
// capital-case in place.
//
// This copy is set aside during parsing, so empty slice is returned for all
// cases where parsing did not happen. Similarly, request line is not stored
// during parsing and can not be returned.
//
// The slice is not safe to use after the handler returns.
func ( *RequestHeader) () []byte {
	return .rawHeaders
}

// String returns request header representation.
func ( *RequestHeader) () string {
	return string(.Header())
}

// AppendBytes appends request header representation to dst and returns
// the extended dst.
func ( *RequestHeader) ( []byte) []byte {
	 = append(, .Method()...)
	 = append(, ' ')
	 = append(, .RequestURI()...)
	 = append(, ' ')
	 = append(, .Protocol()...)
	 = append(, strCRLF...)

	 := .UserAgent()
	if len() > 0 && !.disableSpecialHeader {
		 = appendHeaderLine(, strUserAgent, )
	}

	 := .Host()
	if len() > 0 && !.disableSpecialHeader {
		 = appendHeaderLine(, strHost, )
	}

	 := .ContentType()
	if !.noDefaultContentType && len() == 0 && !.ignoreBody() {
		 = strDefaultContentType
	}
	if len() > 0 && !.disableSpecialHeader {
		 = appendHeaderLine(, strContentType, )
	}
	if len(.contentLengthBytes) > 0 && !.disableSpecialHeader {
		 = appendHeaderLine(, strContentLength, .contentLengthBytes)
	}

	for ,  := 0, len(.h);  < ; ++ {
		 := &.h[]
		// Exclude trailer from header
		 := false
		for ,  := range .trailer {
			if bytes.Equal(.key, .key) {
				 = true
				break
			}
		}
		if ! {
			 = appendHeaderLine(, .key, .value)
		}
	}

	if len(.trailer) > 0 {
		 = appendHeaderLine(, strTrailer, appendArgsKeyBytes(nil, .trailer, strCommaSpace))
	}

	// there is no need in h.collectCookies() here, since if cookies aren't collected yet,
	// they all are located in h.h.
	 := len(.cookies)
	if  > 0 && !.disableSpecialHeader {
		 = append(, strCookie...)
		 = append(, strColonSpace...)
		 = appendRequestCookieBytes(, .cookies)
		 = append(, strCRLF...)
	}

	if .ConnectionClose() && !.disableSpecialHeader {
		 = appendHeaderLine(, strConnection, strClose)
	}

	return append(, strCRLF...)
}

func appendHeaderLine(, ,  []byte) []byte {
	 = append(, ...)
	 = append(, strColonSpace...)
	 = append(, ...)
	return append(, strCRLF...)
}

func ( *ResponseHeader) ( []byte) (int, error) {
	,  := .parseFirstLine()
	if  != nil {
		return 0, 
	}
	,  := .parseHeaders([:])
	if  != nil {
		return 0, 
	}
	return  + , nil
}

func ( *ResponseHeader) ( []byte) (int, error) {
	// Skip any 0 length chunk.
	if [0] == '0' {
		 := len(strCRLF) + 1
		if len() <  {
			return 0, io.EOF
		}
		 = [:]
	}

	var  headerScanner
	.b = 
	.disableNormalizing = .disableNormalizing
	var  error
	for .next() {
		if len(.key) > 0 {
			if bytes.IndexByte(.key, ' ') != -1 || bytes.IndexByte(.key, '\t') != -1 {
				 = fmt.Errorf("invalid trailer key %q", .key)
				continue
			}
			// Forbidden by RFC 7230, section 4.1.2
			if isBadTrailer(.key) {
				 = fmt.Errorf("forbidden trailer key %q", .key)
				continue
			}
			.h = appendArgBytes(.h, .key, .value, argsHasValue)
		}
	}
	if .err != nil {
		return 0, .err
	}
	if  != nil {
		return 0, 
	}
	return .hLen, nil
}

func ( *RequestHeader) () bool {
	return .IsGet() || .IsHead()
}

func ( *RequestHeader) ( []byte) (int, error) {
	,  := .parseFirstLine()
	if  != nil {
		return 0, 
	}

	.rawHeaders, _,  = readRawHeaders(.rawHeaders[:0], [:])
	if  != nil {
		return 0, 
	}
	var  int
	,  = .parseHeaders([:])
	if  != nil {
		return 0, 
	}
	return  + , nil
}

func ( *RequestHeader) ( []byte) (int, error) {
	// Skip any 0 length chunk.
	if [0] == '0' {
		 := len(strCRLF) + 1
		if len() <  {
			return 0, io.EOF
		}
		 = [:]
	}

	var  headerScanner
	.b = 
	.disableNormalizing = .disableNormalizing
	var  error
	for .next() {
		if len(.key) > 0 {
			if bytes.IndexByte(.key, ' ') != -1 || bytes.IndexByte(.key, '\t') != -1 {
				 = fmt.Errorf("invalid trailer key %q", .key)
				continue
			}
			// Forbidden by RFC 7230, section 4.1.2
			if isBadTrailer(.key) {
				 = fmt.Errorf("forbidden trailer key %q", .key)
				continue
			}
			.h = appendArgBytes(.h, .key, .value, argsHasValue)
		}
	}
	if .err != nil {
		return 0, .err
	}
	if  != nil {
		return 0, 
	}
	return .hLen, nil
}

func isBadTrailer( []byte) bool {
	if len() == 0 {
		return true
	}

	switch [0] | 0x20 {
	case 'a':
		return caseInsensitiveCompare(, strAuthorization)
	case 'c':
		if len() > len(HeaderContentType) && caseInsensitiveCompare([:8], strContentType[:8]) {
			// skip compare prefix 'Content-'
			return caseInsensitiveCompare([8:], strContentEncoding[8:]) ||
				caseInsensitiveCompare([8:], strContentLength[8:]) ||
				caseInsensitiveCompare([8:], strContentType[8:]) ||
				caseInsensitiveCompare([8:], strContentRange[8:])
		}
		return caseInsensitiveCompare(, strConnection)
	case 'e':
		return caseInsensitiveCompare(, strExpect)
	case 'h':
		return caseInsensitiveCompare(, strHost)
	case 'k':
		return caseInsensitiveCompare(, strKeepAlive)
	case 'm':
		return caseInsensitiveCompare(, strMaxForwards)
	case 'p':
		if len() > len(HeaderProxyConnection) && caseInsensitiveCompare([:6], strProxyConnection[:6]) {
			// skip compare prefix 'Proxy-'
			return caseInsensitiveCompare([6:], strProxyConnection[6:]) ||
				caseInsensitiveCompare([6:], strProxyAuthenticate[6:]) ||
				caseInsensitiveCompare([6:], strProxyAuthorization[6:])
		}
	case 'r':
		return caseInsensitiveCompare(, strRange)
	case 't':
		return caseInsensitiveCompare(, strTE) ||
			caseInsensitiveCompare(, strTrailer) ||
			caseInsensitiveCompare(, strTransferEncoding)
	case 'w':
		return caseInsensitiveCompare(, strWWWAuthenticate)
	}
	return false
}

func ( *ResponseHeader) ( []byte) (int, error) {
	 := 
	var  []byte
	var  error
	for len() == 0 {
		if , ,  = nextLine();  != nil {
			return 0, 
		}
	}

	// parse protocol
	 := bytes.IndexByte(, ' ')
	if  < 0 {
		if .secureErrorLogMessage {
			return 0, fmt.Errorf("cannot find whitespace in the first line of response")
		}
		return 0, fmt.Errorf("cannot find whitespace in the first line of response %q", )
	}
	.noHTTP11 = !bytes.Equal([:], strHTTP11)
	 = [+1:]

	// parse status code
	.statusCode, ,  = parseUintBuf()
	if  != nil {
		if .secureErrorLogMessage {
			return 0, fmt.Errorf("cannot parse response status code: %w", )
		}
		return 0, fmt.Errorf("cannot parse response status code: %w. Response %q", , )
	}
	if len() >  && [] != ' ' {
		if .secureErrorLogMessage {
			return 0, fmt.Errorf("unexpected char at the end of status code")
		}
		return 0, fmt.Errorf("unexpected char at the end of status code. Response %q", )
	}
	if len() > +1 {
		.SetStatusMessage([+1:])
	}

	return len() - len(), nil
}

func ( *RequestHeader) ( []byte) (int, error) {
	 := 
	var  []byte
	var  error
	for len() == 0 {
		if , ,  = nextLine();  != nil {
			return 0, 
		}
	}

	// parse method
	 := bytes.IndexByte(, ' ')
	if  <= 0 {
		if .secureErrorLogMessage {
			return 0, fmt.Errorf("cannot find http request method")
		}
		return 0, fmt.Errorf("cannot find http request method in %q", )
	}
	.method = append(.method[:0], [:]...)
	 = [+1:]

	 := strHTTP11
	// parse requestURI
	 = bytes.LastIndexByte(, ' ')
	switch {
	case  < 0:
		.noHTTP11 = true
		 = len()
		 = strHTTP10
	case  == 0:
		if .secureErrorLogMessage {
			return 0, fmt.Errorf("requestURI cannot be empty")
		}
		return 0, fmt.Errorf("requestURI cannot be empty in %q", )
	case !bytes.Equal([+1:], strHTTP11):
		.noHTTP11 = true
		 = [+1:]
	}

	.proto = append(.proto[:0], ...)
	.requestURI = append(.requestURI[:0], [:]...)

	return len() - len(), nil
}

func readRawHeaders(,  []byte) ([]byte, int, error) {
	 := bytes.IndexByte(, nChar)
	if  < 0 {
		return [:0], 0, errNeedMore
	}
	if ( == 1 && [0] == rChar) ||  == 0 {
		// empty headers
		return ,  + 1, nil
	}

	++
	 := 
	 := 
	for {
		 = [:]
		 = bytes.IndexByte(, nChar)
		if  < 0 {
			return , 0, errNeedMore
		}
		++
		 += 
		if ( == 2 && [0] == rChar) ||  == 1 {
			 = append(, [:]...)
			return , , nil
		}
	}
}

func ( *ResponseHeader) ( []byte) (int, error) {
	// 'identity' content-length by default
	.contentLength = -2

	var  headerScanner
	.b = 
	.disableNormalizing = .disableNormalizing
	var  error
	var  *argsKV
	for .next() {
		if len(.key) > 0 {
			switch .key[0] | 0x20 {
			case 'c':
				if caseInsensitiveCompare(.key, strContentType) {
					.contentType = append(.contentType[:0], .value...)
					continue
				}
				if caseInsensitiveCompare(.key, strContentEncoding) {
					.contentEncoding = append(.contentEncoding[:0], .value...)
					continue
				}
				if caseInsensitiveCompare(.key, strContentLength) {
					if .contentLength != -1 {
						if .contentLength,  = parseContentLength(.value);  != nil {
							.contentLength = -2
						} else {
							.contentLengthBytes = append(.contentLengthBytes[:0], .value...)
						}
					}
					continue
				}
				if caseInsensitiveCompare(.key, strConnection) {
					if bytes.Equal(.value, strClose) {
						.connectionClose = true
					} else {
						.connectionClose = false
						.h = appendArgBytes(.h, .key, .value, argsHasValue)
					}
					continue
				}
			case 's':
				if caseInsensitiveCompare(.key, strServer) {
					.server = append(.server[:0], .value...)
					continue
				}
				if caseInsensitiveCompare(.key, strSetCookie) {
					.cookies,  = allocArg(.cookies)
					.key = getCookieKey(.key, .value)
					.value = append(.value[:0], .value...)
					continue
				}
			case 't':
				if caseInsensitiveCompare(.key, strTransferEncoding) {
					if len(.value) > 0 && !bytes.Equal(.value, strIdentity) {
						.contentLength = -1
						.h = setArgBytes(.h, strTransferEncoding, strChunked, argsHasValue)
					}
					continue
				}
				if caseInsensitiveCompare(.key, strTrailer) {
					 = .SetTrailerBytes(.value)
					continue
				}
			}
			.h = appendArgBytes(.h, .key, .value, argsHasValue)
		}
	}
	if .err != nil {
		.connectionClose = true
		return 0, .err
	}

	if .contentLength < 0 {
		.contentLengthBytes = .contentLengthBytes[:0]
	}
	if .contentLength == -2 && !.ConnectionUpgrade() && !.mustSkipContentLength() {
		.h = setArgBytes(.h, strTransferEncoding, strIdentity, argsHasValue)
		.connectionClose = true
	}
	if .noHTTP11 && !.connectionClose {
		// close connection for non-http/1.1 response unless 'Connection: keep-alive' is set.
		 := peekArgBytes(.h, strConnection)
		.connectionClose = !hasHeaderValue(, strKeepAlive)
	}

	return len() - len(.b), 
}

func ( *RequestHeader) ( []byte) (int, error) {
	.contentLength = -2

	var  headerScanner
	.b = 
	.disableNormalizing = .disableNormalizing
	var  error
	for .next() {
		if len(.key) > 0 {
			// Spaces between the header key and colon are not allowed.
			// See RFC 7230, Section 3.2.4.
			if bytes.IndexByte(.key, ' ') != -1 || bytes.IndexByte(.key, '\t') != -1 {
				 = fmt.Errorf("invalid header key %q", .key)
				continue
			}

			if .disableSpecialHeader {
				.h = appendArgBytes(.h, .key, .value, argsHasValue)
				continue
			}

			switch .key[0] | 0x20 {
			case 'h':
				if caseInsensitiveCompare(.key, strHost) {
					.host = append(.host[:0], .value...)
					continue
				}
			case 'u':
				if caseInsensitiveCompare(.key, strUserAgent) {
					.userAgent = append(.userAgent[:0], .value...)
					continue
				}
			case 'c':
				if caseInsensitiveCompare(.key, strContentType) {
					.contentType = append(.contentType[:0], .value...)
					continue
				}
				if caseInsensitiveCompare(.key, strContentLength) {
					if .contentLength != -1 {
						var  error
						if .contentLength,  = parseContentLength(.value);  != nil {
							if  == nil {
								 = 
							}
							.contentLength = -2
						} else {
							.contentLengthBytes = append(.contentLengthBytes[:0], .value...)
						}
					}
					continue
				}
				if caseInsensitiveCompare(.key, strConnection) {
					if bytes.Equal(.value, strClose) {
						.connectionClose = true
					} else {
						.connectionClose = false
						.h = appendArgBytes(.h, .key, .value, argsHasValue)
					}
					continue
				}
			case 't':
				if caseInsensitiveCompare(.key, strTransferEncoding) {
					if !bytes.Equal(.value, strIdentity) {
						.contentLength = -1
						.h = setArgBytes(.h, strTransferEncoding, strChunked, argsHasValue)
					}
					continue
				}
				if caseInsensitiveCompare(.key, strTrailer) {
					if  := .SetTrailerBytes(.value);  != nil {
						if  == nil {
							 = 
						}
					}
					continue
				}
			}
		}
		.h = appendArgBytes(.h, .key, .value, argsHasValue)
	}
	if .err != nil &&  == nil {
		 = .err
	}
	if  != nil {
		.connectionClose = true
		return 0, 
	}

	if .contentLength < 0 {
		.contentLengthBytes = .contentLengthBytes[:0]
	}
	if .noHTTP11 && !.connectionClose {
		// close connection for non-http/1.1 request unless 'Connection: keep-alive' is set.
		 := peekArgBytes(.h, strConnection)
		.connectionClose = !hasHeaderValue(, strKeepAlive)
	}
	return .hLen, nil
}

func ( *RequestHeader) () {
	if .cookiesCollected {
		return
	}

	for ,  := 0, len(.h);  < ; ++ {
		 := &.h[]
		if caseInsensitiveCompare(.key, strCookie) {
			.cookies = parseRequestCookies(.cookies, .value)
			 := *
			copy(.h[:], .h[+1:])
			--
			--
			.h[] = 
			.h = .h[:]
		}
	}
	.cookiesCollected = true
}

var errNonNumericChars = errors.New("non-numeric chars found")

func parseContentLength( []byte) (int, error) {
	, ,  := parseUintBuf()
	if  != nil {
		return -1, fmt.Errorf("cannot parse Content-Length: %w", )
	}
	if  != len() {
		return -1, fmt.Errorf("cannot parse Content-Length: %w", errNonNumericChars)
	}
	return , nil
}

type headerScanner struct {
	b     []byte
	key   []byte
	value []byte
	err   error

	// hLen stores header subslice len
	hLen int

	disableNormalizing bool

	// by checking whether the next line contains a colon or not to tell
	// it's a header entry or a multi line value of current header entry.
	// the side effect of this operation is that we know the index of the
	// next colon and new line, so this can be used during next iteration,
	// instead of find them again.
	nextColon   int
	nextNewLine int

	initialized bool
}

func ( *headerScanner) () bool {
	if !.initialized {
		.nextColon = -1
		.nextNewLine = -1
		.initialized = true
	}
	 := len(.b)
	if  >= 2 && .b[0] == rChar && .b[1] == nChar {
		.b = .b[2:]
		.hLen += 2
		return false
	}
	if  >= 1 && .b[0] == nChar {
		.b = .b[1:]
		.hLen++
		return false
	}
	var  int
	if .nextColon >= 0 {
		 = .nextColon
		.nextColon = -1
	} else {
		 = bytes.IndexByte(.b, ':')

		// There can't be a \n inside the header name, check for this.
		 := bytes.IndexByte(.b, nChar)
		if  < 0 {
			// A header name should always at some point be followed by a \n
			// even if it's the one that terminates the header block.
			.err = errNeedMore
			return false
		}
		if  <  {
			// There was a \n before the :
			.err = errInvalidName
			return false
		}
	}
	if  < 0 {
		.err = errNeedMore
		return false
	}
	.key = .b[:]
	normalizeHeaderKey(.key, .disableNormalizing)
	++
	for len(.b) >  && .b[] == ' ' {
		++
		// the newline index is a relative index, and lines below trimmed `s.b` by `n`,
		// so the relative newline index also shifted forward. it's safe to decrease
		// to a minus value, it means it's invalid, and will find the newline again.
		.nextNewLine--
	}
	.hLen += 
	.b = .b[:]
	if .nextNewLine >= 0 {
		 = .nextNewLine
		.nextNewLine = -1
	} else {
		 = bytes.IndexByte(.b, nChar)
	}
	if  < 0 {
		.err = errNeedMore
		return false
	}
	 := false
	for {
		if +1 >= len(.b) {
			break
		}
		if .b[+1] != ' ' && .b[+1] != '\t' {
			break
		}
		 := bytes.IndexByte(.b[+1:], nChar)
		if  <= 0 {
			break
		} else if  == 1 && .b[+1] == rChar {
			break
		}
		 :=  +  + 1
		if  := bytes.IndexByte(.b[+1:], ':');  >= 0 {
			.nextColon = 
			.nextNewLine =  -  - 1
			break
		}
		 = true
		 = 
	}
	if  >= len(.b) {
		.err = errNeedMore
		return false
	}
	 := .b
	.value = .b[:]
	.hLen +=  + 1
	.b = .b[+1:]

	if  > 0 && .value[-1] == rChar {
		--
	}
	for  > 0 && .value[-1] == ' ' {
		--
	}
	.value = .value[:]
	if  {
		.value, .b, .hLen = normalizeHeaderValue(.value, , .hLen)
	}
	return true
}

type headerValueScanner struct {
	b     []byte
	value []byte
}

func ( *headerValueScanner) () bool {
	 := .b
	if len() == 0 {
		return false
	}
	 := bytes.IndexByte(, ',')
	if  < 0 {
		.value = stripSpace()
		.b = [len():]
		return true
	}
	.value = stripSpace([:])
	.b = [+1:]
	return true
}

func stripSpace( []byte) []byte {
	for len() > 0 && [0] == ' ' {
		 = [1:]
	}
	for len() > 0 && [len()-1] == ' ' {
		 = [:len()-1]
	}
	return 
}

func hasHeaderValue(,  []byte) bool {
	var  headerValueScanner
	.b = 
	for .next() {
		if caseInsensitiveCompare(.value, ) {
			return true
		}
	}
	return false
}

func nextLine( []byte) ([]byte, []byte, error) {
	 := bytes.IndexByte(, nChar)
	if  < 0 {
		return nil, nil, errNeedMore
	}
	 := 
	if  > 0 && [-1] == rChar {
		--
	}
	return [:], [+1:], nil
}

func initHeaderKV( *argsKV, ,  string,  bool) {
	.key = getHeaderKeyBytes(, , )
	// https://tools.ietf.org/html/rfc7230#section-3.2.4
	.value = append(.value[:0], ...)
	.value = removeNewLines(.value)
}

func getHeaderKeyBytes( *argsKV,  string,  bool) []byte {
	.key = append(.key[:0], ...)
	normalizeHeaderKey(.key, )
	return .key
}

func normalizeHeaderValue(,  []byte,  int) (,  []byte,  int) {
	 = 
	 := len()
	if  <= 0 {
		return
	}
	 := 0
	 := 0
	 := false
	for  := 0;  < ; ++ {
		 := []
		switch {
		case  == rChar ||  == nChar:
			++
			if  == nChar {
				 = true
			}
			continue
		case  &&  == '\t':
			 = ' '
		default:
			 = false
		}
		[] = 
		++
	}

	 = [:]
	copy([:], [+:])

	// Check if we need to skip \r\n or just \n
	 := 0
	if [] == rChar {
		if [+1] == nChar {
			 += 2
		} else {
			++
		}
	} else if [] == nChar {
		++
	}

	 = [+ : len()-]
	 =  - 
	return
}

func normalizeHeaderKey( []byte,  bool) {
	if  {
		return
	}

	 := len()
	if  == 0 {
		return
	}

	[0] = toUpperTable[[0]]
	for  := 1;  < ; ++ {
		 := &[]
		if * == '-' {
			++
			if  <  {
				[] = toUpperTable[[]]
			}
			continue
		}
		* = toLowerTable[*]
	}
}

// removeNewLines will replace `\r` and `\n` with an empty space
func removeNewLines( []byte) []byte {
	// check if a `\r` is present and save the position.
	// if no `\r` is found, check if a `\n` is present.
	 := bytes.IndexByte(, rChar)
	 := bytes.IndexByte(, nChar)
	 := 0

	switch {
	case  != -1:
		if  >  {
			 = 
		} else if  != -1 {
			 = 
		}
	case  != -1:
		 = 
	default:
		return 
	}

	for  := ;  < len(); ++ {
		switch [] {
		case rChar, nChar:
			[] = ' '
		default:
			continue
		}
	}
	return 
}

// AppendNormalizedHeaderKey appends normalized header key (name) to dst
// and returns the resulting dst.
//
// Normalized header key starts with uppercase letter. The first letters
// after dashes are also uppercased. All the other letters are lowercased.
// Examples:
//
//   - coNTENT-TYPe -> Content-Type
//   - HOST -> Host
//   - foo-bar-baz -> Foo-Bar-Baz
func ( []byte,  string) []byte {
	 = append(, ...)
	normalizeHeaderKey([len()-len():], false)
	return 
}

// AppendNormalizedHeaderKeyBytes appends normalized header key (name) to dst
// and returns the resulting dst.
//
// Normalized header key starts with uppercase letter. The first letters
// after dashes are also uppercased. All the other letters are lowercased.
// Examples:
//
//   - coNTENT-TYPe -> Content-Type
//   - HOST -> Host
//   - foo-bar-baz -> Foo-Bar-Baz
func (,  []byte) []byte {
	return AppendNormalizedHeaderKey(, b2s())
}

func appendArgsKeyBytes( []byte,  []argsKV,  []byte) []byte {
	for ,  := 0, len();  < ; ++ {
		 := &[]
		 = append(, .key...)
		if +1 <  {
			 = append(, ...)
		}
	}
	return 
}

var (
	errNeedMore    = errors.New("need more data: cannot find trailing lf")
	errInvalidName = errors.New("invalid header name")
	errSmallBuffer = errors.New("small read buffer. Increase ReadBufferSize")
)

// ErrNothingRead is returned when a keep-alive connection is closed,
// either because the remote closed it or because of a read timeout.
type ErrNothingRead struct {
	error
}

// ErrSmallBuffer is returned when the provided buffer size is too small
// for reading request and/or response headers.
//
// ReadBufferSize value from Server or clients should reduce the number
// of such errors.
type ErrSmallBuffer struct {
	error
}

func mustPeekBuffered( *bufio.Reader) []byte {
	,  := .Peek(.Buffered())
	if len() == 0 ||  != nil {
		panic(fmt.Sprintf("bufio.Reader.Peek() returned unexpected data (%q, %v)", , ))
	}
	return 
}

func mustDiscard( *bufio.Reader,  int) {
	if ,  := .Discard();  != nil {
		panic(fmt.Sprintf("bufio.Reader.Discard(%d) failed: %v", , ))
	}
}