Skip to content

Add admin endpoint to stream list of stored filenames#51

Open
hauxir wants to merge 2 commits into
masterfrom
feature/admin-list-files
Open

Add admin endpoint to stream list of stored filenames#51
hauxir wants to merge 2 commits into
masterfrom
feature/admin-list-files

Conversation

@hauxir

@hauxir hauxir commented Apr 14, 2026

Copy link
Copy Markdown
Owner

Summary

  • Adds GET /admin/files that streams filenames from IMAGES_DIR one per line (text/plain), using os.scandir so memory usage is flat regardless of store size.
  • Gated by the existing Bearer API_KEY via check_auth.
  • Supports optional ?prefix= filtering and ?limit= for sampling.
  • Registered before the /{filename:path} catch-all so it is not swallowed as a filename lookup.

Usage:

curl -H "Authorization: Bearer \$API_KEY" https://host/admin/files > all.txt

Test plan

  • curl with valid key returns filenames, one per line
  • curl without / with wrong key returns 403
  • ?prefix=abc filters results
  • ?limit=10 caps results
  • Response begins streaming immediately on a large directory (no full-list buffering)

🤖 Generated with Claude Code

GET /admin/files streams one filename per line from IMAGES_DIR using
os.scandir, so memory stays flat even for very large stores. Gated by
the existing Bearer API key. Supports optional ?prefix= and ?limit=.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Review Summary by Qodo

Add admin endpoint to stream list of stored filenames

✨ Enhancement

Grey Divider

Walkthroughs

Description
• Adds GET /admin/files endpoint to stream stored filenames
• Uses os.scandir for memory-efficient streaming regardless of store size
• Supports optional ?prefix= filtering and ?limit= sampling parameters
• Secured with existing Bearer token authentication via check_auth
Diagram
flowchart LR
  A["GET /admin/files<br/>endpoint"] -->|"scandir<br/>IMAGES_DIR"| B["Stream filenames<br/>one per line"]
  B -->|"optional<br/>?prefix="| C["Filter by prefix"]
  B -->|"optional<br/>?limit="| D["Limit results"]
  A -->|"Bearer token"| E["check_auth<br/>validation"]
Loading

Grey Divider

File Changes

1. app/app.py ✨ Enhancement +26/-1

Add streaming admin endpoint for file listing

• Imported StreamingResponse from fastapi.responses
• Added new GET /admin/files endpoint that streams filenames from IMAGES_DIR
• Implemented iter_names() generator using os.scandir for memory-efficient iteration
• Supports optional ?prefix= query parameter to filter filenames by prefix
• Supports optional ?limit= query parameter to cap number of results returned
• Secured endpoint with check_auth() validation using Bearer token

app/app.py


Grey Divider

Qodo Logo

@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Apr 14, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0)

Grey Divider


Remediation recommended

1. Raw filename line injection🐞
Description
/admin/files yields entry.name + "\n" without escaping, so any stored filename containing
\n/\r will be split into multiple lines and corrupt the one-filename-per-line output format for
consumers.
Code

app/app.py[R208-213]

+                if prefix and not entry.name.startswith(prefix):
+                    continue
+                yield entry.name + "\n"
+                count += 1
+                if limit and count >= limit:
+                    return
Evidence
The endpoint’s streaming generator writes each filename directly into a line-oriented format by
concatenating a newline, with no sanitization/escaping step before emitting the value.

app/app.py[193-216]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`/admin/files` is documented/implemented as “one filename per line”, but it currently streams raw `entry.name` plus a newline. Filenames can contain newline/carriage-return characters, which will corrupt the line-based format (one file can appear as multiple lines).
## Issue Context
The streaming generator in `list_files()` yields `entry.name + "\n"` directly.
## Fix Focus Areas
- app/app.py[193-216]
## Suggested change
- Sanitize/escape `entry.name` before yielding (at minimum replace `\n` and `\r` with escaped sequences like `\\n`/`\\r`).
- (Optional hardening) Yield bytes with explicit encoding (e.g. `encode("utf-8", "surrogateescape")`) to avoid response encoding issues from unusual filesystem names.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

Filenames containing newline or carriage-return characters would have
split across lines in the previous plain-text format. Emit one
JSON-encoded string per line instead so any byte sequence round-trips
cleanly.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant