func (ctx *Context) OkStream(contentType string, r io.Reader) error {
	return ctx.Stream(http.StatusOK, contentType, r)
}
OkStream is a wrap of ctx.Stream with http.StatusOK
package gear
import (
	"bytes"
	"context"
	"encoding/json"
	"encoding/xml"
	"fmt"
	"io"
	"io/ioutil"
	"mime"
	"net"
	"net/http"
	"net/url"
	"strings"
	"time"
	"github.com/go-http-utils/cookie"
	"github.com/go-http-utils/negotiator"
)
type contextKey int
const (
	isInheritedContext contextKey = iota
	isGearContext
	paramsKey
	routerNodeKey
	routerRootKey
)
type Any interface {
	New(ctx *Context) (interface{}, error)
}
type BodyTemplate interface {
	Validate() error
}
type Context struct {
	app     *App
	Req     *http.Request
	Res     *Response
	Cookies *cookie.Cookies  
	Host    string
	Method  string
	Path    string
	StartAt time.Time
	query     url.Values
	ctx       context.Context
	cancelCtx context.CancelFunc
	done      <-chan struct{}
	kv        map[interface{}]interface{}
}
func NewContext(app *App, w http.ResponseWriter, r *http.Request) *Context {
	ctx := Context{
		app: app,
		Res: &Response{w: w, rw: w, handlerHeader: w.Header()},
		Host:    r.Host,
		Method:  r.Method,
		Path:    r.URL.Path,
		StartAt: time.Now().UTC(),
		Cookies: cookie.New(w, r, app.keys...),
		kv:      make(map[interface{}]interface{}),
	}
	if app.serverName != "" {
		ctx.SetHeader(HeaderServer, app.serverName)
	}
	if app.timeout <= 0 {
		ctx.ctx, ctx.cancelCtx = context.WithCancel(r.Context())
	} else {
		ctx.ctx, ctx.cancelCtx = context.WithTimeout(r.Context(), app.timeout)
	}
	ctx.ctx = context.WithValue(ctx.ctx, isInheritedContext, struct{}{})
	ctx.Req = r.WithContext(ctx.ctx)
	if app.withContext != nil {
		ctx.WithContext(app.withContext(ctx.Req))
	}
	ctx.done = ctx.ctx.Done()
	return &ctx
}
func (ctx *Context) Deadline() (time.Time, bool) {
	return ctx.ctx.Deadline()
}
func (ctx *Context) Done() <-chan struct{} {
	return ctx.ctx.Done()
}
func (ctx *Context) Err() error {
	return ctx.ctx.Err()
}
func (ctx *Context) Value(key interface{}) (val interface{}) {
	if key == isGearContext {
		return struct{}{}
	}
	return ctx.ctx.Value(key)
}
func (ctx *Context) Cancel() {
	ctx.Res.ended.setTrue()  
	ctx.Res.afterHooks = nil
	ctx.cancelCtx()
}
func (ctx *Context) WithCancel() (context.Context, context.CancelFunc) {
	return context.WithCancel(ctx.ctx)
}
func (ctx *Context) WithDeadline(deadline time.Time) (context.Context, context.CancelFunc) {
	return context.WithDeadline(ctx.ctx, deadline)
}
func (ctx *Context) WithTimeout(timeout time.Duration) (context.Context, context.CancelFunc) {
	return context.WithTimeout(ctx.ctx, timeout)
}
func (ctx *Context) WithValue(key, val interface{}) context.Context {
	return context.WithValue(ctx.ctx, key, val)
}
func (ctx *Context) Context() context.Context {
	return ctx.ctx
}
func (ctx *Context) WithContext(c context.Context) {
	if c.Value(isGearContext) != nil {
		panic(Err.WithMsg("should not use *gear.Context as parent context, please use ctx.Context()"))
	}
	if c.Value(isInheritedContext) == nil {
		panic(Err.WithMsg("the context is not created from ctx.Context()"))
	}
	ctx.Req = ctx.Req.WithContext(c)
	ctx.ctx = c
}
func (ctx *Context) LogErr(err error) {
	ctx.app.Error(err)
}
func (ctx *Context) Timing(dt time.Duration, fn func(context.Context)) (err error) {
	ct, cancel := ctx.WithTimeout(dt)
	defer cancel()
	ch := make(chan error, 1)  
	go tryRunTiming(ct, fn, ch)
	select {
	case <-ct.Done():
		err = ct.Err()
	case err = <-ch:
	}
	return
}
func (ctx *Context) Any(any interface{}) (val interface{}, err error) {
	var ok bool
	if val, ok = ctx.kv[any]; !ok {
		switch v := any.(type) {
		case Any:
			if val, err = v.New(ctx); err == nil {
				ctx.kv[any] = val
			}
		default:
			return nil, Err.WithMsg("non-existent key")
		}
	}
	return
}
func (ctx *Context) MustAny(any interface{}) interface{} {
	val, err := ctx.Any(any)
	if err != nil {
		panic(err)
	}
	return val
}
func (ctx *Context) SetAny(key, val interface{}) {
	ctx.kv[key] = val
}
func (ctx *Context) Setting(key interface{}) interface{} {
	if val, ok := ctx.app.settings[key]; ok {
		return val
	}
	return nil
}
func (ctx *Context) IP(trustedProxy ...bool) net.IP {
	trusted := ctx.Setting(SetTrustedProxy).(bool)
	if len(trustedProxy) > 0 {
		trusted = trustedProxy[0]
	}
	var ip string
	if trusted {
		ip = ctx.Req.Header.Get(HeaderXRealIP)
		if ip == "" {
			ip = ctx.Req.Header.Get(HeaderXForwardedFor)
			if i := strings.IndexByte(ip, ','); i > 0 {
				ip = ip[0:i]
			}
		}
	}
	if ip == "" {
		ra := ctx.Req.RemoteAddr
		ip, _, _ = net.SplitHostPort(ra)
	}
	return net.ParseIP(ip)
}
func (ctx *Context) Protocol(trustedProxy ...bool) string {
	return ctx.Scheme(trustedProxy...)
}
func (ctx *Context) Scheme(trustedProxy ...bool) string {
	trusted := ctx.Setting(SetTrustedProxy).(bool)
	if len(trustedProxy) > 0 {
		trusted = trustedProxy[0]
	}
	var s string
	if trusted {
		if s = ctx.GetHeader(HeaderXRealScheme); s == "" {
			if s = ctx.GetHeader(HeaderXForwardedProto); s == "" {
				s = ctx.GetHeader(HeaderXForwardedScheme)
			}
		}
		s = strings.ToLower(s)
	}
	if s == "" {
		if ctx.Req.TLS != nil {
			s = "https"
		} else {
			s = "http"
		}
	}
	return s
}
func (ctx *Context) AcceptType(preferred ...string) string {
	return negotiator.New(ctx.Req.Header).Type(preferred...)
}
func (ctx *Context) AcceptLanguage(preferred ...string) string {
	return negotiator.New(ctx.Req.Header).Language(preferred...)
}
func (ctx *Context) AcceptEncoding(preferred ...string) string {
	return negotiator.New(ctx.Req.Header).Encoding(preferred...)
}
func (ctx *Context) AcceptCharset(preferred ...string) string {
	return negotiator.New(ctx.Req.Header).Charset(preferred...)
}
func (ctx *Context) Param(key string) (val string) {
	if res, _ := ctx.Any(paramsKey); res != nil {
		val, _ = res.(map[string]string)[key]
	}
	return
}
func (ctx *Context) Query(name string) string {
	if ctx.query == nil {
		ctx.query = ctx.Req.URL.Query()
	}
	return ctx.query.Get(name)
}
func (ctx *Context) QueryAll(name string) []string {
	if ctx.query == nil {
		ctx.query = ctx.Req.URL.Query()
	}
	return ctx.query[name]
}
func (ctx *Context) ParseBody(body BodyTemplate) error {
	if ctx.app.bodyParser == nil {
		return Err.WithMsg("bodyParser not registered")
	}
	if ctx.Req.Body == nil {
		return Err.WithMsg("missing request body")
	}
	var err error
	var buf []byte
	var mediaType string
	var encoding string
	var params map[string]string
	if mediaType = ctx.GetHeader(HeaderContentType); mediaType == "" {
		mediaType = MIMEOctetStream
	}
	ctx.SetAny("GEAR_REQUEST_CONTENT_TYPE", mediaType)
	if mediaType, params, err = mime.ParseMediaType(mediaType); err != nil {
		return ErrUnsupportedMediaType.From(err)
	}
	b := ctx.Req.Body
	if encoding = ctx.GetHeader(HeaderContentEncoding); encoding != "" {
		if b, err = Decompress(encoding, ctx.Req.Body); err != nil {
			return ErrBadRequest.From(err)
		}
	}
	reader := http.MaxBytesReader(ctx.Res, b, ctx.app.bodyParser.MaxBytes())
	defer reader.Close()
	if buf, err = ioutil.ReadAll(reader); err != nil {
		return ErrRequestEntityTooLarge.From(err)
	}
	ctx.SetAny("GEAR_REQUEST_BODY", buf[:])
	if err = ctx.app.bodyParser.Parse(buf, body, mediaType, params["charset"]); err != nil {
		return ErrBadRequest.From(err)
	}
	if err = body.Validate(); err != nil {
		return ErrBadRequest.From(err)
	}
	return nil
}
func (ctx *Context) ParseURL(body BodyTemplate) error {
	if ctx.app.urlParser == nil {
		return Err.WithMsg("urlParser not registered")
	}
	if err := ctx.app.urlParser.Parse(ctx.Req.URL.Query(), body, "query"); err != nil {
		return ErrBadRequest.From(err)
	}
	if res, _ := ctx.Any(paramsKey); res != nil {
		if params, _ := res.(map[string]string); len(params) > 0 {
			paramValues := make(map[string][]string)
			for k, v := range params {
				paramValues[k] = []string{v}
			}
			if err := ctx.app.urlParser.Parse(paramValues, body, "param"); err != nil {
				return ErrBadRequest.From(err)
			}
		}
	}
	if err := body.Validate(); err != nil {
		return ErrBadRequest.From(err)
	}
	return nil
}
func (ctx *Context) GetHeader(key string) string {
	switch key {
	case "Referer", "referer", "Referrer", "referrer":
		if val := ctx.Req.Header.Get("Referer"); val != "" {
			return val
		}
		return ctx.Req.Header.Get("Referrer")
	default:
		return ctx.Req.Header.Get(key)
	}
}
func (ctx *Context) GetHeaders(key string) []string {
	switch key {
	case "Referer", "referer", "Referrer", "referrer":
		if vals := getHeaderValues(ctx.Req.Header, "Referer"); len(vals) > 0 {
			return vals
		}
		return getHeaderValues(ctx.Req.Header, "Referrer")
	default:
		return getHeaderValues(ctx.Req.Header, key)
	}
}
func (ctx *Context) SetHeader(key, value string) {
	ctx.Res.Set(key, value)
}
func (ctx *Context) Status(code int) {
	ctx.Res.status = code
}
func (ctx *Context) Type(str string) {
	ctx.Res.Set(HeaderContentType, str)
}
func (ctx *Context) HTML(code int, str string) error {
	ctx.Type(MIMETextHTMLCharsetUTF8)
	return ctx.End(code, []byte(str))
}
func (ctx *Context) JSON(code int, val interface{}) error {
	buf, err := json.Marshal(val)
	if err != nil {
		return err
	}
	return ctx.JSONBlob(code, buf)
}
func (ctx *Context) JSONBlob(code int, buf []byte) error {
	ctx.Type(MIMEApplicationJSONCharsetUTF8)
	return ctx.End(code, buf)
}
func (ctx *Context) JSONP(code int, callback string, val interface{}) error {
	buf, err := json.Marshal(val)
	if err != nil {
		return err
	}
	return ctx.JSONPBlob(code, callback, buf)
}
func (ctx *Context) JSONPBlob(code int, callback string, buf []byte) error {
	ctx.Type(MIMEApplicationJavaScriptCharsetUTF8)
	ctx.SetHeader(HeaderXContentTypeOptions, "nosniff")
	b := []byte(fmt.Sprintf(`  typeof %s === "function" && %s(`, callback, callback))
	b = append(b, buf...)
	return ctx.End(code, append(b, ')', ';'))
}
func (ctx *Context) XML(code int, val interface{}) error {
	buf, err := xml.Marshal(val)
	if err != nil {
		return err
	}
	return ctx.XMLBlob(code, buf)
}
func (ctx *Context) XMLBlob(code int, buf []byte) error {
	ctx.Type(MIMEApplicationXMLCharsetUTF8)
	return ctx.End(code, buf)
}
func (ctx *Context) Send(code int, data interface{}) (err error) {
	if ctx.app.sender == nil {
		return Err.WithMsg("sender not registered")
	}
	return ctx.app.sender.Send(ctx, code, data)
}
func (ctx *Context) Render(code int, name string, data interface{}) (err error) {
	if ctx.app.renderer == nil {
		return Err.WithMsg("renderer not registered")
	}
	buf := new(bytes.Buffer)
	if err = ctx.app.renderer.Render(ctx, buf, name, data); err == nil {
		ctx.Type(MIMETextHTMLCharsetUTF8)
		return ctx.End(code, buf.Bytes())
	}
	return
}
func (ctx *Context) Stream(code int, contentType string, r io.Reader) (err error) {
	if ctx.Res.ended.swapTrue() {
		ctx.Status(code)
		ctx.Type(contentType)
		_, err = io.Copy(ctx.Res, r)
	} else {
		err = ErrInternalServerError.WithMsg("request ended before ctx.Stream")
	}
	return
}
func (ctx *Context) Attachment(name string, modtime time.Time, content io.ReadSeeker, inline ...bool) (err error) {
	if ctx.Res.ended.swapTrue() {
		dispositionType := "attachment"
		if len(inline) > 0 && inline[0] {
			dispositionType = "inline"
		}
		ctx.SetHeader(HeaderContentDisposition, ContentDisposition(name, dispositionType))
		http.ServeContent(ctx.Res, ctx.Req, name, modtime, content)
	} else {
		err = ErrInternalServerError.WithMsg("request ended before ctx.Attachment")
	}
	return
}
func (ctx *Context) Redirect(url string) (err error) {
	if ctx.Res.ended.swapTrue() {
		if !isRedirectStatus(ctx.Res.status) {
			ctx.Res.status = http.StatusFound
		}
		http.Redirect(ctx.Res, ctx.Req, url, ctx.Res.status)
	} else {
		err = ErrInternalServerError.WithMsg("request ended before ctx.Redirect")
	}
	return
}
func (ctx *Context) OkHTML(str string) error {
	return ctx.HTML(http.StatusOK, str)
}
func (ctx *Context) OkJSON(val interface{}) error {
	return ctx.JSON(http.StatusOK, val)
}
func (ctx *Context) OkXML(val interface{}) error {
	return ctx.XML(http.StatusOK, val)
}
func (ctx *Context) OkSend(val interface{}) error {
	return ctx.Send(http.StatusOK, val)
}
func (ctx *Context) OkRender(name string, val interface{}) error {
	return ctx.Render(http.StatusOK, name, val)
}