package snap import ( "bytes" "encoding/json" "io/ioutil" "net/http" "git.twelvetwelve.org/library/snap/auth" "github.com/gorilla/mux" ) type Context struct { srv *Server auth *auth.AuthData w http.ResponseWriter r *http.Request vars *Vars form *Form } type SnapContent struct { User string UserProperties map[string]string Theme string Meta map[string]string Content interface{} Version int64 } func (c *Context) GetRequest() *http.Request { return c.r } func (c *Context) Writer() http.ResponseWriter { return c.w } func (c *Context) GetUser() string { if c.auth == nil { return "" } return c.auth.User } func (c *Context) Error(code int, msg string) { c.srv.renderError(c.w, code, msg) } func (c *Context) ErrorObject(code int, obj interface{}) { msg, err := json.Marshal(obj) if err != nil { c.Error(http.StatusInternalServerError, "Internal Server Error") return } c.Error(code, string(msg)) } func (c *Context) Reply(msg string) { c.srv.reply(c.w, msg) } func (c *Context) ReplyWithHeaders(msg string, kv map[string]string) { h := c.w.Header() for k, v := range kv { h.Add(k, v) } c.srv.reply(c.w, msg) } func (c *Context) ReplyObject(obj interface{}) { compact := c.r.Header.Get("Compact") msg, err := json.Marshal(obj) if err != nil { c.Error(http.StatusInternalServerError, "Internal Server Error") return } if compact == "" { var pretty bytes.Buffer err := json.Indent(&pretty, msg, "", " ") if err == nil { msg = pretty.Bytes() } } c.Reply(string(msg)) } func (c *Context) GetObject(obj interface{}) error { data, err := ioutil.ReadAll(c.r.Body) defer c.r.Body.Close() if err != nil { return err } return json.Unmarshal(data, obj) } func (c *Context) Render(tmpl string, content interface{}) { c.srv.render(c.w, tmpl, content) } func (c *Context) RenderEx(tmpl string, content interface{}) { cnt := SnapContent{ User: c.GetUser(), Theme: c.srv.theme, Meta: c.srv.meta, Content: content, Version: c.srv.version, } if c.auth != nil { cnt.UserProperties = c.auth.Properties } c.srv.render(c.w, tmpl, &cnt) } func (c *Context) RenderWithMeta(tmpl string, meta map[string]string, content interface{}) { // Merge metas if meta == nil { meta = make(map[string]string) } for k, v := range c.srv.meta { if _, ok := meta[k]; !ok { meta[k] = v } } cnt := SnapContent{ User: c.GetUser(), Theme: c.srv.theme, Meta: meta, Content: content, Version: c.srv.version, } if c.auth != nil { cnt.UserProperties = c.auth.Properties } c.srv.render(c.w, tmpl, &cnt) } func (c *Context) Form() (*Options, error) { if c.form != nil { return &Options{ kv: c.form, }, nil } err := c.r.ParseForm() if err != nil { return nil, err } c.form = &Form{ r: c.r, } return &Options{ kv: c.form, }, nil } func (c *Context) Redirect(url string) { http.Redirect(c.w, c.r, url, http.StatusSeeOther) } func (c *Context) QueryValue(key string) string { return c.r.URL.Query().Get(key) } func (c *Context) QueryHas(key string) bool { _, ok := c.r.URL.Query()[key] return ok } func (c *Context) QueryValueWithDefault(key string, def string) string { val := c.r.URL.Query().Get(key) if val == "" { return def } return val } func (c *Context) ReadObject(object interface{}) error { defer c.r.Body.Close() decoder := json.NewDecoder(c.r.Body) return decoder.Decode(object) } func (c *Context) ParseVars() *Options { if c.vars == nil { c.vars = &Vars{ vars: mux.Vars(c.r), } } return &Options{ kv: c.vars, } }