A community based topic aggregation platform built on atproto
at main 3.0 kB view raw
1package comments 2 3import ( 4 "Coves/internal/core/comments" 5 "encoding/json" 6 "errors" 7 "log" 8 "net/http" 9) 10 11// errorResponse represents a standardized JSON error response 12type errorResponse struct { 13 Error string `json:"error"` 14 Message string `json:"message"` 15} 16 17// writeError writes a JSON error response with the given status code 18func writeError(w http.ResponseWriter, statusCode int, errorType, message string) { 19 w.Header().Set("Content-Type", "application/json") 20 w.WriteHeader(statusCode) 21 if err := json.NewEncoder(w).Encode(errorResponse{ 22 Error: errorType, 23 Message: message, 24 }); err != nil { 25 log.Printf("Failed to encode error response: %v", err) 26 } 27} 28 29// handleServiceError maps service-layer errors to HTTP responses 30// This follows the error handling pattern from other handlers (post, community) 31func handleServiceError(w http.ResponseWriter, err error) { 32 switch { 33 case comments.IsNotFound(err): 34 // Map specific not found errors to appropriate messages 35 switch { 36 case errors.Is(err, comments.ErrCommentNotFound): 37 writeError(w, http.StatusNotFound, "CommentNotFound", "Comment not found") 38 case errors.Is(err, comments.ErrParentNotFound): 39 writeError(w, http.StatusNotFound, "ParentNotFound", "Parent post or comment not found") 40 case errors.Is(err, comments.ErrRootNotFound): 41 writeError(w, http.StatusNotFound, "RootNotFound", "Root post not found") 42 default: 43 writeError(w, http.StatusNotFound, "NotFound", err.Error()) 44 } 45 46 case comments.IsValidationError(err): 47 // Map specific validation errors to appropriate messages 48 switch { 49 case errors.Is(err, comments.ErrInvalidReply): 50 writeError(w, http.StatusBadRequest, "InvalidReply", "The reply reference is invalid or malformed") 51 case errors.Is(err, comments.ErrContentTooLong): 52 writeError(w, http.StatusBadRequest, "ContentTooLong", "Comment content exceeds 10000 graphemes") 53 case errors.Is(err, comments.ErrContentEmpty): 54 writeError(w, http.StatusBadRequest, "ContentEmpty", "Comment content is required") 55 default: 56 writeError(w, http.StatusBadRequest, "InvalidRequest", err.Error()) 57 } 58 59 case errors.Is(err, comments.ErrNotAuthorized): 60 writeError(w, http.StatusForbidden, "NotAuthorized", "User is not authorized to perform this action") 61 62 case errors.Is(err, comments.ErrBanned): 63 writeError(w, http.StatusForbidden, "Banned", "User is banned from this community") 64 65 // NOTE: IsConflict case removed - the PDS handles duplicate detection via CreateRecord, 66 // so ErrCommentAlreadyExists is never returned from the service layer. If the PDS rejects 67 // a duplicate record, it returns an auth/validation error which is handled by other cases. 68 // Keeping this code would be dead code that never executes. 69 70 default: 71 // Don't leak internal error details to clients 72 log.Printf("Unexpected error in comments handler: %v", err) 73 writeError(w, http.StatusInternalServerError, "InternalServerError", 74 "An internal error occurred") 75 } 76}