2018-02-07 22:25:00 +00:00
|
|
|
package snap
|
|
|
|
|
2018-03-24 16:12:02 +00:00
|
|
|
import (
|
2023-05-29 20:21:08 +00:00
|
|
|
"bytes"
|
2018-03-24 16:12:02 +00:00
|
|
|
"encoding/json"
|
2019-01-04 00:38:02 +00:00
|
|
|
"io/ioutil"
|
|
|
|
"net/http"
|
|
|
|
|
2023-05-23 14:09:57 +00:00
|
|
|
"git.twelvetwelve.org/library/snap/auth"
|
2023-05-29 20:38:37 +00:00
|
|
|
"github.com/gorilla/mux"
|
2018-03-24 16:12:02 +00:00
|
|
|
)
|
2018-02-07 22:25:00 +00:00
|
|
|
|
|
|
|
type Context struct {
|
2019-01-04 00:38:02 +00:00
|
|
|
srv *Server
|
2018-03-24 16:12:02 +00:00
|
|
|
auth *auth.AuthData
|
|
|
|
|
2019-01-04 00:38:02 +00:00
|
|
|
w http.ResponseWriter
|
|
|
|
r *http.Request
|
2023-05-29 20:21:08 +00:00
|
|
|
vars *Vars
|
|
|
|
form *Form
|
2018-02-07 22:25:00 +00:00
|
|
|
}
|
|
|
|
|
2018-02-11 00:17:14 +00:00
|
|
|
type SnapContent struct {
|
2021-05-29 21:14:15 +00:00
|
|
|
User string
|
|
|
|
UserProperties map[string]string
|
|
|
|
Theme string
|
|
|
|
Meta map[string]string
|
|
|
|
Content interface{}
|
2018-02-11 00:17:14 +00:00
|
|
|
}
|
2018-02-07 22:25:00 +00:00
|
|
|
|
|
|
|
func (c *Context) GetRequest() *http.Request {
|
|
|
|
return c.r
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Context) Writer() http.ResponseWriter {
|
|
|
|
return c.w
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Context) GetUser() string {
|
2018-03-24 16:12:02 +00:00
|
|
|
if c.auth == nil {
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
return c.auth.User
|
2018-02-07 22:25:00 +00:00
|
|
|
}
|
|
|
|
|
2018-02-11 00:17:14 +00:00
|
|
|
func (c *Context) Error(code int, msg string) {
|
|
|
|
c.srv.renderError(c.w, code, msg)
|
|
|
|
}
|
|
|
|
|
2021-05-29 21:14:15 +00:00
|
|
|
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))
|
|
|
|
}
|
|
|
|
|
2018-03-24 16:12:02 +00:00
|
|
|
func (c *Context) Reply(msg string) {
|
|
|
|
c.srv.reply(c.w, msg)
|
|
|
|
}
|
|
|
|
|
2021-05-29 21:14:15 +00:00
|
|
|
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)
|
|
|
|
}
|
|
|
|
|
2018-03-24 16:12:02 +00:00
|
|
|
func (c *Context) ReplyObject(obj interface{}) {
|
2023-05-29 20:21:08 +00:00
|
|
|
compact := c.r.Header.Get("Compact")
|
2018-03-24 16:12:02 +00:00
|
|
|
msg, err := json.Marshal(obj)
|
|
|
|
if err != nil {
|
2021-05-29 21:14:15 +00:00
|
|
|
c.Error(http.StatusInternalServerError, "Internal Server Error")
|
|
|
|
return
|
2018-03-24 16:12:02 +00:00
|
|
|
}
|
2023-05-29 20:21:08 +00:00
|
|
|
|
|
|
|
if compact == "" {
|
|
|
|
var pretty bytes.Buffer
|
|
|
|
err := json.Indent(&pretty, msg, "", " ")
|
|
|
|
if err == nil {
|
|
|
|
msg = pretty.Bytes()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-24 16:12:02 +00:00
|
|
|
c.Reply(string(msg))
|
|
|
|
}
|
|
|
|
|
2019-01-04 00:38:02 +00:00
|
|
|
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)
|
|
|
|
}
|
2018-02-07 22:25:00 +00:00
|
|
|
|
|
|
|
func (c *Context) Render(tmpl string, content interface{}) {
|
|
|
|
c.srv.render(c.w, tmpl, content)
|
|
|
|
}
|
|
|
|
|
2018-02-11 00:17:14 +00:00
|
|
|
func (c *Context) RenderEx(tmpl string, content interface{}) {
|
2019-01-04 00:38:02 +00:00
|
|
|
cnt := SnapContent{
|
|
|
|
User: c.GetUser(),
|
|
|
|
Theme: c.srv.theme,
|
2021-05-29 21:14:15 +00:00
|
|
|
Meta: c.srv.meta,
|
2019-01-04 00:38:02 +00:00
|
|
|
Content: content,
|
2018-02-11 00:17:14 +00:00
|
|
|
}
|
2021-06-18 19:43:52 +00:00
|
|
|
|
|
|
|
if c.auth != nil {
|
|
|
|
cnt.UserProperties = c.auth.Properties
|
|
|
|
}
|
|
|
|
|
2018-02-11 00:17:14 +00:00
|
|
|
c.srv.render(c.w, tmpl, &cnt)
|
|
|
|
}
|
|
|
|
|
2021-05-29 21:14:15 +00:00
|
|
|
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,
|
|
|
|
}
|
|
|
|
|
|
|
|
if c.auth != nil {
|
|
|
|
cnt.UserProperties = c.auth.Properties
|
|
|
|
}
|
|
|
|
|
|
|
|
c.srv.render(c.w, tmpl, &cnt)
|
|
|
|
}
|
|
|
|
|
2023-05-29 20:21:08 +00:00
|
|
|
func (c *Context) Form() (*Options, error) {
|
|
|
|
if c.form != nil {
|
|
|
|
return &Options{
|
|
|
|
kv: c.form,
|
|
|
|
}, nil
|
2018-02-11 00:17:14 +00:00
|
|
|
}
|
2019-01-04 00:38:02 +00:00
|
|
|
|
2023-05-29 20:21:08 +00:00
|
|
|
err := c.r.ParseForm()
|
2019-01-04 00:38:02 +00:00
|
|
|
if err != nil {
|
2023-05-29 20:21:08 +00:00
|
|
|
return nil, err
|
2019-01-04 00:38:02 +00:00
|
|
|
}
|
2023-05-29 20:21:08 +00:00
|
|
|
c.form = &Form{
|
|
|
|
r: c.r,
|
2021-05-29 21:14:15 +00:00
|
|
|
}
|
2023-05-29 20:21:08 +00:00
|
|
|
|
|
|
|
return &Options{
|
|
|
|
kv: c.form,
|
|
|
|
}, nil
|
2021-05-29 21:14:15 +00:00
|
|
|
}
|
|
|
|
|
2019-01-04 00:38:02 +00:00
|
|
|
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)
|
|
|
|
}
|
2019-10-20 14:01:21 +00:00
|
|
|
|
2021-05-29 21:14:15 +00:00
|
|
|
func (c *Context) QueryHas(key string) bool {
|
|
|
|
_, ok := c.r.URL.Query()[key]
|
|
|
|
return ok
|
|
|
|
}
|
|
|
|
|
2019-10-20 14:01:21 +00:00
|
|
|
func (c *Context) QueryValueWithDefault(key string, def string) string {
|
|
|
|
val := c.r.URL.Query().Get(key)
|
|
|
|
if val == "" {
|
|
|
|
return def
|
|
|
|
}
|
|
|
|
return val
|
|
|
|
}
|
2023-05-29 20:21:08 +00:00
|
|
|
|
|
|
|
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 {
|
2023-05-29 20:38:37 +00:00
|
|
|
if c.vars == nil {
|
|
|
|
c.vars = &Vars{
|
|
|
|
vars: mux.Vars(c.r),
|
2023-05-29 20:21:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return &Options{
|
2023-05-29 20:38:37 +00:00
|
|
|
kv: c.vars,
|
2023-05-29 20:21:08 +00:00
|
|
|
}
|
|
|
|
}
|