Skip to content

Instantly share code, notes, and snippets.

@kasparsd
Last active October 1, 2024 13:26
Show Gist options
  • Save kasparsd/6afae57835c93d1c778233545e3eacba to your computer and use it in GitHub Desktop.
Save kasparsd/6afae57835c93d1c778233545e3eacba to your computer and use it in GitHub Desktop.
Replace WP.org API calls with custom hostnames
<?php
/**
* Plugin Name: WP API Mirror Config
*
* Place this file in `wp-content/mu-plugins/wp-api-mirror.php`
* and it will be activated automatically.
*
* Note that most requests to api.wordpress.org contain dynamic payload
* such as list of activated plugins, themes and your site URLs. Some of
* them also use POST requests so be sure to configure heavy caching that
* accounts for the full request payload.
*/
// Replace all requests to wp.org APIs with custom hostnames.
add_action(
'http_api_curl',
function ( $handle, $parsed_args, $url ) {
$hostname_map = [
// REPLACE these with your own hostnames.
'api.wordpress.org' => 'reverse.example.net/wp-api',
'downloads.wordpress.org' => 'reverse.example.net/wp-downloads',
];
// Attempt to rewrite the request hostname.
$url_replaced = str_replace(
array_keys( $hostname_map ),
array_values( $hostname_map ),
$url
);
if ( $url_replaced !== $url ) {
curl_setopt( $handle, CURLOPT_URL, $url_replaced );
}
},
1000,
3
);
#
# THIS IS A SAMPLE CONFIGURATION FOR EDUCATIONAL PURPOSES ONLY! PLEASE
# DON'T ABUSE THE WP.ORG SERVERS AND HOST YOUR OWN REPLICAS INSTEAD!
#
# Reverse proxies like this are still putting load on the origin servers
# and can be easily blocked by IP or rate limiting.
#
# Place this under /etc/nginx/sites-enabled/wp-api-reverse.conf
#
# Configure proxy cache for all responses.
proxy_cache_path /var/cache/nginx-reverse levels=1:2 keys_zone=REVERSE:10m inactive=24h max_size=1g;
server {
server_name reverse.example.com;
listen 443 ssl http2;
# Specify the DNS server used for resolving the origin hostname IPs.
resolver 8.8.8.8;
# Disable logs for these requests.
access_log off;
location /wp-api/ {
proxy_pass https://api.wordpress.org/;
proxy_cache REVERSE;
proxy_cache_key "$host$request_uri";
proxy_cache_valid 200 1h;
proxy_ignore_headers Expires Cache-Control Set-Cookie;
proxy_intercept_errors on;
proxy_cache_use_stale error timeout invalid_header updating http_500 http_502 http_503 http_504;
}
location /wp-downloads/ {
proxy_pass https://downloads.wordpress.org/;
proxy_cache REVERSE;
proxy_cache_key "$host$request_uri";
proxy_cache_valid 200 1h;
proxy_hide_header Link;
proxy_ignore_headers Expires Cache-Control Set-Cookie;
proxy_intercept_errors on;
proxy_cache_use_stale error timeout invalid_header updating http_500 http_502 http_503 http_504;
}
# Additional TLS config goes here.
}
@kasparsd
Copy link
Author

See this gist with notes on the WP API endpoints and their functionality https://gist.github.com/kasparsd/0b0cec8548b0115f5611f814d534b9aa

@devhaozi
Copy link

It looks like wordpress has blocked all Nginx proxy traffic, and wpmirror.com is now failing to download any files with a 434 error code.

I'm both saddened and shocked that .org has become a private property.

A temporary fix was deployed to resolve this issue, let's see what else happens.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment