Title: Divine Apparitions Uploads Proxy
Author: philltran
Published: <strong>July 1, 2026</strong>
Last modified: July 1, 2026

---

Search plugins

![](https://s.w.org/plugins/geopattern-icon/divine-apparitions-uploads-proxy.svg)

# Divine Apparitions Uploads Proxy

 By [philltran](https://profiles.wordpress.org/philltran/)

[Download](https://downloads.wordpress.org/plugin/divine-apparitions-uploads-proxy.0.11.1.zip)

 * [Details](https://wordpress.org/plugins/divine-apparitions-uploads-proxy/#description)
 * [Reviews](https://wordpress.org/plugins/divine-apparitions-uploads-proxy/#reviews)
 *  [Installation](https://wordpress.org/plugins/divine-apparitions-uploads-proxy/#installation)
 * [Development](https://wordpress.org/plugins/divine-apparitions-uploads-proxy/#developers)

 [Support](https://wordpress.org/support/plugin/divine-apparitions-uploads-proxy/)

## Description

When you pull a production database into a staging or local environment, every media
URL points at a file you didn’t copy — pages render with broken images and dead 
file links. Divine Apparitions Uploads Proxy intercepts the request for any _missing_
uploads file and resolves it against a configured production **Origin**, so pages
render with real media without syncing the entire uploads directory.

Because it works at the request level — hooking `template_redirect` when the web
server routes a missing file to `index.php` (nginx `try_files`, used by DDEV, Lando,
and Pantheon) — it catches _every_ missing upload, including images embedded directly
in post content, size derivatives, and `srcset` candidates, not just the URLs WordPress
generates for attachments.

It resolves a missing file in one of two modes:

 * **Download mode** (default): streams the file from the Origin, saves it into 
   the local uploads directory, and serves it. Every later request is served by 
   the web server, so your local site accumulates exactly the subset of media your
   tests actually touch — never the whole uploads folder.
 * **Hotlink mode** (opt-in): issues a temporary redirect to the file on the Origin,
   writing nothing locally.

Configuration lives in `wp-config` constants / environment variables (with a database-
option fallback), so it survives every database pull and configures itself hands-
free in CI. The plugin is inert on production and stays off until an Origin is configured.

Features:

 * Request-level interception — resolves content-embedded images, derivatives, and`
   srcset`, not just attachment URLs.
 * Download or Hotlink mode, chosen per environment.
 * Optional Basic Auth for fetching from a locked Test/Dev Origin.
 * Negative cache so a file genuinely missing on the Origin stops re-hitting it,
   while transient errors (5xx/timeout) retry on the next request.
 * Write hardening: executable file types are refused and paths are contained to
   the uploads directory.
 * Diagnostics settings page showing the effective config and its source, the counters,
   and a “test Origin connection” button.
 * `wp uploads-proxy` WP-CLI command (`status` / `clear-cache`) for scripting setup
   and reset in CI.
 * Inert on production; off until an Origin is configured.

## Installation

 1. Install the plugin from the **Plugins  Add New** screen, or upload the `divine-
    apparitions-uploads-proxy` directory to `/wp-content/plugins/`.
 2. Activate the plugin through the **Plugins** menu in WordPress.
 3. Configure the Origin and mode via a `wp-config` constant or environment variable(
    recommended — these survive a production database pull and work hands-free in CI),
    or as a fallback from **Settings  Uploads Proxy**.

## FAQ

### Does this download files to my local environment?

In Download mode (the default), yes — each missing file is fetched from the Origin
once, saved into your local uploads directory, and served; every later request is
served directly by the web server. In Hotlink mode nothing is written locally — 
the browser is redirected to the file on the Origin.

### How do I configure it so my settings survive a database pull?

Set the Origin (and mode, and optional Basic Auth) in a `wp-config` constant or 
an environment variable. Configuration resolves in the order constant  environment
variable  database option  off, so constants/env always win over anything a pulled
production database might carry. The settings page is only a fallback for when no
constant or env var is set.

### Will it run on production?

No. When `wp_get_environment_type()` returns `production`, the proxy stays inactive.

### I’m on Apache and nothing happens. Why?

Request interception needs the web server to route a missing file to `index.php`.
On nginx (DDEV, Lando, Pantheon) this always happens. On Apache it only happens 
with pretty permalinks enabled — the plugin shows an admin notice for this case.
Enable pretty permalinks at **Settings  Permalinks**.

### My SVGs are broken in Download mode. Why?

Download mode only saves files whose type WordPress recognises on a front-end request,
and SVG is usually not on that list (the _SVG Support_ plugin registers it only 
for logged-in uploaders). Either add a one-line `uploads_proxy_is_allowed_file` 
filter to opt SVG in (see the readme/README), or switch to Hotlink mode, which redirects
to the Origin and applies no write gate.

### Large files time out in Download mode. Can I fix that?

The whole file is buffered in memory, so the default Origin timeout is a short 15
seconds. Raise it with the `uploads_proxy_origin_timeout` filter, or use Hotlink
mode to avoid downloading large files locally at all.

## Reviews

There are no reviews for this plugin.

## Contributors & Developers

“Divine Apparitions Uploads Proxy” is open source software. The following people
have contributed to this plugin.

Contributors

 *   [ philltran ](https://profiles.wordpress.org/philltran/)

[Translate “Divine Apparitions Uploads Proxy” into your language.](https://translate.wordpress.org/projects/wp-plugins/divine-apparitions-uploads-proxy)

### Interested in development?

[Browse the code](https://plugins.trac.wordpress.org/browser/divine-apparitions-uploads-proxy/),
check out the [SVN repository](https://plugins.svn.wordpress.org/divine-apparitions-uploads-proxy/),
or subscribe to the [development log](https://plugins.trac.wordpress.org/log/divine-apparitions-uploads-proxy/)
by [RSS](https://plugins.trac.wordpress.org/log/divine-apparitions-uploads-proxy/?limit=100&mode=stop_on_copy&format=rss).

## Changelog

#### 0.11.1

 * Maintenance release: version bump only, no functional changes.

#### 0.11.0

 * Renamed the plugin to **Divine Apparitions Uploads Proxy** (slug and text domain`
   divine-apparitions-uploads-proxy`) for the WordPress.org directory; internal 
   option keys, filters, the `X-Uploads-Proxy` header, and the `wp uploads-proxy`
   CLI command are unchanged.
 * Added an `uploads_proxy_is_allowed_file` filter so types WordPress omits on the
   front end (notably SVG) can be proxied in Download mode; executables can never
   be re-enabled through it.
 * Added an `uploads_proxy_origin_timeout` filter to adjust the outbound Origin 
   timeout (default 15s) for large media on a slow link.
 * Fixed: a Download-mode Miss is served with HTTP 200 (was 404 on the first request).
 * Fixed: a Hotlink-mode Miss returns a real 302 even behind a page cache that tracks
   status through `status_header()` (e.g. Pantheon Advanced Page Cache); all responses
   now set status via `status_header()`.
 * Fixed: percent-encoded filenames (e.g. a space) are decoded before the local 
   lookup, so the file is saved under its real name instead of a junk “%20” copy
   that is re-proxied every request; also hardens the scope against encoded `../`
   and null bytes.
 * Added a settings-screen notice when the proxy is enabled but the environment 
   type is `production`.

#### 0.10.0

 * Clean up after the plugin on uninstall: deleting the plugin removes its settings
   option, both counters (downloaded total and Negative-cache size), and every Negative-
   cache transient — on every site of a multisite network. Downloaded media in the
   uploads directory is never deleted, so you keep any files you pulled in.

#### 0.9.0

 * Add an admin notice for the Apache plain-permalinks edge case: when the proxy
   is active on Apache without pretty permalinks (so interception can’t fire), a
   notice explains that pretty permalinks are required. Never shown on nginx, with
   pretty permalinks, when inert, or on production.

#### 0.8.0

 * Add the `wp uploads-proxy` WP-CLI command. `status` reports the active state,
   effective Origin, mode and each value’s source, and both counters (`--format=
   table|json|yaml|csv`). `clear-cache` clears the Negative cache and resets the
   counters without deleting downloaded media. Registered only under WP-CLI.

#### 0.7.0

 * Replace the plain settings form with a diagnostics-first **Settings  Uploads 
   Proxy** page: status panel with the effective Origin/mode/Basic-Auth each labelled
   by source, the downloaded and Negative-cache counters, and a “test Origin connection”
   button (graded reachable on a 2xx response only).
 * Fields are editable only when no constant/env var overrides them; an overridden
   field is shown read-only with its source. The Basic Auth password is write-only—
   never rendered into the page — and an empty save no longer blanks the stored 
   password.

#### 0.6.0

 * Add Hotlink mode: when `mode = hotlink`, a Miss issues a `302` temporary redirect(
   never `301`) to the file on the Origin with an `X-Uploads-Proxy: hotlink` header,
   writing nothing locally. Download mode remains the default.

#### 0.5.0

 * Add the Miss-fallback + Negative cache. An Origin `404`/`410` serves a local `
   404` (`X-Uploads-Proxy: negative`) and records a short-lived transient so repeat
   Misses short-circuit without re-hitting the Origin; an Origin `5xx`/timeout serves`
   404` without caching so the next request retries.

#### 0.4.0

 * Harden the download writer: a two-layer gate denies executable extensions (`.
   php`, `.phtml`, `.cgi`, …) and admits only WordPress-permitted MIME types, so
   a disallowed type from the Origin returns a local `404` and writes nothing. Reinforces
   path containment and host-fixed Origin fetch.

#### 0.3.0

 * Add the request-interception walking skeleton (ADR-0001): on a Miss for a missing
   Uploads path, Download mode fetches the file from the Origin, atomically saves
   it into the local uploads directory, and serves it with an `X-Uploads-Proxy: 
   download` header. Replaces the URL-rewriting media proxy.
 * Inert on production and until an Origin is configured. Stands up a `@wordpress/
   env` integration test harness that boots real WordPress with a mocked Origin.

#### 0.2.0

 * Add a configuration resolver that resolves the Origin, mode, and Basic Auth in
   the order constant  environment variable  database option  off, reporting each
   value’s source.
 * Reshape the stored settings to an enabled flag, Origin URL, mode (Download/Hotlink),
   and Basic Auth credentials. The plugin stays off until an Origin is configured.

#### 0.1.0

 * Initial scaffold: settings page, URL-rewriting media proxy, and tooling.

## Meta

 *  Version **0.11.1**
 *  Last updated **24 hours ago**
 *  Active installations **Fewer than 10**
 *  WordPress version ** 6.5 or higher **
 *  Tested up to **7.0**
 *  PHP version ** 8.2 or higher **
 * Tags
 * [development](https://wordpress.org/plugins/tags/development/)[media](https://wordpress.org/plugins/tags/media/)
   [proxy](https://wordpress.org/plugins/tags/proxy/)[staging](https://wordpress.org/plugins/tags/staging/)
   [uploads](https://wordpress.org/plugins/tags/uploads/)
 *  [Advanced View](https://wordpress.org/plugins/divine-apparitions-uploads-proxy/advanced/)

## Ratings

No reviews have been submitted yet.

[Your review](https://wordpress.org/support/plugin/divine-apparitions-uploads-proxy/reviews/#new-post)

[See all reviews](https://wordpress.org/support/plugin/divine-apparitions-uploads-proxy/reviews/)

## Contributors

 *   [ philltran ](https://profiles.wordpress.org/philltran/)

## Support

Got something to say? Need help?

 [View support forum](https://wordpress.org/support/plugin/divine-apparitions-uploads-proxy/)