3.0 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project
http2pic - PHP website renderer that takes screenshots of URLs and returns them as images. Live at https://http2pic.haschek.at/
Architecture
Entry point: web/index.php - PSR-4 router with two paths:
/api- Chrome/Chromium screenshot via Selenium WebDriver (php-webdriver). Takesurl,viewport(WIDTHxHEIGHT),js(true/false) params. Connects tolocalhost:4444ChromeDriver, sets window size, disables scrollbars, takes screenshot as PNG.- default - renders
src/templates/index.html.php(landing page).
Legacy class: src/http2pic.class.php - Old wkhtmltoimage-based renderer (deprecated, not used in production). Supports PNG/JPG, viewport, resize, URL reachability check, file caching.
Helpers: src/helpers.php - renderTemplate(), addToLog(), getUserIP().
Config: src/config.inc.php - set at build time by start.sh from URL env var.
Running
Docker (production):
docker compose up -d
Services: Caddy (:80), PHP-FPM, ChromeDriver (:4444). Volumes: ./cache and ./logs. Configured via URL env var.
Dev container: .devcontainer/ - same stack, run ./devcontainer/start.sh. Forward port 8080.
Quick test:
php -S localhost:8080 -t web/
# Then visit http://localhost:8080/api?url=<target>
Key files
| File | Purpose |
|---|---|
web/index.php |
API + template router |
src/http2pic.class.php |
Legacy wkhtmltoimage renderer |
src/helpers.php |
Template render, logging, IP helper |
src/config.inc.php |
Runtime config (URL, API_KEY, BLOCK_PRIVATE_IPS) |
docker/Caddyfile |
Reverse proxy, PHP-FPM, file server |
docker/start.sh |
Boots PHP-FPM, ChromeDriver, writes config |
docker-compose.yml |
Production compose |
API Key
Set API_KEY env var in docker-compose to require authentication on all /api requests.
Leave unset (default) for open access.
# via header (preferred — not logged in access logs)
curl -H "X-API-Key: your-secret-key" "http://host/api?url=https://example.com"
# via query param
curl "http://host/api?key=your-secret-key&url=https://example.com"
SSRF Protection
Set BLOCK_PRIVATE_IPS=true to reject requests to LAN, loopback, and cloud metadata IPs.
Recommended when hosting publicly. Default is off (allows local/LAN addresses).
Note: DNS rebinding attacks can bypass this protection (attacker-controlled DNS can return a public IP during validation and a private IP when Chrome actually connects). Full protection requires a network-level egress firewall.
Caveats
web/index.phphas avar_dump($cmd)debug statement left inhttp2pic.class.php:181- remove before shipping.- Legacy
http2pic.class.phphas a variable scoping bug: line 109 uses$urlinstead of$this->params['url']. - Cache dir permissions must be
777(set bystart.sh). - ChromeDriver must be running on
localhost:4444for the API to work.