banner
Barry

Barry

偶尔摆烂,经常偶尔.
twitter
github
tg_channel
medium
email
steam_profiles

How do I solve the pollution of jsDelivr in China?

As early as December 20, 2021, the ICP filing of jsDelivr in mainland China was revoked, and the subsequent service in mainland China became extremely unstable, severely slowing down the speed of web pages.

Due to the blocking of jsDelivr, the web page speed of the CDN service that used to use jsDelivr became slow, and most of the functions were not working properly. To solve this problem, you can either change the CDN or add a reverse proxy to jsDelivr. Here, the blogger chose to use Cloudflare Worker.

Create a Worker#

Log in to the Cloudflare console, click on Workers in the sidebar, and create a new service.

gh

Enter your own service name on the creation page.
gh

After creation, you will be redirected to the resource page.
gh

Deployment#

Click on "Quick Edit" and copy the following code into the code box:

// Replace with the site you want to mirror
const upstream = 'cdn.jsdelivr.net'
 
// If the site has a dedicated mobile site, otherwise keep it the same as above
const upstream_mobile = 'cdn.jsdelivr.net'
 
const blocked_region = ['KP','RU']
 
const blocked_ip_address = ['0.0.0.0', '127.0.0.1']
 
const replace_dict = {
    '$upstream': '$custom_domain',
    '//cdn.jsdelivr.net': ''
}
 
// The following content does not need to be modified
addEventListener('fetch', event => {
    event.respondWith(fetchAndApply(event.request));
})
 
async function fetchAndApply(request) {
 
    const region = request.headers.get('cf-ipcountry').toUpperCase();
    const ip_address = request.headers.get('cf-connecting-ip');
    const user_agent = request.headers.get('user-agent');
 
    let response = null;
    let url = new URL(request.url);
    let url_host = url.host;
 
    if (url.protocol == 'http:') {
        url.protocol = 'https:'
        response = Response.redirect(url.href);
        return response;
    }
 
    if (await device_status(user_agent)) {
        upstream_domain = upstream
    } else {
        upstream_domain = upstream_mobile
    }
 
    url.host = upstream_domain;
 
    if (blocked_region.includes(region)) {
        response = new Response('Access denied: WorkersProxy is not available in your region yet.', {
            status: 403
        });
    } else if(blocked_ip_address.includes(ip_address)){
        response = new Response('Access denied: Your IP address is blocked by WorkersProxy.', {
            status: 403
        });
    } else{
        let method = request.method;
        let request_headers = request.headers;
        let new_request_headers = new Headers(request_headers);
 
        new_request_headers.set('Host', upstream_domain);
        new_request_headers.set('Referer', url.href);
 
        let original_response = await fetch(url.href, {
            method: method,
            headers: new_request_headers
        })
 
        let original_response_clone = original_response.clone();
        let original_text = null;
        let response_headers = original_response.headers;
        let new_response_headers = new Headers(response_headers);
        let status = original_response.status;
 
        new_response_headers.set('access-control-allow-origin', '*');
        new_response_headers.set('access-control-allow-credentials', true);
        new_response_headers.delete('content-security-policy');
        new_response_headers.delete('content-security-policy-report-only');
        new_response_headers.delete('clear-site-data');
 
        const content_type = new_response_headers.get('content-type');
        if (content_type.includes('text/html') && content_type.includes('UTF-8')) {
            original_text = await replace_response_text(original_response_clone, upstream_domain, url_host);
        } else {
            original_text = original_response_clone.body
        }
 
        response = new Response(original_text, {
            status,
            headers: new_response_headers
        })
    }
    return response;
}
 
async function replace_response_text(response, upstream_domain, host_name) {
    let text = await response.text()
 
    var i, j;
    for (i in replace_dict) {
        j = replace_dict[i]
        if (i == '$upstream') {
            i = upstream_domain
        } else if (i == '$custom_domain') {
            i = host_name
        }
 
        if (j == '$upstream') {
            j = upstream_domain
        } else if (j == '$custom_domain') {
            j = host_name
        }
 
        let re = new RegExp(i, 'g')
        text = text.replace(re, j);
    }
    return text;
}
 
async function device_status (user_agent_info) {
    var agents = ["Android", "iPhone", "SymbianOS", "Windows Phone", "iPad", "iPod"];
    var flag = true;
    for (var v = 0; v < agents.length; v++) {
        if (user_agent_info.indexOf(agents[v]) > 0) {
            flag = false;
            break;
        }
    }
    return flag;
}

After saving and deploying, your reverse proxy will take effect.

Custom Domain#

Unfortunately, the .workers.dev domain suffix in China is now polluted, so you need to bind your own domain in China to access it normally.
First, purchase a domain and then transfer its DNS service provider to Cloudflare. Then, go to the Workers management page we just created, click on Triggers -> Custom Domain -> Add Custom Domain, and enter the domain you want to bind.

Testing#

When using it, replace the original cdn.jsdelivr.net domain with your own Worker or the Worker provided by the blogger. For example:

https://cdn.jsdelivr.net/gh/BarryYangi/ObsStaticData/obsidian/168069442100071iy8i.png

Replace cdn.jsdelivr.net with our Worker:

https://jsdelivr-cdn.2059484047.workers.dev/gh/BarryYangi/ObsStaticData/obsidian/168069442100071iy8i.png

This way, you can ensure a more stable use of the jsDelivr service.

Just enjoy it.

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.