Skip to content

Allow downloading a database through a proxy - #102

Merged
peter-gribanov merged 3 commits into
gpslab:masterfrom
peter-gribanov:proxy
Aug 7, 2026
Merged

peter-gribanov merged 3 commits into
gpslab:masterfrom
peter-gribanov:proxy

Conversation

@peter-gribanov

@peter-gribanov peter-gribanov commented Aug 7, 2026 •

Copy link
Copy Markdown
Member

Closes #95

The documentation suggested using the source URL option to go through a proxy, but that option is the address of the database, not of the proxy — hence the confusion in the issue. This adds a real proxy option and fixes the misleading sentence.

gpslab_geoip:
    license: 'XXXXXXXXXXXXXXXX'
    edition: 'GeoLite2-City'
    proxy: 'http://user:password@proxy.example.com:3128'

The http, https, socks4, socks4a, socks5 and socks5h schemes are accepted. Credentials can be a part of the address and are url decoded.

How it works

Filesystem::copy() opens the source with the default stream context, so no transport option can be handed to it. The downloader now fetches the archive itself:

  • with cURL when the extension is installed — it is the only way to reach a SOCKS proxy, to authenticate against a proxy with anything other than Basic, and to download at all when allow_url_fopen is disabled;
  • with PHP streams otherwise — HTTP proxies only, Basic authentication only. A SOCKS proxy given to this path is rejected with an explicit error rather than silently ignored.

ext-curl is not a new requirement, it goes to suggest. This mirrors how splitbrain/php-archive is already handled in the downloader: use the better tool when it is there, fall back otherwise. So the bundle keeps working down to Symfony 2.8 and PHP 7.2 with no new dependency.

Backward compatibility

  • the Downloader interface is untouched;
  • MaxMindDownloader gets the proxy as an optional fourth constructor argument;
  • the new config option has no default, so the processed configuration is unchanged when it is not set.

The one behaviour change: the archive is no longer fetched through Filesystem::copy(). Filesystem is still used for every filesystem operation, and failures still raise its IOException.

Tests

195 tests (was 165), both download paths covered:

  • the cURL path runs against a real proxy started in a separate process. It answers the first request with a 407 challenge, so the test proves that curl sends the absolute URI in the request line and retries with Proxy-Authorization — and that the downloaded archive is intact.
  • the streams path uses a stream wrapper that captures the context the archive is opened with, asserting the proxy address, the transport translation and the header.

Verified locally on the stacks the CI matrix resolves: PHP 7.2 + Symfony 2.8, PHP 8.0 + Symfony 5.2, PHP 8.3 + Symfony 7.4 and PHP 8.5 + Symfony 8.1 — tests and PHPStan green on all of them, PHP CS Fixer clean.

🤖 Generated with Claude Code

peter-gribanov and others added 3 commits August 7, 2026 18:30
Add the "proxy" option. Filesystem::copy() opens the source with the
default stream context, so a proxy can not be given to it and the archive
is fetched by the downloader itself when a proxy is configured.

The option takes the address of the proxy server, credentials included:

    gpslab_geoip:
        proxy: 'http://user:password@proxy.example.com:3128'

The http, https, tcp and ssl schemes are accepted, an application protocol
is replaced with the transport PHP expects and the credentials are moved to
the Proxy-Authorization header. A proxy of any of these schemes downloads a
database over HTTPS, PHP tunnels the request with CONNECT.

The documentation suggested to use the source URL option for a proxy, which
is the address of the database and not of the proxy. It is fixed.

Closes gpslab#95

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
PHP streams support HTTP proxies only, so a SOCKS proxy was out of reach,
and they need the allow_url_fopen option, which is disabled on a hardened
server. cURL has neither limitation.

The extension is optional, exactly like splitbrain/php-archive: cURL is used
when it is installed and PHP streams are the fallback. A SOCKS proxy given
to the fallback is rejected with an explicit error instead of being ignored.

The accepted proxy schemes become http, https, socks4, socks4a, socks5 and
socks5h. The tcp and ssl schemes are dropped, they leaked the transport PHP
streams expect into the configuration.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@peter-gribanov
peter-gribanov merged commit 92a2660 into gpslab:master Aug 7, 2026
26 of 27 checks passed
@peter-gribanov
peter-gribanov deleted the proxy branch August 7, 2026 16:40
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.

Update maxmind file via proxy

1 participant