Published on
Library Management System with Simple CRUD Operations in Go
Abstract:
The Library App provides a REST API for managing a collection of books, enabling basic CRUD operations. The structure supports scalability and potential future integration with authentication, persistent storage, and structured error handling.
Problem Statement:
Manual record-keeping in small to medium-sized libraries can lead to data inconsistencies and hinder data access. The Library App addresses these challenges by providing a centralized API for managing book data, enabling structured data storage and retrieval.
Objectives:
Implement a REST API for managing book records with a modular architecture that ensures code maintainability and scalability. The current version uses in-memory storage but is structured to support database integration and additional features in future updates.
Usage
Base URL: http://localhost:8080
Create Book:
- Endpoint:
POST /books
- Description: Adds a new book to the library.
- Request Body:
{ "title": "string", "author": "string", "year": int }
Valid Input:
curl -X POST http://localhost:8080/books \
-H "Content-Type: application/json" \
-d '{ "title": "Clean Code", "author": "Robert C. Martin", "year": 2008 }'
Expected Response (201 Created):
{"id": 1, "title": "Clean Code", "author": "Robert C. Martin", "year": 2008}
Invalid JSON Input:
curl -X POST http://localhost:8080/books \
-H "Content-Type: application/json" \
-d 'Invalid JSON'
Expected Response (400 Bad Request):
{"type": "/errors/create-book", "title": "Invalid Input", "status": 400, "detail": "The input provided is not in the expected format.", "instance": "create-book"}
Missing Fields:
curl -X POST http://localhost:8080/books \
-H "Content-Type: application/json" \
-d '{ "title": "", "author": "Author", "year": 2020 }'
Expected Response (400 Bad Request):
{"type": "/errors/create-book", "title": "Missing Fields", "status": 400, "detail": "Title, Author, and Year are required fields.", "instance": "create-book"}
Get Book by ID:
- Endpoint:
GET /books/{id}
- Description: Retrieves a book by its ID.
Valid ID:
curl -X GET http://localhost:8080/books/1
Expected Response (200 OK):
{"id": 1, "title": "Clean Code", "author": "Robert C. Martin", "year": 2008}
Invalid ID (Non-Numeric):
curl -X GET http://localhost:8080/books/abc
Expected Response (400 Bad Request):
{"type": "/errors/get-book", "title": "Invalid ID", "status": 400, "detail": "The provided ID is not a valid number.", "instance": "get-book"}
Book Not Found:
curl -X GET http://localhost:8080/books/99
Expected Response (404 Not Found):
{"type": "/errors/get-book", "title": "Book Not Found", "status": 404, "detail": "No book found with the provided ID.", "instance": "get-book"}
Get All Books:
- Endpoint:
GET /books
- Description: Retrieves all books in the library.
Empty Library:
curl -X GET http://localhost:8080/books
Expected Response (200 OK):
[]
Library with Books: After adding a book using the POST request above:
curl -X GET http://localhost:8080/books
Expected Response (200 OK):
[{"id": 1, "title": "Clean Code", "author": "Robert C. Martin", "year": 2008}]
Update Book:
- Endpoint:
PUT /books/{id}
- Description: Updates an existing book record.
Valid Update:
curl -X PUT http://localhost:8080/books/1 \
-H "Content-Type: application/json" \
-d '{ "title": "Clean Code (Updated)", "author": "Robert C. Martin", "year": 2010 }'
Expected Response (200 OK):
{"id": 1, "title": "Clean Code (Updated)", "author": "Robert C. Martin", "year": 2010}
Invalid ID (Non-Numeric):
curl -X PUT http://localhost:8080/books/abc \
-H "Content-Type: application/json" \
-d '{ "title": "New Title", "author": "Author", "year": 2021 }'
Expected Response (400 Bad Request):
{"type": "/errors/update-book", "title": "Invalid ID", "status": 400, "detail": "The provided ID is not a valid number.", "instance": "update-book"}
Missing Fields in Update:
curl -X PUT http://localhost:8080/books/1 \
-H "Content-Type: application/json" \
-d '{ "title": "", "author": "Updated Author", "year": 2021 }'
Expected Response (400 Bad Request):
{"type": "/errors/update-book", "title": "Missing Fields", "status": 400, "detail": "Title, Author, and Year are required fields.", "instance": "update-book"}
Delete Book:
- Endpoint:
DELETE /books/{id}
- Description: Deletes a book by its ID.
Valid Delete:
curl -X DELETE http://localhost:8080/books/1
Expected Response (204 No Content)
Book Not Found for Deletion:
curl -X DELETE http://localhost:8080/books/99
Expected Response (404 Not Found):
{"type": "/errors/delete-book", "title": "Book Not Found", "status": 404, "detail": "No book found with the provided ID.", "instance": "delete-book"}
Technical Architecture:
-
cmd/libraryapp/main.go
: Application entry point. Initializes the server and defines routes. -
internal/library/library.go
: Contains the main logic, including data structures, handlers, and in-memory storage.
Data Validation and Error Handling:
- Title: Required, UTF-8 string, non-empty.
- Author: Required, UTF-8 string, non-empty.
- Year: Required, positive integer.
Error Handling: Error responses are structured as JSON objects for consistency:
{
"type": "/errors/{operation}",
"title": "Error Title",
"status": 400,
"detail": "Detailed error message.",
"instance": "{operation}"
}
Security Considerations:
- No authentication or authorization mechanisms are implemented.
- No input sanitization beyond basic type checking.
- No rate limiting to prevent abuse.
For future enhancement, includes but not limited to:
- Add JWT authentication.
- Implement request rate limiting.
- Apply input sanitization to prevent injection attacks.
Testing Approach:
Testing is implemented using Go’s testing
and httptest
packages. Key scenarios covered:
-
Book Creation: Valid and invalid inputs.
-
Book Retrieval: Existing and non-existing IDs.
-
Book Update: Valid, invalid, and missing fields.
-
Book Deletion: Valid and invalid IDs.
Scalability Considerations:
The application currently uses in-memory storage, which is not suitable for production use.
For future enhancement, includes but not limited to:
-
Integrate persistent storage (e.g., PostgreSQL).
-
Implement caching for frequently accessed endpoints.
-
Apply connection pooling for database access.
-
Introduce rate limiting for heavy traffic.
Limitations and Future Enhancements:
Current Limitations:
- Data Persistence: Data is stored in-memory and lost on server restart.
- Error Responses: Errors are structured as JSON with a consistent format, but lack contextual details such as timestamps or error codes.
- Validation: No length checks for
Title
andAuthor
fields; only basic presence and type validation. - Input Sanitization: Limited to basic type and structure checks; no comprehensive sanitization.
- Logging and Monitoring: Not implemented. No request or error logging is present.
- Authentication: All endpoints are publicly accessible without any form of authentication or authorization.
Planned Enhancements:
- Data Persistence: Implement persistent storage using PostgreSQL.
- Enhanced Error Responses: Add additional context, such as timestamps and error codes, to error responses.
- Validation: Enforce length limits for
Title
(100 chars) andAuthor
(50 chars). - Input Sanitization: Apply input sanitization to mitigate potential injection attacks.
- Logging and Monitoring: Integrate structured logging for requests and errors.
- Authentication: Implement JWT authentication for route protection.
Discussion and feedback