Caching mobile and Desktop separately

I’m new to Cloudflare workers, but I am using small script to control the caching of my site, based on the presence of cookies or not. The worker is working correctly, but I’m having a little trouble making it cache differently based on mobile content or not—basically, my site has a different theme for mobile than it does for desktop.

If a page is cached on desktop, however, it’s being shown to mobile viewers instead of the mobile version. Does anyone have any tips on how to differentiate the cache based on the user agent? I’ve tried to implement this, but my knowledge of workers is next to nothing, and I can’t get it to work. Myt site also sends the mf_useformat cookie if using the mobile version. Here’s my attempt to get it to cache differerently based on user-agent:

addEventListener('fetch', event => {
    event.respondWith(handleRequest(event.request));
});

const BYPASS_COOKIES = [
    'betacentralauth_Session',
    'betacentralauth_User'
];

const BYPASS_NAMESPACES = ["Special", "Module", "Especial"];

async function handleRequest(request) {
    if (request.method === "POST") {
        return fetch(request);
    }
    
    let url = new URL(request.url);
    let isMobile = false;

    const accept = request.headers.get('accept') || '';
    let cookie = request.headers.get('cookie') || '';
    const ua = request.headers.get('user-agent') || '';

    const mobileUA = /mobi|android|ipod|kindle|webos/i.test(ua);

    if ( mobileUA ) {
        isMobile = true;
    }

    let bypassCache = false;

    for (const cookieName of BYPASS_COOKIES) {
        if (cookie.includes(cookieName)) {
            bypassCache = true;
            break;
        }
    }

    for (const namespace of BYPASS_NAMESPACES) {
        if (url.pathname.includes(`/wiki/${namespace}:`)) {
            bypassCache = true;
            break;
        }
    }

    if (bypassCache) {
        const response = await fetch(request);
        const responseHeaders = new Headers(response.headers);
        responseHeaders.set('CF-Cache-Status', 'BYPASS');
        return new Response(response.body, {
            status: response.status,
            statusText: response.statusText,
            headers: responseHeaders,
            redirect: "manual"
        });
    }
    
    const modifiedHeaders = new Headers(request.headers);
    if (isMobile) {
        modifiedHeaders.set('User-Agent', `${request.headers.get('User-Agent')} (MobileView)`);
    }

    // Conditional properties for new Request
    const requestProps = {
        method: request.method,
        headers: modifiedHeaders,
        cf: { cacheEverything: true }
    };

    if (request.method !== "GET" && request.method !== "HEAD") {
        requestProps.body = request.body;
    }

    request = new Request(request.url, requestProps);

    const originalResponse = await fetch(request);
    const responseHeaders = new Headers(originalResponse.headers);

    responseHeaders.set('Cache-Control', 'public, must-revalidate, max-age=3600, stale-while-revalidate=90');
    responseHeaders.append('Vary', 'User-Agent');

    return new Response(originalResponse.body, {
        status: originalResponse.status,
        statusText: originalResponse.statusText,
        headers: responseHeaders
    });
}

I’m right there with you. If this is all about learning Workers, someone may have an answer for this, or you can check on the Cloudflare Discord server:

If this is just about Caching, you might have better luck with Cache Rules. It can trigger based on cookies and paths, and include cache by device type as part of the cache key:

1 Like