Comments
The Comments API allows users to add, retrieve, and manage comments on blog posts. All authenticated users can create and view comments, while comment deletion is restricted to the comment author or administrators.
Endpoints
Create Comment
Adds a new comment to a specific blog post and increments the blog's comment count.
Endpoint: POST /comments/
Authentication: Required (Bearer token)
Request Body:
{
"blogId": "60b7c8b4f9b3c12345678903",
"content": "Great article! The examples really helped me understand the concepts better."
}
Success Response (201 Created):
{
"comment": {
"_id": "60b7c8b4f9b3c12345678905",
"blogId": "60b7c8b4f9b3c12345678903",
"userId": "60b7c8b4f9b3c12345678901",
"content": "Great article! The examples really helped me understand the concepts better.",
"likesCount": 0,
"createdAt": "2024-01-21T14:30:00.000Z",
"updatedAt": "2024-01-21T14:30:00.000Z"
}
}
Error Responses:
400
- Validation errors (missing blogId, content too long, etc.)401
- Unauthorized404
- Blog post not found500
- Internal server error
Validation Rules:
blogId
: Must be a valid MongoDB ObjectIdcontent
: Required, maximum 1000 charactersuserId
: Automatically set from authenticated user
Get Comments by Blog
Retrieves all comments associated with a specific blog post, ordered by creation date.
Endpoint: GET /comments/blog/{blogId}
Authentication: Required (Bearer token)
Path Parameters:
blogId
: MongoDB ObjectId of the blog post
Success Response (200 OK):
{
"comments": [
{
"_id": "60b7c8b4f9b3c12345678905",
"blogId": "60b7c8b4f9b3c12345678903",
"userId": "60b7c8b4f9b3c12345678901",
"content": "Great article! The examples really helped me understand the concepts better.",
"likesCount": 5,
"createdAt": "2024-01-21T14:30:00.000Z",
"updatedAt": "2024-01-21T14:30:00.000Z"
},
{
"_id": "60b7c8b4f9b3c12345678906",
"blogId": "60b7c8b4f9b3c12345678903",
"userId": "60b7c8b4f9b3c12345678902",
"content": "I've been looking for a tutorial like this for weeks. Thank you for sharing!",
"likesCount": 3,
"createdAt": "2024-01-21T15:45:00.000Z",
"updatedAt": "2024-01-21T15:45:00.000Z"
},
{
"_id": "60b7c8b4f9b3c12345678907",
"blogId": "60b7c8b4f9b3c12345678903",
"userId": "60b7c8b4f9b3c12345678904",
"content": "Could you elaborate more on the authentication part? I'm still a bit confused about JWT implementation.",
"likesCount": 1,
"createdAt": "2024-01-21T16:20:00.000Z",
"updatedAt": "2024-01-21T16:20:00.000Z"
}
]
}
Error Responses:
401
- Unauthorized404
- Blog post not found500
- Internal server error
Notes:
Comments are returned in chronological order (oldest first)
No pagination is currently implemented for comments
Returns empty array if no comments exist
Delete Comment
Deletes a specific comment. Only the comment author or administrators can delete comments. Decrements the blog's comment count.
Endpoint: DELETE /comments/{commentId}
Authentication: Required (Bearer token)
Path Parameters:
commentId
: MongoDB ObjectId of the comment to delete
Success Response (204 No Content): Empty response body
Error Responses:
401
- Unauthorized403
- Forbidden (user is not the comment author or admin)404
- Comment not found500
- Internal server error
Authorization Logic:
Comment authors can delete their own comments
Administrators can delete any comment
Other users receive a 403 Forbidden error
Comment Lifecycle
1. Creation Flow
sequenceDiagram
participant User
participant API
participant Database
participant Blog
User->>API: POST /comments/ with blogId and content
API->>Database: Validate blog exists
Database-->>API: Blog found
API->>Database: Create comment
Database-->>API: Comment created
API->>Blog: Increment commentsCount
API-->>User: Return new comment
2. Retrieval
Comments are fetched when viewing a blog post
All comments for a blog are returned in a single request
Comments include creation timestamps and like counts
3. Deletion Flow
sequenceDiagram
participant User
participant API
participant Database
participant Blog
User->>API: DELETE /comments/{commentId}
API->>Database: Check comment ownership/admin role
Database-->>API: Authorization confirmed
API->>Database: Delete comment
Database-->>API: Comment deleted
API->>Blog: Decrement commentsCount
API-->>User: 204 No Content
Code Examples
Create a Comment
const createComment = async (accessToken, blogId, content) => {
const response = await fetch("/api/v1/comments/", {
method: "POST",
headers: {
Authorization: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
blogId,
content,
}),
});
if (response.ok) {
const data = await response.json();
return data.comment;
}
const error = await response.json();
throw new Error(error.message || "Failed to create comment");
};
Get Comments for a Blog Post
const getBlogComments = async (accessToken, blogId) => {
const response = await fetch(`/api/v1/comments/blog/${blogId}`, {
method: "GET",
headers: {
Authorization: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
});
if (response.ok) {
const data = await response.json();
return data.comments;
}
throw new Error("Failed to fetch comments");
};
Delete a Comment
const deleteComment = async (accessToken, commentId) => {
const response = await fetch(`/api/v1/comments/${commentId}`, {
method: "DELETE",
headers: {
Authorization: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
});
if (response.status === 204) {
return true;
}
if (response.status === 403) {
throw new Error("You can only delete your own comments");
}
throw new Error("Failed to delete comment");
};
Complete Comment Management Class
class CommentAPI {
constructor(baseURL, accessToken) {
this.baseURL = baseURL;
this.accessToken = accessToken;
}
async createComment(blogId, content) {
const response = await fetch(`${this.baseURL}/comments/`, {
method: "POST",
headers: this._getHeaders(),
body: JSON.stringify({ blogId, content }),
});
return this._handleResponse(response);
}
async getBlogComments(blogId) {
const response = await fetch(`${this.baseURL}/comments/blog/${blogId}`, {
method: "GET",
headers: this._getHeaders(),
});
const data = await this._handleResponse(response);
return data.comments;
}
async deleteComment(commentId) {
const response = await fetch(`${this.baseURL}/comments/${commentId}`, {
method: "DELETE",
headers: this._getHeaders(),
});
if (response.status === 204) {
return true;
}
if (response.status === 403) {
throw new Error("You can only delete your own comments");
}
throw new Error("Failed to delete comment");
}
_getHeaders() {
return {
Authorization: `Bearer ${this.accessToken}`,
"Content-Type": "application/json",
};
}
async _handleResponse(response) {
if (response.ok) {
return await response.json();
}
const error = await response
.json()
.catch(() => ({ message: "Unknown error" }));
throw new Error(error.message || `HTTP ${response.status}`);
}
}
React Component Example
import React, { useState, useEffect } from "react";
const CommentSection = ({ blogId, accessToken }) => {
const [comments, setComments] = useState([]);
const [newComment, setNewComment] = useState("");
const [loading, setLoading] = useState(false);
useEffect(() => {
loadComments();
}, [blogId]);
const loadComments = async () => {
try {
const commentAPI = new CommentAPI("/api/v1", accessToken);
const fetchedComments = await commentAPI.getBlogComments(blogId);
setComments(fetchedComments);
} catch (error) {
console.error("Failed to load comments:", error);
}
};
const handleSubmitComment = async (e) => {
e.preventDefault();
if (!newComment.trim()) return;
setLoading(true);
try {
const commentAPI = new CommentAPI("/api/v1", accessToken);
const createdComment = await commentAPI.createComment(blogId, newComment);
setComments([...comments, createdComment]);
setNewComment("");
} catch (error) {
alert("Failed to create comment: " + error.message);
}
setLoading(false);
};
const handleDeleteComment = async (commentId) => {
if (!confirm("Are you sure you want to delete this comment?")) return;
try {
const commentAPI = new CommentAPI("/api/v1", accessToken);
await commentAPI.deleteComment(commentId);
setComments(comments.filter((c) => c._id !== commentId));
} catch (error) {
alert("Failed to delete comment: " + error.message);
}
};
return (
<div className="comment-section">
<h3>Comments ({comments.length})</h3>
{/* Comment Form */}
<form onSubmit={handleSubmitComment} className="comment-form">
<textarea
value={newComment}
onChange={(e) => setNewComment(e.target.value)}
placeholder="Write a comment..."
maxLength={1000}
rows={3}
required
/>
<button type="submit" disabled={loading || !newComment.trim()}>
{loading ? "Posting..." : "Post Comment"}
</button>
</form>
{/* Comments List */}
<div className="comments-list">
{comments.map((comment) => (
<div key={comment._id} className="comment">
<div className="comment-content">{comment.content}</div>
<div className="comment-meta">
<span className="comment-date">
{new Date(comment.createdAt).toLocaleDateString()}
</span>
<span className="comment-likes">{comment.likesCount} likes</span>
<button
onClick={() => handleDeleteComment(comment._id)}
className="delete-button"
>
Delete
</button>
</div>
</div>
))}
</div>
{comments.length === 0 && (
<p className="no-comments">No comments yet. Be the first to comment!</p>
)}
</div>
);
};
Content Guidelines
Comment Content
Length: Maximum 1000 characters
Format: Plain text (HTML is not processed)
Language: Should be respectful and constructive
Links: URLs are not automatically converted to clickable links
Moderation
Comments are not pre-moderated
Users can delete their own comments
Admins can delete any comment
Consider implementing reporting functionality for inappropriate content
Best Practices
For Users
Be Constructive: Provide helpful, relevant feedback
Stay On Topic: Keep comments related to the blog post
Be Respectful: Maintain a professional and courteous tone
Check Length: Ensure comments are under 1000 characters
For Developers
Input Validation: Always validate comment content on both client and server
Rate Limiting: Consider implementing comment rate limiting to prevent spam
Error Handling: Provide clear error messages for failed operations
Real-time Updates: Consider WebSocket integration for real-time comment updates
Pagination: Implement pagination for blogs with many comments
Security Considerations
XSS Prevention: Sanitize comment content before display
Authorization: Always verify user permissions before allowing operations
Content Filtering: Consider implementing profanity filters
Spam Detection: Implement basic spam detection mechanisms
Future Enhancements
The current comment system can be extended with:
Comment Likes: Allow users to like/unlike comments
Nested Replies: Support threaded comment conversations
Edit Comments: Allow users to edit their comments within a time limit
Comment Notifications: Notify blog authors of new comments
Rich Text: Support for basic markdown formatting
Comment Search: Search functionality within comments
User Mentions: @ mention functionality for other users
Last updated