Fetch url from Shopify store returns 403 Forbidden

I have the simplest worker on my domain, doing fetch() to the Shopify store.

Request is working in the preview (“wrangler preview” or “wrangler dev”), but when published to my zone I am getting 403 Forbidden as response from Shopify/CloudFlare

< HTTP/2 403 
< date: Fri, 01 May 2020 21:40:03 GMT
< content-type: text/html
< set-cookie: __cfduid=d982725a03a8d3eda83c93bc994950b5e1588369203; expires=Sun, 31-May-20 21:40:03 GMT; path=/; domain=.devbase.xyz; HttpOnly; SameSite=Lax
< cf-ray: 58cca8a24a97004a-LHR
< cf-cache-status: DYNAMIC
< cf-request-id: 0273c7b96b0000004a563ae200000001
< expect-ct: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
< server: cloudflare
< 
<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>cloudflare</center>
</body>
</html>
  1. Why is fetch() working in “wrangler dev” and “wrangler preview” but not when published?

  2. Is it related to “orange to orange” problem and somehow related to CloudFlare - Shopify setup?

  3. Is there some workaround or option that can be added to cf object in the fetch call?

Could be that Shopify is also on Cloudflare, which should work when it’s on a different zone.

So if you have the worker on worker.mydomain.com making requests to mydomain.com it won’t work.

I’d test running the worker from the workers.dev domain to see if that’s the issue.

Worker code:

async function handleRequest(event) {
    return await fetch('https://hauslondon.com/', {
        headers: {
            'User-Agent': event.request.headers.get('user-agent')
        }
    })
}

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

Domain hauslondon.com is not in my zone, it is random Shopify store I found in “Best Shopify stores” Google search. I see same behavior with any other Shopify store with custom domain. Fetching from stores without custom Shopify domain (on myshopify.com) works fine.

Worker works in “wrangler preview” and “wrangler dev” and when deployed to “workers.dev”.

Worker returns 403 Forbidden response from Shopify/Cloudflare when deployed to my zone, that is different top level domain than hauslondon.com.

You’re trying to pass through the user agent of the browser of the Worker visitor?

In Dev mode this would be null if I’m not mistaken, some values are not allowed to be modified and I think user agent is one of those. Edit: I was thinking of mutating, which is not the same here.

Fetch behavior is the same without UA header too. Without UA Shopify shows “friendly bot” page but serving response from the origin. Again, this works in preview and on workers.dev, but not when published to my zone, where I get 403 Frobidden response and not page from Shopify.

It should not relate to UA header (eg. setting how fetch should be seen on the origin like sending “app name” in the UA) and when checking against my own origin, I see that UA header is forwarded. Origin server receives:

Name Value
Accept-Encoding gzip
Cdn-Loop cloudflare; subreqs=1
Cf-Connecting-Ip 2a06:98c0:3600::103
Cf-Ew-Via 15
Cf-Ray 58d09160a6f03e30-PRG
Cf-Visitor {“scheme”:“https”}
Cf-Worker (either workers.dev subdomain or my domain)
User-Agent Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36
X-Forwarded-For 172.68.215.204
X-Forwarded-Proto httpshtt

Hm, I think it might be an SSL issue since you’re essentially proxying the entire domain.

You could try setting SSL to Full in the settings.

Forbidden 403 response seems to be only about fetching from Shopify stores on custom domains (that are not on myshopify.com). Fetching from others sites on CloudFlare either from my zone or from other zones from the Worker works fine.

Is there some special setup in CloudFlare - Shopify, or special action Shopify takes in order to block fetch requests from Workers published to non-Shopify zones?

Seems a bit far-fetched to block all Worker like this, did you try the SSL settings?

You are right, chaning from Flexible to Full is solving the problem

1 Like