77 lines
3.1 KiB
Markdown
77 lines
3.1 KiB
Markdown
# 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). Params: `url`, `viewport` (WIDTHxHEIGHT), `js` (true/false), `fullpage` (true/false), `maxheight` (1–30000, default 15000). Connects to `localhost:4444` ChromeDriver, sets window size, takes screenshot as PNG. In fullpage mode, resizes window to full `scrollHeight` (capped at `maxheight`) instead of hiding overflow.
|
||
- 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.
|
||
|
||
```bash
|
||
# 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.php` has a `var_dump($cmd)` debug statement left in `http2pic.class.php:181` - remove before shipping.
|
||
- Legacy `http2pic.class.php` has a variable scoping bug: line 109 uses `$url` instead of `$this->params['url']`.
|
||
- Cache dir permissions must be `777` (set by `start.sh`).
|
||
- ChromeDriver must be running on `localhost:4444` for the API to work.
|