mirror of
https://github.com/m1k1o/neko.git
synced 2024-07-24 14:40:50 +12:00
refactor HTTP error.
This commit is contained in:
parent
d46c5d9d30
commit
4fa11e6a2a
@ -2,7 +2,6 @@ package members
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
@ -18,13 +17,13 @@ type MemberBulkUpdatePayload struct {
|
||||
func (h *MembersHandler) membersBulkUpdate(w http.ResponseWriter, r *http.Request) {
|
||||
bytes, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
utils.HttpInternalServerError(w, err)
|
||||
utils.HttpBadRequest(w).WithInternalErr(err).Msg("unable to read post body")
|
||||
return
|
||||
}
|
||||
|
||||
header := &MemberBulkUpdatePayload{}
|
||||
if err := json.Unmarshal(bytes, &header); err != nil {
|
||||
utils.HttpInternalServerError(w, err)
|
||||
utils.HttpBadRequest(w).WithInternalErr(err).Msg("unable to unmarshal payload")
|
||||
return
|
||||
}
|
||||
|
||||
@ -32,7 +31,7 @@ func (h *MembersHandler) membersBulkUpdate(w http.ResponseWriter, r *http.Reques
|
||||
// TODO: Bulk select?
|
||||
profile, err := h.members.Select(memberId)
|
||||
if err != nil {
|
||||
utils.HttpInternalServerError(w, fmt.Sprintf("member %s: %v", memberId, err))
|
||||
utils.HttpInternalServerError(w, err).WithInternalMsg("unable to select member profile").Msgf("failed to update member %s", memberId)
|
||||
return
|
||||
}
|
||||
|
||||
@ -41,12 +40,12 @@ func (h *MembersHandler) membersBulkUpdate(w http.ResponseWriter, r *http.Reques
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(bytes, &body); err != nil {
|
||||
utils.HttpInternalServerError(w, fmt.Sprintf("member %s: %v", memberId, err))
|
||||
utils.HttpBadRequest(w).WithInternalErr(err).Msgf("unable to unmarshal payload for member %s", memberId)
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.members.UpdateProfile(memberId, body.Profile); err != nil {
|
||||
utils.HttpInternalServerError(w, fmt.Sprintf("member %s: %v", memberId, err))
|
||||
utils.HttpInternalServerError(w, err).WithInternalMsg("unable to update member profile").Msgf("failed to update member %s", memberId)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ func (h *MembersHandler) membersList(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
entries, err := h.members.SelectAll(limit, offset)
|
||||
if err != nil {
|
||||
utils.HttpInternalServerError(w, err)
|
||||
utils.HttpInternalServerError(w, err).Send()
|
||||
return
|
||||
}
|
||||
|
||||
@ -72,21 +72,21 @@ func (h *MembersHandler) membersCreate(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
if data.Username == "" {
|
||||
utils.HttpBadRequest(w, "username cannot be empty")
|
||||
utils.HttpBadRequest(w).Msg("username cannot be empty")
|
||||
return
|
||||
}
|
||||
|
||||
if data.Password == "" {
|
||||
utils.HttpBadRequest(w, "password cannot be empty")
|
||||
utils.HttpBadRequest(w).Msg("password cannot be empty")
|
||||
return
|
||||
}
|
||||
|
||||
id, err := h.members.Insert(data.Username, data.Password, data.Profile)
|
||||
if err != nil {
|
||||
if errors.Is(err, types.ErrMemberAlreadyExists) {
|
||||
utils.HttpUnprocessableEntity(w, err)
|
||||
utils.HttpUnprocessableEntity(w).Msg("member already exists")
|
||||
} else {
|
||||
utils.HttpInternalServerError(w, err)
|
||||
utils.HttpInternalServerError(w, err).Send()
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -113,7 +113,7 @@ func (h *MembersHandler) membersUpdateProfile(w http.ResponseWriter, r *http.Req
|
||||
}
|
||||
|
||||
if err := h.members.UpdateProfile(member.ID, profile); err != nil {
|
||||
utils.HttpInternalServerError(w, err)
|
||||
utils.HttpInternalServerError(w, err).Send()
|
||||
return
|
||||
}
|
||||
|
||||
@ -129,7 +129,7 @@ func (h *MembersHandler) membersUpdatePassword(w http.ResponseWriter, r *http.Re
|
||||
}
|
||||
|
||||
if err := h.members.UpdatePassword(member.ID, data.Password); err != nil {
|
||||
utils.HttpInternalServerError(w, err)
|
||||
utils.HttpInternalServerError(w, err).Send()
|
||||
return
|
||||
}
|
||||
|
||||
@ -140,7 +140,7 @@ func (h *MembersHandler) membersDelete(w http.ResponseWriter, r *http.Request) {
|
||||
member := GetMember(r)
|
||||
|
||||
if err := h.members.Delete(member.ID); err != nil {
|
||||
utils.HttpInternalServerError(w, err)
|
||||
utils.HttpInternalServerError(w, err).Send()
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -71,9 +71,9 @@ func (h *MembersHandler) ExtractMember(next http.Handler) http.Handler {
|
||||
profile, err := h.members.Select(memberId)
|
||||
if err != nil {
|
||||
if errors.Is(err, types.ErrMemberDoesNotExist) {
|
||||
utils.HttpNotFound(w, err)
|
||||
utils.HttpNotFound(w).Msg("member not found")
|
||||
} else {
|
||||
utils.HttpInternalServerError(w, err)
|
||||
utils.HttpInternalServerError(w, err).Send()
|
||||
}
|
||||
|
||||
return
|
||||
|
@ -28,18 +28,18 @@ func (h *RoomHandler) boradcastStart(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
if data.URL == "" {
|
||||
utils.HttpBadRequest(w, "missing broadcast URL")
|
||||
utils.HttpBadRequest(w).Msg("missing broadcast URL")
|
||||
return
|
||||
}
|
||||
|
||||
broadcast := h.capture.Broadcast()
|
||||
if broadcast.Started() {
|
||||
utils.HttpUnprocessableEntity(w, "server is already broadcasting")
|
||||
utils.HttpUnprocessableEntity(w).Msg("server is already broadcasting")
|
||||
return
|
||||
}
|
||||
|
||||
if err := broadcast.Start(data.URL); err != nil {
|
||||
utils.HttpInternalServerError(w, err)
|
||||
utils.HttpInternalServerError(w, err).Send()
|
||||
return
|
||||
}
|
||||
|
||||
@ -56,7 +56,7 @@ func (h *RoomHandler) boradcastStart(w http.ResponseWriter, r *http.Request) {
|
||||
func (h *RoomHandler) boradcastStop(w http.ResponseWriter, r *http.Request) {
|
||||
broadcast := h.capture.Broadcast()
|
||||
if !broadcast.Started() {
|
||||
utils.HttpUnprocessableEntity(w, "server is not broadcasting")
|
||||
utils.HttpUnprocessableEntity(w).Msg("server is not broadcasting")
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,7 @@ type ClipboardPayload struct {
|
||||
func (h *RoomHandler) clipboardGetText(w http.ResponseWriter, r *http.Request) {
|
||||
data, err := h.desktop.ClipboardGetText()
|
||||
if err != nil {
|
||||
utils.HttpInternalServerError(w, err)
|
||||
utils.HttpInternalServerError(w, err).Send()
|
||||
return
|
||||
}
|
||||
|
||||
@ -40,7 +40,7 @@ func (h *RoomHandler) clipboardSetText(w http.ResponseWriter, r *http.Request) {
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
utils.HttpInternalServerError(w, err)
|
||||
utils.HttpInternalServerError(w, err).Send()
|
||||
return
|
||||
}
|
||||
|
||||
@ -50,7 +50,7 @@ func (h *RoomHandler) clipboardSetText(w http.ResponseWriter, r *http.Request) {
|
||||
func (h *RoomHandler) clipboardGetImage(w http.ResponseWriter, r *http.Request) {
|
||||
bytes, err := h.desktop.ClipboardGetBinary("image/png")
|
||||
if err != nil {
|
||||
utils.HttpInternalServerError(w, err)
|
||||
utils.HttpInternalServerError(w, err).Send()
|
||||
return
|
||||
}
|
||||
|
||||
@ -64,7 +64,7 @@ func (h *RoomHandler) clipboardGetImage(w http.ResponseWriter, r *http.Request)
|
||||
func (h *RoomHandler) clipboardSetImage(w http.ResponseWriter, r *http.Request) {
|
||||
err := r.ParseMultipartForm(MAX_UPLOAD_SIZE)
|
||||
if err != nil {
|
||||
utils.HttpBadRequest(w, "failed to parse multipart form")
|
||||
utils.HttpBadRequest(w).WithInternalErr(err).Msg("failed to parse multipart form")
|
||||
return
|
||||
}
|
||||
|
||||
@ -73,7 +73,7 @@ func (h *RoomHandler) clipboardSetImage(w http.ResponseWriter, r *http.Request)
|
||||
|
||||
file, header, err := r.FormFile("file")
|
||||
if err != nil {
|
||||
utils.HttpBadRequest(w, "no file received")
|
||||
utils.HttpBadRequest(w).WithInternalErr(err).Msg("no file received")
|
||||
return
|
||||
}
|
||||
|
||||
@ -81,20 +81,20 @@ func (h *RoomHandler) clipboardSetImage(w http.ResponseWriter, r *http.Request)
|
||||
|
||||
mime := header.Header.Get("Content-Type")
|
||||
if !strings.HasPrefix(mime, "image/") {
|
||||
utils.HttpBadRequest(w, "file must be image")
|
||||
utils.HttpBadRequest(w).Msg("file must be image")
|
||||
return
|
||||
}
|
||||
|
||||
buffer := new(bytes.Buffer)
|
||||
_, err = buffer.ReadFrom(file)
|
||||
if err != nil {
|
||||
utils.HttpInternalServerError(w, err)
|
||||
utils.HttpInternalServerError(w, err).WithInternalMsg("unable to read from uploaded file").Send()
|
||||
return
|
||||
}
|
||||
|
||||
err = h.desktop.ClipboardSetBinary("image/png", buffer.Bytes())
|
||||
if err != nil {
|
||||
utils.HttpInternalServerError(w, err)
|
||||
utils.HttpInternalServerError(w, err).WithInternalMsg("unable set image to clipboard").Send()
|
||||
return
|
||||
}
|
||||
|
||||
@ -104,7 +104,7 @@ func (h *RoomHandler) clipboardSetImage(w http.ResponseWriter, r *http.Request)
|
||||
func (h *RoomHandler) clipboardGetTargets(w http.ResponseWriter, r *http.Request) {
|
||||
targets, err := h.desktop.ClipboardGetTargets()
|
||||
if err != nil {
|
||||
utils.HttpInternalServerError(w, err)
|
||||
utils.HttpInternalServerError(w, err).Send()
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -36,7 +36,7 @@ func (h *RoomHandler) controlStatus(w http.ResponseWriter, r *http.Request) {
|
||||
func (h *RoomHandler) controlRequest(w http.ResponseWriter, r *http.Request) {
|
||||
host := h.sessions.GetHost()
|
||||
if host != nil {
|
||||
utils.HttpUnprocessableEntity(w, "there is already a host")
|
||||
utils.HttpUnprocessableEntity(w).Msg("there is already a host")
|
||||
return
|
||||
}
|
||||
|
||||
@ -49,7 +49,7 @@ func (h *RoomHandler) controlRequest(w http.ResponseWriter, r *http.Request) {
|
||||
func (h *RoomHandler) controlRelease(w http.ResponseWriter, r *http.Request) {
|
||||
session := auth.GetSession(r)
|
||||
if !session.IsHost() {
|
||||
utils.HttpUnprocessableEntity(w, "session is not the host")
|
||||
utils.HttpUnprocessableEntity(w).Msg("session is not the host")
|
||||
return
|
||||
}
|
||||
|
||||
@ -71,12 +71,12 @@ func (h *RoomHandler) controlGive(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
target, ok := h.sessions.Get(sessionId)
|
||||
if !ok {
|
||||
utils.HttpNotFound(w, "target session was not found")
|
||||
utils.HttpNotFound(w).Msg("target session was not found")
|
||||
return
|
||||
}
|
||||
|
||||
if !target.Profile().CanHost {
|
||||
utils.HttpBadRequest(w, "target session is not allowed to host")
|
||||
utils.HttpBadRequest(w).Msg("target session is not allowed to host")
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -90,7 +90,7 @@ func (h *RoomHandler) uploadMiddleware(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
session := auth.GetSession(r)
|
||||
if !session.IsHost() && (!session.Profile().CanHost || !h.sessions.ImplicitHosting()) {
|
||||
utils.HttpForbidden(w, "without implicit hosting, only host can upload files")
|
||||
utils.HttpForbidden(w).Msg("without implicit hosting, only host can upload files")
|
||||
} else {
|
||||
next.ServeHTTP(w, r)
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ func (h *RoomHandler) keyboardMapSet(w http.ResponseWriter, r *http.Request) {
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
utils.HttpInternalServerError(w, "unable to change keyboard map")
|
||||
utils.HttpInternalServerError(w, err).Send()
|
||||
return
|
||||
}
|
||||
|
||||
@ -40,7 +40,7 @@ func (h *RoomHandler) keyboardMapGet(w http.ResponseWriter, r *http.Request) {
|
||||
data, err := h.desktop.GetKeyboardMap()
|
||||
|
||||
if err != nil {
|
||||
utils.HttpInternalServerError(w, "unable to get keyboard map")
|
||||
utils.HttpInternalServerError(w, err).Send()
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,7 @@ func (h *RoomHandler) screenConfiguration(w http.ResponseWriter, r *http.Request
|
||||
size := h.desktop.GetScreenSize()
|
||||
|
||||
if size == nil {
|
||||
utils.HttpInternalServerError(w, "unable to get screen configuration")
|
||||
utils.HttpInternalServerError(w, nil).WithInternalMsg("unable to get screen configuration").Send()
|
||||
return
|
||||
}
|
||||
|
||||
@ -42,7 +42,7 @@ func (h *RoomHandler) screenConfigurationChange(w http.ResponseWriter, r *http.R
|
||||
Height: data.Height,
|
||||
Rate: data.Rate,
|
||||
}); err != nil {
|
||||
utils.HttpUnprocessableEntity(w, err)
|
||||
utils.HttpUnprocessableEntity(w).WithInternalErr(err).Msg("cannot set screen size")
|
||||
return
|
||||
}
|
||||
|
||||
@ -83,7 +83,7 @@ func (h *RoomHandler) screenShotGet(w http.ResponseWriter, r *http.Request) {
|
||||
img := h.desktop.GetScreenshotImage()
|
||||
bytes, err := utils.CreateJPGImage(img, quality)
|
||||
if err != nil {
|
||||
utils.HttpInternalServerError(w, err)
|
||||
utils.HttpInternalServerError(w, err).Send()
|
||||
return
|
||||
}
|
||||
|
||||
@ -96,13 +96,13 @@ func (h *RoomHandler) screenShotGet(w http.ResponseWriter, r *http.Request) {
|
||||
func (h *RoomHandler) screenCastGet(w http.ResponseWriter, r *http.Request) {
|
||||
screencast := h.capture.Screencast()
|
||||
if !screencast.Enabled() {
|
||||
utils.HttpBadRequest(w, "screencast pipeline is not enabled")
|
||||
utils.HttpBadRequest(w).Msg("screencast pipeline is not enabled")
|
||||
return
|
||||
}
|
||||
|
||||
bytes, err := screencast.Image()
|
||||
if err != nil {
|
||||
utils.HttpInternalServerError(w, err)
|
||||
utils.HttpInternalServerError(w, err).Send()
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -10,13 +10,15 @@ import (
|
||||
"demodesk/neko/internal/utils"
|
||||
)
|
||||
|
||||
// TODO: Extract file uploading to custom utility.
|
||||
|
||||
// maximum upload size of 32 MB
|
||||
const maxUploadSize = 32 << 20
|
||||
|
||||
func (h *RoomHandler) uploadDrop(w http.ResponseWriter, r *http.Request) {
|
||||
err := r.ParseMultipartForm(maxUploadSize)
|
||||
if err != nil {
|
||||
utils.HttpBadRequest(w, "failed to parse multipart form")
|
||||
utils.HttpBadRequest(w).WithInternalErr(err).Msg("failed to parse multipart form")
|
||||
return
|
||||
}
|
||||
|
||||
@ -25,25 +27,25 @@ func (h *RoomHandler) uploadDrop(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
X, err := strconv.Atoi(r.FormValue("x"))
|
||||
if err != nil {
|
||||
utils.HttpBadRequest(w, "no X coordinate received")
|
||||
utils.HttpBadRequest(w).WithInternalErr(err).Msg("no X coordinate received")
|
||||
return
|
||||
}
|
||||
|
||||
Y, err := strconv.Atoi(r.FormValue("y"))
|
||||
if err != nil {
|
||||
utils.HttpBadRequest(w, "no Y coordinate received")
|
||||
utils.HttpBadRequest(w).WithInternalErr(err).Msg("no Y coordinate received")
|
||||
return
|
||||
}
|
||||
|
||||
req_files := r.MultipartForm.File["files"]
|
||||
if len(req_files) == 0 {
|
||||
utils.HttpBadRequest(w, "no files received")
|
||||
utils.HttpBadRequest(w).Msg("no files received")
|
||||
return
|
||||
}
|
||||
|
||||
dir, err := os.MkdirTemp("", "neko-drop-*")
|
||||
if err != nil {
|
||||
utils.HttpInternalServerError(w, err)
|
||||
utils.HttpInternalServerError(w, err).WithInternalMsg("unable to create temporary directory").Send()
|
||||
return
|
||||
}
|
||||
|
||||
@ -53,7 +55,7 @@ func (h *RoomHandler) uploadDrop(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
srcFile, err := req_file.Open()
|
||||
if err != nil {
|
||||
utils.HttpInternalServerError(w, err)
|
||||
utils.HttpInternalServerError(w, err).WithInternalMsg("unable to open uploaded file").Send()
|
||||
return
|
||||
}
|
||||
|
||||
@ -61,7 +63,7 @@ func (h *RoomHandler) uploadDrop(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
dstFile, err := os.OpenFile(path, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
||||
if err != nil {
|
||||
utils.HttpInternalServerError(w, err)
|
||||
utils.HttpInternalServerError(w, err).WithInternalMsg("unable to open destination file").Send()
|
||||
return
|
||||
}
|
||||
|
||||
@ -69,7 +71,7 @@ func (h *RoomHandler) uploadDrop(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
_, err = io.Copy(dstFile, srcFile)
|
||||
if err != nil {
|
||||
utils.HttpInternalServerError(w, err)
|
||||
utils.HttpInternalServerError(w, err).WithInternalMsg("unable to copy uploaded file to destination file").Send()
|
||||
return
|
||||
}
|
||||
|
||||
@ -77,7 +79,7 @@ func (h *RoomHandler) uploadDrop(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
if !h.desktop.DropFiles(X, Y, files) {
|
||||
utils.HttpInternalServerError(w, "unable to drop files")
|
||||
utils.HttpInternalServerError(w, nil).WithInternalMsg("unable to drop files").Send()
|
||||
return
|
||||
}
|
||||
|
||||
@ -87,7 +89,7 @@ func (h *RoomHandler) uploadDrop(w http.ResponseWriter, r *http.Request) {
|
||||
func (h *RoomHandler) uploadDialogPost(w http.ResponseWriter, r *http.Request) {
|
||||
err := r.ParseMultipartForm(maxUploadSize)
|
||||
if err != nil {
|
||||
utils.HttpBadRequest(w, "failed to parse multipart form")
|
||||
utils.HttpBadRequest(w).WithInternalErr(err).Msg("failed to parse multipart form")
|
||||
return
|
||||
}
|
||||
|
||||
@ -95,19 +97,19 @@ func (h *RoomHandler) uploadDialogPost(w http.ResponseWriter, r *http.Request) {
|
||||
defer r.MultipartForm.RemoveAll()
|
||||
|
||||
if !h.desktop.IsFileChooserDialogOpened() {
|
||||
utils.HttpBadRequest(w, "open file chooser dialog first")
|
||||
utils.HttpUnprocessableEntity(w).Msg("file chooser dialog is not open")
|
||||
return
|
||||
}
|
||||
|
||||
req_files := r.MultipartForm.File["files"]
|
||||
if len(req_files) == 0 {
|
||||
utils.HttpBadRequest(w, "no files received")
|
||||
utils.HttpInternalServerError(w, err).WithInternalMsg("unable to copy uploaded file to destination file").Send()
|
||||
return
|
||||
}
|
||||
|
||||
dir, err := os.MkdirTemp("", "neko-dialog-*")
|
||||
if err != nil {
|
||||
utils.HttpInternalServerError(w, err)
|
||||
utils.HttpInternalServerError(w, err).WithInternalMsg("unable to create temporary directory").Send()
|
||||
return
|
||||
}
|
||||
|
||||
@ -116,7 +118,7 @@ func (h *RoomHandler) uploadDialogPost(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
srcFile, err := req_file.Open()
|
||||
if err != nil {
|
||||
utils.HttpInternalServerError(w, err)
|
||||
utils.HttpInternalServerError(w, err).WithInternalMsg("unable to open uploaded file").Send()
|
||||
return
|
||||
}
|
||||
|
||||
@ -124,7 +126,7 @@ func (h *RoomHandler) uploadDialogPost(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
dstFile, err := os.OpenFile(path, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
||||
if err != nil {
|
||||
utils.HttpInternalServerError(w, err)
|
||||
utils.HttpInternalServerError(w, err).WithInternalMsg("unable to open destination file").Send()
|
||||
return
|
||||
}
|
||||
|
||||
@ -132,13 +134,13 @@ func (h *RoomHandler) uploadDialogPost(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
_, err = io.Copy(dstFile, srcFile)
|
||||
if err != nil {
|
||||
utils.HttpInternalServerError(w, err)
|
||||
utils.HttpInternalServerError(w, err).WithInternalMsg("unable to copy uploaded file to destination file").Send()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if err := h.desktop.HandleFileChooserDialog(dir); err != nil {
|
||||
utils.HttpInternalServerError(w, "unable to handle file chooser dialog")
|
||||
utils.HttpInternalServerError(w, err).WithInternalMsg("unable to handle file chooser dialog").Send()
|
||||
return
|
||||
}
|
||||
|
||||
@ -147,7 +149,7 @@ func (h *RoomHandler) uploadDialogPost(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
func (h *RoomHandler) uploadDialogClose(w http.ResponseWriter, r *http.Request) {
|
||||
if !h.desktop.IsFileChooserDialogOpened() {
|
||||
utils.HttpBadRequest(w, "file chooser dialog is not open")
|
||||
utils.HttpUnprocessableEntity(w).Msg("file chooser dialog is not open")
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -76,9 +76,9 @@ func (api *ApiManagerCtx) Authenticate(next http.Handler) http.Handler {
|
||||
}
|
||||
|
||||
if errors.Is(err, types.ErrSessionLoginDisabled) {
|
||||
utils.HttpForbidden(w, err)
|
||||
utils.HttpForbidden(w).Msg("login is disabled for this session")
|
||||
} else {
|
||||
utils.HttpUnauthorized(w, err)
|
||||
utils.HttpUnauthorized(w).WithInternalErr(err).Send()
|
||||
}
|
||||
|
||||
return
|
||||
|
@ -28,7 +28,7 @@ func (api *ApiManagerCtx) Login(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
session, token, err := api.members.Login(data.Username, data.Password)
|
||||
if err != nil {
|
||||
utils.HttpUnauthorized(w, err)
|
||||
utils.HttpUnauthorized(w).WithInternalErr(err).Send()
|
||||
return
|
||||
}
|
||||
|
||||
@ -52,7 +52,7 @@ func (api *ApiManagerCtx) Logout(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
err := api.members.Logout(session.ID())
|
||||
if err != nil {
|
||||
utils.HttpUnauthorized(w, err)
|
||||
utils.HttpUnauthorized(w).WithInternalErr(err).Send()
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,7 @@ func AdminsOnly(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
session := GetSession(r)
|
||||
if !session.Profile().IsAdmin {
|
||||
utils.HttpForbidden(w)
|
||||
utils.HttpForbidden(w).Msg("session is not admin")
|
||||
} else {
|
||||
next.ServeHTTP(w, r)
|
||||
}
|
||||
@ -36,7 +36,7 @@ func HostsOnly(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
session := GetSession(r)
|
||||
if !session.IsHost() {
|
||||
utils.HttpForbidden(w, "only host can do this")
|
||||
utils.HttpForbidden(w).Msg("session is not host")
|
||||
} else {
|
||||
next.ServeHTTP(w, r)
|
||||
}
|
||||
@ -47,7 +47,7 @@ func CanWatchOnly(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
session := GetSession(r)
|
||||
if !session.Profile().CanWatch {
|
||||
utils.HttpForbidden(w)
|
||||
utils.HttpForbidden(w).Msg("session cannot watch")
|
||||
} else {
|
||||
next.ServeHTTP(w, r)
|
||||
}
|
||||
@ -58,7 +58,7 @@ func CanHostOnly(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
session := GetSession(r)
|
||||
if !session.Profile().CanHost {
|
||||
utils.HttpForbidden(w)
|
||||
utils.HttpForbidden(w).Msg("session cannot host")
|
||||
} else {
|
||||
next.ServeHTTP(w, r)
|
||||
}
|
||||
@ -69,7 +69,7 @@ func CanAccessClipboardOnly(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
session := GetSession(r)
|
||||
if !session.Profile().CanAccessClipboard {
|
||||
utils.HttpForbidden(w)
|
||||
utils.HttpForbidden(w).Msg("session cannot access clipboard")
|
||||
} else {
|
||||
next.ServeHTTP(w, r)
|
||||
}
|
||||
|
@ -13,7 +13,6 @@ import (
|
||||
|
||||
"demodesk/neko/internal/config"
|
||||
"demodesk/neko/internal/types"
|
||||
"demodesk/neko/internal/utils"
|
||||
)
|
||||
|
||||
type HttpManagerCtx struct {
|
||||
@ -55,13 +54,13 @@ func New(WebSocketManager types.WebSocketManager, ApiManager types.ApiManager, c
|
||||
if _, err := os.Stat(config.Static + r.URL.Path); !os.IsNotExist(err) {
|
||||
fs.ServeHTTP(w, r)
|
||||
} else {
|
||||
utils.HttpNotFound(w)
|
||||
http.NotFound(w, r)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
router.NotFound(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
utils.HttpNotFound(w)
|
||||
http.NotFound(w, r)
|
||||
}))
|
||||
|
||||
return &HttpManagerCtx{
|
||||
|
@ -9,16 +9,12 @@ import (
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
type ErrResponse struct {
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
func HttpJsonRequest(w http.ResponseWriter, r *http.Request, res interface{}) bool {
|
||||
if err := json.NewDecoder(r.Body).Decode(res); err != nil {
|
||||
if err == io.EOF {
|
||||
HttpBadRequest(w, "no data provided")
|
||||
HttpBadRequest(w).WithInternalErr(err).Msg("no data provided")
|
||||
} else {
|
||||
HttpBadRequest(w, err)
|
||||
HttpBadRequest(w).WithInternalErr(err).Msg("unable to parse provided data")
|
||||
}
|
||||
|
||||
return false
|
||||
@ -27,21 +23,15 @@ func HttpJsonRequest(w http.ResponseWriter, r *http.Request, res interface{}) bo
|
||||
return true
|
||||
}
|
||||
|
||||
func HttpJsonResponse(w http.ResponseWriter, status int, res interface{}) {
|
||||
func HttpJsonResponse(w http.ResponseWriter, code int, res interface{}) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(status)
|
||||
w.WriteHeader(code)
|
||||
|
||||
if err := json.NewEncoder(w).Encode(res); err != nil {
|
||||
log.Err(err).Str("module", "http").Msg("sending http json response failed")
|
||||
}
|
||||
}
|
||||
|
||||
func HttpError(w http.ResponseWriter, status int, res interface{}) {
|
||||
HttpJsonResponse(w, status, &ErrResponse{
|
||||
Message: fmt.Sprint(res),
|
||||
})
|
||||
}
|
||||
|
||||
func HttpSuccess(w http.ResponseWriter, res ...interface{}) {
|
||||
if len(res) == 0 {
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
@ -50,34 +40,108 @@ func HttpSuccess(w http.ResponseWriter, res ...interface{}) {
|
||||
}
|
||||
}
|
||||
|
||||
func HttpBadRequest(w http.ResponseWriter, res ...interface{}) {
|
||||
defHttpError(w, http.StatusBadRequest, "bad request", res...)
|
||||
// HTTPError is an error with a message and an HTTP status code.
|
||||
type HTTPError struct {
|
||||
Code int `json:"code"`
|
||||
Message string `json:"message"`
|
||||
|
||||
InternalErr error `json:"-"`
|
||||
InternalMsg string `json:"-"`
|
||||
|
||||
w http.ResponseWriter `json:"-"`
|
||||
}
|
||||
|
||||
func HttpUnauthorized(w http.ResponseWriter, res ...interface{}) {
|
||||
defHttpError(w, http.StatusUnauthorized, "invalid or missing access token", res...)
|
||||
func (e *HTTPError) Error() string {
|
||||
if e.InternalMsg != "" {
|
||||
return e.InternalMsg
|
||||
}
|
||||
return fmt.Sprintf("%d: %s", e.Code, e.Message)
|
||||
}
|
||||
|
||||
func HttpForbidden(w http.ResponseWriter, res ...interface{}) {
|
||||
defHttpError(w, http.StatusForbidden, "access token does not have the required scope", res...)
|
||||
func (e *HTTPError) Cause() error {
|
||||
if e.InternalErr != nil {
|
||||
return e.InternalErr
|
||||
}
|
||||
return e
|
||||
}
|
||||
|
||||
func HttpNotFound(w http.ResponseWriter, res ...interface{}) {
|
||||
defHttpError(w, http.StatusNotFound, "resource not found", res...)
|
||||
// WithInternalErr adds internal error information to the error
|
||||
func (e *HTTPError) WithInternalErr(err error) *HTTPError {
|
||||
e.InternalErr = err
|
||||
return e
|
||||
}
|
||||
|
||||
func HttpUnprocessableEntity(w http.ResponseWriter, res ...interface{}) {
|
||||
defHttpError(w, http.StatusUnprocessableEntity, "unprocessable entity", res...)
|
||||
// WithInternalMsg adds internal message information to the error
|
||||
func (e *HTTPError) WithInternalMsg(msg string) *HTTPError {
|
||||
e.InternalMsg = msg
|
||||
return e
|
||||
}
|
||||
|
||||
func HttpInternalServerError(w http.ResponseWriter, res ...interface{}) {
|
||||
defHttpError(w, http.StatusInternalServerError, "internal server error", res...)
|
||||
// WithInternalMsg adds internal formated message information to the error
|
||||
func (e *HTTPError) WithInternalMsgf(fmtStr string, args ...interface{}) *HTTPError {
|
||||
e.InternalMsg = fmt.Sprintf(fmtStr, args...)
|
||||
return e
|
||||
}
|
||||
|
||||
func defHttpError(w http.ResponseWriter, status int, text string, res ...interface{}) {
|
||||
if len(res) == 0 {
|
||||
HttpError(w, status, text)
|
||||
} else {
|
||||
HttpError(w, status, res[0])
|
||||
// Sends error with custom formated message
|
||||
func (e *HTTPError) Msgf(fmtSt string, args ...interface{}) {
|
||||
e.Message = fmt.Sprintf(fmtSt, args...)
|
||||
e.Send()
|
||||
}
|
||||
|
||||
// Sends error with custom message
|
||||
func (e *HTTPError) Msg(str string) {
|
||||
e.Message = str
|
||||
e.Send()
|
||||
}
|
||||
|
||||
// Sends error with default status text
|
||||
func (e *HTTPError) Send() {
|
||||
if e.Message == "" {
|
||||
e.Message = http.StatusText(e.Code)
|
||||
}
|
||||
|
||||
logger := log.Error().
|
||||
Err(e.InternalErr).
|
||||
Str("module", "http").
|
||||
Int("code", e.Code)
|
||||
|
||||
message := e.Message
|
||||
if e.InternalMsg != "" {
|
||||
message = e.InternalMsg
|
||||
}
|
||||
|
||||
logger.Msg(message)
|
||||
HttpJsonResponse(e.w, e.Code, e)
|
||||
}
|
||||
|
||||
func HttpError(w http.ResponseWriter, code int) *HTTPError {
|
||||
return &HTTPError{
|
||||
Code: code,
|
||||
w: w,
|
||||
}
|
||||
}
|
||||
|
||||
func HttpBadRequest(w http.ResponseWriter) *HTTPError {
|
||||
return HttpError(w, http.StatusBadRequest)
|
||||
}
|
||||
|
||||
func HttpUnauthorized(w http.ResponseWriter) *HTTPError {
|
||||
return HttpError(w, http.StatusUnauthorized)
|
||||
}
|
||||
|
||||
func HttpForbidden(w http.ResponseWriter) *HTTPError {
|
||||
return HttpError(w, http.StatusForbidden)
|
||||
}
|
||||
|
||||
func HttpNotFound(w http.ResponseWriter) *HTTPError {
|
||||
return HttpError(w, http.StatusNotFound)
|
||||
}
|
||||
|
||||
func HttpUnprocessableEntity(w http.ResponseWriter) *HTTPError {
|
||||
return HttpError(w, http.StatusUnprocessableEntity)
|
||||
}
|
||||
|
||||
func HttpInternalServerError(w http.ResponseWriter, err error) *HTTPError {
|
||||
return HttpError(w, http.StatusInternalServerError).WithInternalErr(err)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user