func (c *Context) Redirect(url string, status int) {
	http.Redirect(c.Res, c.Req, url, status)
}
Redirect redirects the client to the url with status code.
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
}