A high-performance CRUD RESTful API server for local machine file management built in Go using net/http and charlievieth/fastwalk.
Caution
This project was written almost by AI
- File/Folder Operations: List, search recursively, create, rename, delete, download, and upload files.
- SSE Upload Progress: Real-time server-sent events indicating percent complete and bytes written during file uploads.
- Race Condition Safety: Path-keyed locking (
sync.Mapof mutexes) ensures operations on the same path are fully serialized while unrelated paths remain parallel. - Security Checkers:
- Rejects symlinks and hardlinks.
- Validates paths against escaping via path-traversal checking.
- Checks for duplicates and validates form data inputs.
- Implements request body limits (
MaxBytesReader) on form inputs to prevent memory exhaustion.
- Conditional Logging Middleware: Build-tag gated logging (
//go:build !production) logs formatMETHOD /path {time}ms.
- Go (1.22+ recommended)
golangci-lint(v2.x) for code analysis
Build the server binary:
makeRun tests:
make testClean build artifacts:
make cleanStart the server using the compiled binary by passing the storage path:
./bin/storage [flags] /path/to/storage-p,--port: Port to listen on (overrides thePORTenvironment variable; defaults to8080).
- Route:
GET /src/{path...} - Response: List of
ItemJSON objects.
- Route:
GET /src/{path...}?q=search_term - Response: List of matching
ItemJSON objects.
- Route:
POST /src/{path...} - Form Data:
newName(name of directory) - Response:
{"path": "relative/path/to/new_folder"}
- Route:
PUT /src/{path...} - Form Data:
newName(new base name) - Response:
{"path": "new_relative_path"}(for folder) or{"status": "oke"}(for file)
- Route:
DELETE /src/{path...} - Response:
{"status": "oke"}
- Route:
POST /upload/{path...} - Form Data:
name: target name of the filefile: binary contents of the file
- Response: Server-Sent Events stream:
- Event payload:
data: {"percent": 45, "bytesWritten": 4500000, "totalBytes": 10000000} - Final success event payload:
data: {"status": "oke", "file": "filename.ext"}
- Event payload:
- Route:
GET /download/{path...} - Response: Serves the raw file content.