diff options
author | Brian Picciano <mediocregopher@gmail.com> | 2022-05-20 11:17:31 -0600 |
---|---|---|
committer | Brian Picciano <mediocregopher@gmail.com> | 2022-05-20 11:17:31 -0600 |
commit | 09acb111a2b22f5794541fac175b024dd0f9100e (patch) | |
tree | 11d4578a42ad4aea968b42a2689f64c799f9176e /srv/src/api/chat.go | |
parent | f69ed83de73bbfc4b7af0931de6ced8cf12dea61 (diff) |
Rename api package to http
Diffstat (limited to 'srv/src/api/chat.go')
-rw-r--r-- | srv/src/api/chat.go | 211 |
1 files changed, 0 insertions, 211 deletions
diff --git a/srv/src/api/chat.go b/srv/src/api/chat.go deleted file mode 100644 index f4b90ef..0000000 --- a/srv/src/api/chat.go +++ /dev/null @@ -1,211 +0,0 @@ -package api - -import ( - "context" - "errors" - "fmt" - "net/http" - "strings" - "unicode" - - "github.com/gorilla/websocket" - "github.com/mediocregopher/blog.mediocregopher.com/srv/api/apiutil" - "github.com/mediocregopher/blog.mediocregopher.com/srv/chat" -) - -type chatHandler struct { - *http.ServeMux - - room chat.Room - userIDCalc *chat.UserIDCalculator - - wsUpgrader websocket.Upgrader -} - -func newChatHandler( - room chat.Room, userIDCalc *chat.UserIDCalculator, - requirePowMiddleware func(http.Handler) http.Handler, -) http.Handler { - c := &chatHandler{ - ServeMux: http.NewServeMux(), - room: room, - userIDCalc: userIDCalc, - - wsUpgrader: websocket.Upgrader{}, - } - - c.Handle("/history", c.historyHandler()) - c.Handle("/user-id", requirePowMiddleware(c.userIDHandler())) - c.Handle("/append", requirePowMiddleware(c.appendHandler())) - c.Handle("/listen", c.listenHandler()) - - return c -} - -func (c *chatHandler) historyHandler() http.Handler { - return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { - limit, err := apiutil.StrToInt(r.PostFormValue("limit"), 0) - if err != nil { - apiutil.BadRequest(rw, r, fmt.Errorf("invalid limit parameter: %w", err)) - return - } - - cursor := r.PostFormValue("cursor") - - cursor, msgs, err := c.room.History(r.Context(), chat.HistoryOpts{ - Limit: limit, - Cursor: cursor, - }) - - if argErr := (chat.ErrInvalidArg{}); errors.As(err, &argErr) { - apiutil.BadRequest(rw, r, argErr.Err) - return - } else if err != nil { - apiutil.InternalServerError(rw, r, err) - } - - apiutil.JSONResult(rw, r, struct { - Cursor string `json:"cursor"` - Messages []chat.Message `json:"messages"` - }{ - Cursor: cursor, - Messages: msgs, - }) - }) -} - -func (c *chatHandler) userID(r *http.Request) (chat.UserID, error) { - name := r.PostFormValue("name") - if l := len(name); l == 0 { - return chat.UserID{}, errors.New("name is required") - } else if l > 16 { - return chat.UserID{}, errors.New("name too long") - } - - nameClean := strings.Map(func(r rune) rune { - if !unicode.IsPrint(r) { - return -1 - } - return r - }, name) - - if nameClean != name { - return chat.UserID{}, errors.New("name contains invalid characters") - } - - password := r.PostFormValue("password") - if l := len(password); l == 0 { - return chat.UserID{}, errors.New("password is required") - } else if l > 128 { - return chat.UserID{}, errors.New("password too long") - } - - return c.userIDCalc.Calculate(name, password), nil -} - -func (c *chatHandler) userIDHandler() http.Handler { - return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { - userID, err := c.userID(r) - if err != nil { - apiutil.BadRequest(rw, r, err) - return - } - - apiutil.JSONResult(rw, r, struct { - UserID chat.UserID `json:"userID"` - }{ - UserID: userID, - }) - }) -} - -func (c *chatHandler) appendHandler() http.Handler { - return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { - userID, err := c.userID(r) - if err != nil { - apiutil.BadRequest(rw, r, err) - return - } - - body := r.PostFormValue("body") - - if l := len(body); l == 0 { - apiutil.BadRequest(rw, r, errors.New("body is required")) - return - - } else if l > 300 { - apiutil.BadRequest(rw, r, errors.New("body too long")) - return - } - - msg, err := c.room.Append(r.Context(), chat.Message{ - UserID: userID, - Body: body, - }) - - if err != nil { - apiutil.InternalServerError(rw, r, err) - return - } - - apiutil.JSONResult(rw, r, struct { - MessageID string `json:"messageID"` - }{ - MessageID: msg.ID, - }) - }) -} - -func (c *chatHandler) listenHandler() http.Handler { - return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { - - ctx := r.Context() - sinceID := r.FormValue("sinceID") - - conn, err := c.wsUpgrader.Upgrade(rw, r, nil) - if err != nil { - apiutil.BadRequest(rw, r, err) - return - } - defer conn.Close() - - it, err := c.room.Listen(ctx, sinceID) - - if errors.As(err, new(chat.ErrInvalidArg)) { - apiutil.BadRequest(rw, r, err) - return - - } else if errors.Is(err, context.Canceled) { - return - - } else if err != nil { - apiutil.InternalServerError(rw, r, err) - return - } - - defer it.Close() - - for { - - msg, err := it.Next(ctx) - if errors.Is(err, context.Canceled) { - return - - } else if err != nil { - apiutil.InternalServerError(rw, r, err) - return - } - - err = conn.WriteJSON(struct { - Message chat.Message `json:"message"` - }{ - Message: msg, - }) - - if err != nil { - apiutil.GetRequestLogger(r).Error(ctx, "couldn't write message", err) - return - } - } - }) -} |