DeleteFileHandler Documentation
Overview
The DeleteFileHandler class is an HTTP handler that enables authenticated users to delete
files from their website's file structure. It provides a secure API endpoint for file
deletion operations initiated from the web-based file management interface.
Purpose
This handler is part of the multi-tenant hosting service's file management system, allowing
users to remove unwanted or outdated files from their allocated storage space. It ensures
that only authenticated users can delete files and that they can only do so within their
own account boundaries.
Core Functionality
This handler performs the following key operations:
1. Request Validation
- Only accepts POST requests
- Returns HTTP 405 (Method Not Allowed) for non-POST methods
- Expects JSON payload containing the file path and filename
2. Authentication & Authorization
- Extracts and validates the session ID from the request via getJavaSessionId()
- Verifies the session through SessionManager.getUsername()
- Rejects requests with invalid or expired sessions (HTTP 403)
- Ensures users can only delete files within their own directory space
3. Path Construction
The handler builds the target file path based on the authenticated user:
- Standard users: {USER_DIR}/{username}/static/{path}{filename}
- Administrator (ADMIN_HOST match): {ADMIN_DIR}/static/{path}{filename}
Where:
- USER_DIR is the base directory for user accounts (likely /home/lukas/users/)
- ADMIN_DIR is the special directory for administrative content (likely /home/lukas/JavaServerProject/www)
- {path} is the optional subdirectory path provided in the JSON request body
- {filename} is the name of the file to delete, provided in the JSON request body
4. File Existence Verification
- Checks if the target file exists using Files.exists()
- Prevents errors by validating file existence before attempting deletion
- Provides specific feedback when files don't exist
5. File Deletion
- Attempts to delete the file using Files.delete()
- Wraps deletion in try-catch to handle I/O errors gracefully
- Logs errors to the console for debugging purposes
6. Response Messages
Returns a plain text response indicating the operation result:
- "The file was deleted successfully": File was successfully removed
- "The file does not exist": Target file was not found at the specified path
- "An error occured deleting the file": IOException occurred during deletion (default error message)
Request Format
Method: POST
Content-Type: application/json
Body:
{
"path": "relative/directory/path/",
"filename": "file.ext"
}
The path value should be relative to the user's static directory and may be
empty for files in the root. The filename is the name of the file to delete
(e.g., "image.png", "style.css").
Response Format
Content-Type: text/plain (implicit)
Body: One of the three response messages described above
Response Codes
- 200 OK: Request was processed (check response body for success/failure details)
- 403 Forbidden: Invalid or expired session
- 405 Method Not Allowed: Non-POST request method used
Security Features
- Session-based authentication: All requests require valid session credentials
- User isolation: Users can only delete files within their own directory structure
- Path scoping: File paths are always constructed relative to the user's base directory, preventing directory traversal attacks
- Administrator separation: Special handling for admin accounts with different base paths
- Existence verification: Checks file existence before attempting deletion
Error Handling
- Non-existent files: Returns specific message without attempting deletion
- IOException during deletion: Caught and logged; returns error message to client
- Invalid session: Returns 403 Forbidden before processing request
- Invalid request method: Returns 405 Method Not Allowed
Logging
The handler provides console logging for debugging:
- Logs when parsing the request body
- Logs the received path from the request
- Logs the complete deletion target path
- Logs any IOException errors with detailed messages
Use Cases
This handler is typically invoked when users:
- Remove outdated or unwanted files from their website
- Clean up temporary or test files
- Delete uploaded files that are no longer needed
- Manage storage space by removing unnecessary content
- Remove files before replacing them with updated versions
Dependencies
This handler relies on:
- parseJsonToMap(): Converts JSON request body to a key-value map
- getJavaSessionId(): Extracts session identifier from the HTTP request
- SessionManager.getUsername(): Validates session and retrieves the authenticated username
- USER_DIR: Constant defining the base directory for user accounts
- ADMIN_DIR: Constant defining the base directory for administrative content
- ADMIN_HOST: Constant identifying the administrator username
Behavior Notes
- Always returns HTTP 200 for authenticated requests, regardless of success or failure (check response body for actual status)
- Can delete both files and directories (Files.delete() works for both)
- Does not perform recursive deletion - directories must be empty to be deleted
- Path parameter can be empty or null for files in the root static directory
flowchart TD
A(["Start handle"]) --> B{"Request method
== POST?"}
B -->|No| C["Send 405 Method Not Allowed"]
B -->|Yes| D["Read request body using
InputStreamReader with UTF-8
BufferedReader"]
C --> Z(["End"])
D --> E["Collect body lines into String"]
E --> F["Log: 'Parsing body...'
Parse JSON using parseJsonToMap"]
F --> G["Initialize response =
'An error occured deleting the file'"]
G --> H["Get sessionId via
getJavaSessionId(exchange)"]
H --> I["Get username from
SessionManager.getUsername(sessionId)"]
I --> J{"Username
is null?"}
J -->|Yes| K["Send 403 Forbidden
Close response body"]
J -->|No| L["Log: 'Recived path: {map.get(path)}'"]
K --> Z
L --> M["Build base userPath:
USER_DIR + user + /static/"]
M --> N{"Username ==
ADMIN_HOST?"}
N -->|Yes| O["Override userPath:
ADMIN_DIR + /static/"]
N -->|No| P["Keep user base path"]
O --> Q
P --> Q
Q{"map.get(path) not
empty and not null?"}
Q -->|Yes| R["Append path to userPath"]
Q -->|No| S["Keep userPath as is"]
R --> T["Append filename:
userPath += map.get(filename)"]
S --> T
T --> U["Create Path object:
path = Paths.get(userPath)"]
U --> V["Log: 'Delete target: {path.toString()}'"]
V --> W{"Files.exists(path)?"}
W -->|No| X["Set response =
'The file does not exist'"]
W -->|Yes| Y["TRY: Files.delete(path)"]
Y --> AA{"Deletion
successful?"}
AA -->|Success| AB["Set response =
'The file was deleted successfully'"]
AA -->|IOException| AC["CATCH: Log error message
response remains default error"]
AB --> AD
AC --> AD
X --> AD
AD["Send 200 response
with response.length()"]
AD --> AE["Write response bytes
to OutputStream"]
AE --> AF["Close OutputStream"]
AF --> Z