func (ctx *RequestCtx) IsTrace() bool {
	return ctx.Request.Header.IsTrace()
}
IsTrace returns true if request method is TRACE.
package fasthttp
import (
	"bufio"
	"context"
	"crypto/tls"
	"errors"
	"fmt"
	"io"
	"log"
	"mime/multipart"
	"net"
	"os"
	"strings"
	"sync"
	"sync/atomic"
	"time"
)
var errNoCertOrKeyProvided = errors.New("Cert or key has not provided")
var (
	ErrAlreadyServing = errors.New("Server is already serving connections")
)
func ServeConn(c net.Conn, handler RequestHandler) error {
	v := serverPool.Get()
	if v == nil {
		v = &Server{}
	}
	s := v.(*Server)
	s.Handler = handler
	err := s.ServeConn(c)
	s.Handler = nil
	serverPool.Put(v)
	return err
}
var serverPool sync.Pool
func Serve(ln net.Listener, handler RequestHandler) error {
	s := &Server{
		Handler: handler,
	}
	return s.Serve(ln)
}
func ServeTLS(ln net.Listener, certFile, keyFile string, handler RequestHandler) error {
	s := &Server{
		Handler: handler,
	}
	return s.ServeTLS(ln, certFile, keyFile)
}
func ServeTLSEmbed(ln net.Listener, certData, keyData []byte, handler RequestHandler) error {
	s := &Server{
		Handler: handler,
	}
	return s.ServeTLSEmbed(ln, certData, keyData)
}
func ListenAndServe(addr string, handler RequestHandler) error {
	s := &Server{
		Handler: handler,
	}
	return s.ListenAndServe(addr)
}
func ListenAndServeUpSize(addr string, handler RequestHandler, uploadSize int) error {
	if uploadSize == 0 {
		uploadSize = 8 << 20
	}
	s := &Server{
		Handler:            handler,
		MaxRequestBodySize: uploadSize,
	}
	return s.ListenAndServe(addr)
}
func ListenAndServeUNIX(addr string, mode os.FileMode, handler RequestHandler) error {
	s := &Server{
		Handler: handler,
	}
	return s.ListenAndServeUNIX(addr, mode)
}
func ListenAndServeTLS(addr, certFile, keyFile string, handler RequestHandler) error {
	s := &Server{
		Handler: handler,
	}
	return s.ListenAndServeTLS(addr, certFile, keyFile)
}
func ListenAndServeTLSEmbed(addr string, certData, keyData []byte, handler RequestHandler) error {
	s := &Server{
		Handler: handler,
	}
	return s.ListenAndServeTLSEmbed(addr, certData, keyData)
}
type RequestHandler func(ctx *RequestCtx)
type ServeHandler func(c net.Conn) error
type Server struct {
	noCopy noCopy
	Handler RequestHandler
	ErrorHandler func(ctx *RequestCtx, err error)
	HeaderReceived func(header *RequestHeader) RequestConfig
	Name string
	Concurrency int
	DisableKeepalive bool
	ReadBufferSize int
	WriteBufferSize int
	ReadTimeout time.Duration
	WriteTimeout time.Duration
	IdleTimeout time.Duration
	MaxConnsPerIP int
	MaxRequestsPerConn int
	MaxKeepaliveDuration time.Duration
	TCPKeepalive bool
	TCPKeepalivePeriod time.Duration
	MaxRequestBodySize int
	ReduceMemoryUsage bool
	GetOnly bool
	LogAllErrors bool
	DisableHeaderNamesNormalizing bool
	SleepWhenConcurrencyLimitsExceeded time.Duration
	NoDefaultServerHeader bool
	NoDefaultContentType bool
	ConnState func(net.Conn, ConnState)
	Logger Logger
	KeepHijackedConns bool
	tlsConfig  *tls.Config
	nextProtos map[string]ServeHandler
	concurrency      uint32
	concurrencyCh    chan struct{}
	perIPConnCounter perIPConnCounter
	serverName       atomic.Value
	ctxPool        sync.Pool
	readerPool     sync.Pool
	writerPool     sync.Pool
	hijackConnPool sync.Pool
	ln net.Listener
	mu   sync.Mutex
	open int32
	stop int32
	done chan struct{}
}
func TimeoutHandler(h RequestHandler, timeout time.Duration, msg string) RequestHandler {
	return TimeoutWithCodeHandler(h, timeout, msg, StatusRequestTimeout)
}
func TimeoutWithCodeHandler(h RequestHandler, timeout time.Duration, msg string, statusCode int) RequestHandler {
	if timeout <= 0 {
		return h
	}
	return func(ctx *RequestCtx) {
		concurrencyCh := ctx.s.concurrencyCh
		select {
		case concurrencyCh <- struct{}{}:
		default:
			ctx.Error(msg, StatusTooManyRequests)
			return
		}
		ch := ctx.timeoutCh
		if ch == nil {
			ch = make(chan struct{}, 1)
			ctx.timeoutCh = ch
		}
		go func() {
			h(ctx)
			ch <- struct{}{}
			<-concurrencyCh
		}()
		ctx.timeoutTimer = initTimer(ctx.timeoutTimer, timeout)
		select {
		case <-ch:
		case <-ctx.timeoutTimer.C:
			ctx.TimeoutErrorWithCode(msg, statusCode)
		}
		stopTimer(ctx.timeoutTimer)
	}
}
type RequestConfig struct {
	ReadTimeout time.Duration
	WriteTimeout time.Duration
	MaxRequestBodySize int
}
func CompressHandler(h RequestHandler) RequestHandler {
	return CompressHandlerLevel(h, CompressDefaultCompression)
}
func CompressHandlerLevel(h RequestHandler, level int) RequestHandler {
	return func(ctx *RequestCtx) {
		h(ctx)
		if ctx.Request.Header.HasAcceptEncodingBytes(strGzip) {
			ctx.Response.gzipBody(level)
		} else if ctx.Request.Header.HasAcceptEncodingBytes(strDeflate) {
			ctx.Response.deflateBody(level)
		}
	}
}
type RequestCtx struct {
	noCopy noCopy
	Request Request
	Response Response
	userValues userData
	connID         uint64
	connRequestNum uint64
	connTime       time.Time
	time time.Time
	logger ctxLogger
	s      *Server
	c      net.Conn
	fbr    firstByteReader
	timeoutResponse *Response
	timeoutCh       chan struct{}
	timeoutTimer    *time.Timer
	hijackHandler HijackHandler
}
type HijackHandler func(c net.Conn)
func (ctx *RequestCtx) Hijack(handler HijackHandler) {
	ctx.hijackHandler = handler
}
func (ctx *RequestCtx) Hijacked() bool {
	return ctx.hijackHandler != nil
}
func (ctx *RequestCtx) SetUserValue(key string, value interface{}) {
	ctx.userValues.Set(key, value)
}
func (ctx *RequestCtx) SetUserValueBytes(key []byte, value interface{}) {
	ctx.userValues.SetBytes(key, value)
}
func (ctx *RequestCtx) UserValue(key string) interface{} {
	return ctx.userValues.Get(key)
}
func (ctx *RequestCtx) UserValueBytes(key []byte) interface{} {
	return ctx.userValues.GetBytes(key)
}
func (ctx *RequestCtx) VisitUserValues(visitor func([]byte, interface{})) {
	for i, n := 0, len(ctx.userValues); i < n; i++ {
		kv := &ctx.userValues[i]
		visitor(kv.key, kv.value)
	}
}
type connTLSer interface {
	Handshake() error
	ConnectionState() tls.ConnectionState
}
func (ctx *RequestCtx) IsTLS() bool {
	_, ok := ctx.c.(connTLSer)
	return ok
}
func (ctx *RequestCtx) TLSConnectionState() *tls.ConnectionState {
	tlsConn, ok := ctx.c.(connTLSer)
	if !ok {
		return nil
	}
	state := tlsConn.ConnectionState()
	return &state
}
func (ctx *RequestCtx) Conn() net.Conn {
	return ctx.c
}
type firstByteReader struct {
	c        net.Conn
	ch       byte
	byteRead bool
}
func (r *firstByteReader) Read(b []byte) (int, error) {
	if len(b) == 0 {
		return 0, nil
	}
	nn := 0
	if !r.byteRead {
		b[0] = r.ch
		b = b[1:]
		r.byteRead = true
		nn = 1
	}
	n, err := r.c.Read(b)
	return n + nn, err
}
type Logger interface {
	Printf(format string, args ...interface{})
}
var ctxLoggerLock sync.Mutex
type ctxLogger struct {
	ctx    *RequestCtx
	logger Logger
}
func (cl *ctxLogger) Printf(format string, args ...interface{}) {
	msg := fmt.Sprintf(format, args...)
	ctxLoggerLock.Lock()
	cl.logger.Printf("%.3f %s - %s", time.Since(cl.ctx.ConnTime()).Seconds(), cl.ctx.String(), msg)
	ctxLoggerLock.Unlock()
}
var zeroTCPAddr = &net.TCPAddr{
	IP: net.IPv4zero,
}
func (ctx *RequestCtx) String() string {
	return fmt.Sprintf("#%016X - %s<->%s - %s %s", ctx.ID(), ctx.LocalAddr(), ctx.RemoteAddr(), ctx.Request.Header.Method(), ctx.URI().FullURI())
}
func (ctx *RequestCtx) ID() uint64 {
	return (ctx.connID << 32) | ctx.connRequestNum
}
func (ctx *RequestCtx) ConnID() uint64 {
	return ctx.connID
}
func (ctx *RequestCtx) Time() time.Time {
	return ctx.time
}
func (ctx *RequestCtx) ConnTime() time.Time {
	return ctx.connTime
}
func (ctx *RequestCtx) ConnRequestNum() uint64 {
	return ctx.connRequestNum
}
func (ctx *RequestCtx) SetConnectionClose() {
	ctx.Response.SetConnectionClose()
}
func (ctx *RequestCtx) SetStatusCode(statusCode int) {
	ctx.Response.SetStatusCode(statusCode)
}
func (ctx *RequestCtx) SetContentType(contentType string) {
	ctx.Response.Header.SetContentType(contentType)
}
func (ctx *RequestCtx) SetContentTypeBytes(contentType []byte) {
	ctx.Response.Header.SetContentTypeBytes(contentType)
}
func (ctx *RequestCtx) RequestURI() []byte {
	return ctx.Request.Header.RequestURI()
}
func (ctx *RequestCtx) URI() *URI {
	return ctx.Request.URI()
}
func (ctx *RequestCtx) Referer() []byte {
	return ctx.Request.Header.Referer()
}
func (ctx *RequestCtx) UserAgent() []byte {
	return ctx.Request.Header.UserAgent()
}
func (ctx *RequestCtx) Path() []byte {
	return ctx.URI().Path()
}
func (ctx *RequestCtx) Host() []byte {
	return ctx.URI().Host()
}
func (ctx *RequestCtx) QueryArgs() *Args {
	return ctx.URI().QueryArgs()
}
func (ctx *RequestCtx) PostArgs() *Args {
	return ctx.Request.PostArgs()
}
func (ctx *RequestCtx) MultipartForm() (*multipart.Form, error) {
	return ctx.Request.MultipartForm()
}
func (ctx *RequestCtx) FormFile(key string) (*multipart.FileHeader, error) {
	mf, err := ctx.MultipartForm()
	if err != nil {
		return nil, err
	}
	if mf.File == nil {
		return nil, err
	}
	fhh := mf.File[key]
	if fhh == nil {
		return nil, ErrMissingFile
	}
	return fhh[0], nil
}
var ErrMissingFile = errors.New("there is no uploaded file associated with the given key")
func SaveMultipartFile(fh *multipart.FileHeader, path string) error {
	f, err := fh.Open()
	if err != nil {
		return err
	}
	if ff, ok := f.(*os.File); ok {
		if err := f.Close(); err != nil {
			return err
		}
		if os.Rename(ff.Name(), path) == nil {
			return nil
		}
		f, err = fh.Open()
		if err != nil {
			return err
		}
	}
	defer f.Close()
	ff, err := os.Create(path)
	if err != nil {
		return err
	}
	defer ff.Close()
	_, err = copyZeroAlloc(ff, f)
	return err
}
func (ctx *RequestCtx) FormValue(key string) []byte {
	v := ctx.QueryArgs().Peek(key)
	if len(v) > 0 {
		return v
	}
	v = ctx.PostArgs().Peek(key)
	if len(v) > 0 {
		return v
	}
	mf, err := ctx.MultipartForm()
	if err == nil && mf.Value != nil {
		vv := mf.Value[key]
		if len(vv) > 0 {
			return []byte(vv[0])
		}
	}
	return nil
}
func (ctx *RequestCtx) IsGet() bool {
	return ctx.Request.Header.IsGet()
}
func (ctx *RequestCtx) IsPost() bool {
	return ctx.Request.Header.IsPost()
}
func (ctx *RequestCtx) IsPut() bool {
	return ctx.Request.Header.IsPut()
}
func (ctx *RequestCtx) IsDelete() bool {
	return ctx.Request.Header.IsDelete()
}
func (ctx *RequestCtx) IsConnect() bool {
	return ctx.Request.Header.IsConnect()
}
func (ctx *RequestCtx) IsOptions() bool {
	return ctx.Request.Header.IsOptions()
}