package main import "encoding/json" import "net/http" import "regexp" import "time" import "github.com/gin-gonic/gin" import "github.com/google/uuid" import "github.com/rs/zerolog/log" import "github.com/sneak/merp/models" func thingRegex() *regexp.Regexp { THING_REGEX, e := regexp.Compile(`^[a-zA-Z0-9\_\-]+$`) if e != nil { panic(e) } return THING_REGEX } func decodeJson(in []byte) interface{} { var out interface{} err := json.Unmarshal(in, &out) if err != nil { log.Error().Msg("error decoding json") return nil } return out } func GetLatestMerps() gin.HandlerFunc { THING_REGEX := thingRegex() orm := models.GetOrmObject() h := func(c *gin.Context) { thing := c.Param("thing") if THING_REGEX.MatchString(thing) == false { c.JSON(http.StatusPreconditionFailed, gin.H{ "this": "failed", "status": http.StatusPreconditionFailed, "because": "invalid thing format, try a-zA-Z0-9-_", }) return } var merps []*models.Merp qs := orm.QueryTable("merp").Filter("thing", thing).OrderBy("-created").Limit(50) qs.All(&merps) var output []map[string]interface{} for _, merp := range merps { outelem := make(map[string]interface{}) outelem["thing"] = merp.Thing outjs := decodeJson([]byte(merp.Content)) if outjs == nil { outelem["content"] = gin.H{} } else { outelem["content"] = outjs } outelem["created"] = merp.Created output = append(output, outelem) } c.JSON(http.StatusOK, gin.H{ "this": "succeeded", "by": "getting", "the": "merps", "with": output, }) } return h } func GetLatestMerp() gin.HandlerFunc { THING_REGEX := thingRegex() h := func(c *gin.Context) { thing := c.Param("thing") if THING_REGEX.MatchString(thing) == false { c.JSON(http.StatusPreconditionFailed, gin.H{ "this": "failed", "status": http.StatusPreconditionFailed, "because": "invalid thing format, try a-zA-Z0-9-_", }) return } c.JSON(http.StatusOK, gin.H{ "this": "succeeded", }) } return h } func HandleNewMerp() gin.HandlerFunc { // server startup time THING_REGEX := thingRegex() // establish db connection *first*, before requests orm := models.GetOrmObject() h := func(c *gin.Context) { // request time thing := c.Param("thing") if THING_REGEX.MatchString(thing) == false { log.Debug().Msgf("%s didnt match", thing) c.JSON(http.StatusPreconditionFailed, gin.H{ "this": "failed", "status": http.StatusPreconditionFailed, "because": "invalid thing format, try a-zA-Z0-9-_", }) return } log.Debug().Msgf("%s matched", thing) //web.Get(`/merp/for/([A-Za-z0-9\-\_\.]+)`, merpHandler) // FIXME rate limit this a bit on thing+clientip+json to cut down on // repeated messages content := make(map[string]interface{}) respContent := gin.H{} // FIXME support POST data as well for k, v := range c.Request.URL.Query() { content[k] = v[0] respContent[k] = v[0] } u := uuid.New() at := time.Now().UTC() atString := at.Format(time.RFC3339) serialized, jsonerr := json.MarshalIndent(content, "", " ") if jsonerr != nil { c.JSON( http.StatusPreconditionFailed, gin.H{ "this": "failed", "status": http.StatusPreconditionFailed, "because": jsonerr.Error(), }, ) return } merp := models.Merp{ Created: at, Thing: thing, Content: string(serialized), UUID: u.String(), } _, err := orm.Insert(&merp) if err != nil { c.JSON( http.StatusPreconditionFailed, gin.H{ "this": "failed", "status": http.StatusPreconditionFailed, "because": err.Error(), }, ) return } c.JSON(http.StatusOK, gin.H{ "this": "succeeded", "by": "merping", "the": "merp", "with": gin.H{ "thing": thing, "created": atString, "content": respContent, "id": u.String(), }, }) } return h }