diff --git a/server/server.go b/server/server.go index e1ed94b8..0a541b68 100644 --- a/server/server.go +++ b/server/server.go @@ -263,6 +263,8 @@ func (s *Server) handle(w http.ResponseWriter, r *http.Request) { func (s *Server) handleInternal(w http.ResponseWriter, r *http.Request, v *visitor) error { if r.Method == http.MethodGet && r.URL.Path == "/" { return s.handleHome(w, r) + } else if (r.Method == http.MethodPut || r.Method == http.MethodPost) && r.URL.Path == "/" { + return s.limitRequests(s.fromMessageJSON(s.authWrite(s.handlePublish)))(w, r, v) } else if r.Method == http.MethodGet && r.URL.Path == "/example.html" { return s.handleExample(w, r) } else if r.Method == http.MethodHead && r.URL.Path == "/" { @@ -1093,6 +1095,47 @@ func (s *Server) limitRequests(next handleFunc) handleFunc { } } +func (s *Server) fromMessageJSON(next handleFunc) handleFunc { + return func(w http.ResponseWriter, r *http.Request, v *visitor) error { + body, err := util.Peak(r.Body, s.config.MessageLimit) + if err != nil { + return err + } + defer r.Body.Close() + var m publishMessage + if err := json.NewDecoder(body).Decode(&m); err != nil { + return err + } + if !topicRegex.MatchString(m.Topic) { + return errors.New("invalid message") + } + if m.Message == "" { + m.Message = emptyMessageBody + } + r.URL.Path = "/" + m.Topic + r.Body = io.NopCloser(strings.NewReader(m.Message)) + if m.Title != "" { + r.Header.Set("X-Title", m.Title) + } + if m.Priority != "" { + r.Header.Set("X-Priority", m.Priority) + } + if m.Tags != "" { + r.Header.Set("X-Tags", m.Tags) + } + if m.Attach != "" { + r.Header.Set("X-Attach", m.Attach) + } + if m.Filename != "" { + r.Header.Set("X-Filename", m.Filename) + } + if m.Click != "" { + r.Header.Set("X-Click", m.Click) + } + return next(w, r, v) + } +} + func (s *Server) authWrite(next handleFunc) handleFunc { return s.withAuth(next, auth.PermissionWrite) } diff --git a/server/types.go b/server/types.go index 9b132e25..ec8259c2 100644 --- a/server/types.go +++ b/server/types.go @@ -42,6 +42,18 @@ type attachment struct { Owner string `json:"-"` // IP address of uploader, used for rate limiting } +// publishMessage is used as input when publishing as JSON +type publishMessage struct { + Topic string `json:"topic"` + Title string `json:"title"` + Message string `json:"message"` + Priority string `json:"priority"` + Tags string `json:"tags"` + Click string `json:"click"` + Attach string `json:"attach"` + Filename string `json:"filename"` +} + // messageEncoder is a function that knows how to encode a message type messageEncoder func(msg *message) (string, error)