func (ctx *RequestCtx) Hijacked() bool {
	return ctx.hijackHandler != nil
}
Hijacked returns true after Hijack is called.
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
}