FetchFileContent Documentation

Overview

The FetchFileContent class is an HTTP handler that enables authenticated users to retrieve the complete contents of files from their website's file structure. It provides a secure API endpoint for reading file contents, typically used by the web-based file editor or viewer interface.


Purpose

This handler is part of the multi-tenant hosting service's file management system, allowing users to access and read their files through the web interface. It is commonly used for editing operations where the client needs to load existing file contents into an editor, or for previewing file contents before modification.


Core Functionality

This handler performs the following key operations:


1. Request Validation


2. Authentication & Authorization


3. Path Construction

The handler builds the target file path based on the authenticated user:

Where:


4. File Existence Verification


5. File Content Retrieval


6. Response Format

Returns the complete file contents with:


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 read (e.g., "index.html", "script.js", "style.css").


Response Format

Content-Type: text/plain; charset=UTF-8

Body: Raw file contents (all bytes)


Response Codes


Security Features


Error Handling


Logging

The handler provides console logging for debugging:


Use Cases

This handler is typically invoked when users:


Dependencies

This handler relies on:


Behavior Notes


Performance Considerations


Potential Improvements

flowchart TD A(["Start handle"]) --> B{"Request method
== POST?"} B -->|No| C["Return silently
(No response sent)"] B -->|Yes| D["Read request body using
InputStreamReader with UTF-8
BufferedReader"] C --> Z(["End"]) D --> E["Collect body lines into String"] E --> F["Get sessionId via
getJavaSessionId(exchange)"] F --> G["Get username from
SessionManager.getUsername(sessionId)"] G --> H{"Username
is null?"} H -->|Yes| I["Send 403 Forbidden
Close response body"] H -->|No| J["Parse JSON body
using parseJsonToMap"] I --> Z J --> K["Initialize response byte array"] K --> L["Build base userPath:
USER_DIR + user + /static/"] L --> M{"Username ==
ADMIN_HOST?"} M -->|Yes| N["Override userPath:
ADMIN_DIR + /static/"] M -->|No| O["Keep user base path"] N --> P O --> P P{"map.get(path) not
empty and not null?"} P -->|Yes| Q["Append path to userPath"] P -->|No| R["Keep userPath as is"] Q --> S["Append filename:
userPath += map.get(filename)"] R --> S S --> T["Create Path object:
path = Paths.get(userPath)"] T --> U{"Files.exists(path)?"} U -->|No| V["Log: 'No file found at: {path.toString()}'"] U -->|Yes| W["Read file contents:
response = Files.readAllBytes(path)"] V --> X["Send 403 Forbidden
Close response body"] X --> Z W --> Y["Set Content-Type header:
text/plain; charset=UTF-8"] Y --> AA["Send 200 response
with response.length"] AA --> AB["Write response bytes
to OutputStream"] AB --> AC["Close OutputStream"] AC --> Z