func (c *Context) Cookie(name string) string {
	ck, _ := c.Req.Cookie(name)
	if ck == nil {
		return ""
	}
	if encrypter == nil {
		return ck.Value
	}
	v, err := encrypter.DecryptBase64([]byte(ck.Value))
	if err != nil {
		c.DeleteCookie(name)
		return ""
	}
	return string(v)
}
Cookie returns the value of the named cookie.
If multiple cookies match the given name, only one cookie value will be returned.
If the secret key is set for app, value will be decrypted before returning.
If cookie is not found or the decryption fails, an empty string is returned.
package app
import (
	"bufio"
	"context"
	"encoding/json"
	"fmt"
	"html/template"
	"log"
	"net"
	"net/http"
	"golang.org/x/text/language"
	"github.com/gowww/check"
	"github.com/gowww/fatal"
	"github.com/gowww/i18n"
	"github.com/gowww/router"
)
type Context struct {
	Res http.ResponseWriter
	Req *http.Request
}
func contextHandle(h http.Handler) http.Handler {
	return Handler(func(c *Context) {
		cw := &contextWriter{ResponseWriter: c.Res}
		defer func() {
			if cw.status != 0 {
				c.Res.WriteHeader(cw.status)
			}
		}()
		cw.Header().Set("Cache-Control", "no-cache")
		cw.Header().Set("Connection", "keep-alive")
		h.ServeHTTP(cw, c.Req)
	})
}
type contextWriter struct {
	http.ResponseWriter
	status int
}
func (cw *contextWriter) WriteHeader(status int) {
	cw.status = status
}
func (cw *contextWriter) Write(b []byte) (int, error) {
	if cw.status != 0 {
		cw.ResponseWriter.WriteHeader(cw.status)
		cw.status = 0
	}
	return cw.ResponseWriter.Write(b)
}
func (cw *contextWriter) CloseNotify() <-chan bool {
	n, ok := cw.ResponseWriter.(http.CloseNotifier)
	if !ok {
		return nil
	}
	return n.CloseNotify()
}
func (cw *contextWriter) Flush() {
	f, ok := cw.ResponseWriter.(http.Flusher)
	if ok {
		f.Flush()
	}
}
func (cw *contextWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
	h, ok := cw.ResponseWriter.(http.Hijacker)
	if !ok {
		return nil, nil, http.ErrNotSupported
	}
	return h.Hijack()
}
func (cw *contextWriter) Push(target string, opts *http.PushOptions) error {
	p, ok := cw.ResponseWriter.(http.Pusher)
	if !ok {
		return http.ErrNotSupported
	}
	return p.Push(target, opts)
}
func (c *Context) Get(key interface{}) interface{} {
	return c.Req.Context().Value(key)
}
func (c *Context) Set(key, val interface{}) {
	c.Req = c.Req.WithContext(context.WithValue(c.Req.Context(), key, val))
}
func (c *Context) PathValue(key string) string {
	return router.Parameter(c.Req, key)
}
func (c *Context) FormValue(key string) string {
	return c.Req.FormValue(key)
}
func (c *Context) HasFormValue(key string) bool {
	return c.Req.FormValue(key) != ""
}
func (c *Context) Write(b []byte) (int, error) {
	return c.Res.Write(b)
}
func (c *Context) Text(s string) {
	c.Write([]byte(s))
}
func (c *Context) Textf(s string, a ...interface{}) {
	fmt.Fprintf(c.Res, s, a...)
}
func (c *Context) Bytes(b []byte) {
	c.Write(b)
}
func (c *Context) Status(code int) *Context {
	c.Res.WriteHeader(code)
	return c
}
func (c *Context) View(name string, data ...ViewData) {
	mdata := mergeViewData(data)
	mdata["c"] = c
	switch errs := mdata["errors"].(type) {
	case check.TranslatedErrors:
		break
	case check.Errors:
		mdata["errors"] = c.TErrors(errs)
	default:
		mdata["errors"] = make(check.TranslatedErrors)
	}
	err := views.ExecuteTemplate(c, name, mdata)
	if err != nil {
		c.Panic(err)
	}
}
func (c *Context) JSON(v interface{}) {
	c.Res.Header().Set("Content-Type", "application/json")
	enc := json.NewEncoder(c.Res)
	if vjson, ok := v.(interface {
		JSON() interface{}
	}); ok {
		if err := enc.Encode(vjson.JSON()); err != nil {
			c.Panic(err)
		}
		return
	}
	if err := enc.Encode(v); err != nil {
		c.Panic(err)
	}
}
func (c *Context) Check(checker check.Checker) check.Errors {
	return checker.CheckRequest(c.Req)
}
func (c *Context) TErrors(errs check.Errors) check.TranslatedErrors {
	return errs.T(i18n.RequestTranslator(c.Req))
}
func (c *Context) BadRequest(checker check.Checker, view string, data ...ViewData) bool {
	errs := c.Check(checker)
	if errs.Empty() {
		return false
	}
	c.Status(http.StatusBadRequest)
	if view == "" {
		c.JSON(errs)
	} else {
		data = append(data, ViewData{"errors": errs})
		c.View(view, data...)
	}
	return true
}
func (c *Context) Redirect(url string, status int) {
	http.Redirect(c.Res, c.Req, url, status)
}