Requesting Worker from Pages on same domain

Hello everyone,

This is my first post here so if I am doing something wrong please let me know :slight_smile:.

I’ve had this problem for quite some time now, I’ve been able to work around it, but it doesn’t seem right to me, so I decided to ask here for any advice or possible solution.

Let me start by explaining my setup.

  • I have an Astro SSR page hosted on Cloudflare Pages with a custom domain - dashboard.mydomain.com.
  • I also have a worker that does all the heavy lifting, or rather the backend. This worker has the following route defined in wrangler.toml - route = { pattern = "dashboard.mydomain.com/api/*", zone_name = "mydomain.com" }

A first thought, which I already discussed on Discord:
Q: Why not use Astro Endpoints (API) for this?
A: Personal preference I guess. I just prefer to keep the frontend separate from the backend, so if I want to use a different framework in the future, it will be much less of a migration.

But back to the topic. After deploying both to Cloudflare, I monitored/tailed both deployments to see if a request was even sent to the worker. This is the output:


→ On the left is the worker, on the right is the page.

As you can see in the screenshot, the worker didn’t get the request, both were “accepted”/handled by the page.

Just for completeness, this is how I request the backend in the astro page (this code is executed on the server on every page load), which either failed or gave me a blank page.

let message = "Hello World";
try {
  const api = await fetch("https://dashboard.ruxiom.dev/api/v1/ping");
  message = await api.text();
} catch (error) {
  console.log(error);
  message = "Error or nothing found :(";
}

That was basically the end of the first day and I gave up.

JFYI: I also tried every combination of include and exclude in the _routes.json (which is generated by @astrojs/cloudflare but matches the documentation).

On the second day I wanted to see if I could use the Astro Endpoint API to “proxy” the request to the backend. I finally saw light at the end of the tunnel by doing the following:

export async function GET({ parameters }) {
  const backendRequest = await fetch(
    "https://dashboard.ruxiom.dev/api/" + params.request,
    {
      headers: {
        "CF-Access-Client-Id": "something.access",
        "CF-Access-Client-Secret":
          "xxx",
      },
    }
  );

  return backendRequest.clone();
}

I created a “catch-all” /api route/function in the page itself. At first it failed because I got an access denied error, so I had to create an additional service auth rule, which seemed odd to me (the sandbox environment is protected by zero trust). But with this setup I was finally able to request my worker from my page (I didn’t have to change the above code to request the backend).

After this finally worked, it raised some questions, especially about invocations. If I’m thinking correctly, this is how the “request loop” works.
Request to /ping.html → request to internal page API proxy /api → request to worker

In a perfect world / solution, I would not have to request this internal API proxy, because it just feels like a ■■■■ to maintain or explain to anyone. Mainly because every request I try to make to the external API is duplicated because it has to go through the page function first, which requests the correct backend.

Am I doing something wrong or should I something completely different.

I hope I have been able to summarise my problem and you understand what I am trying to achieve.

Any help would be greatly appreciated :slight_smile:

Thanks for reading (my first post) and have a nice day,
David

If I’m understanding correctly, you are trying to call the Worker from the server-side code in your Pages app?

You need to use Service Bindings:

After creating the Service Binding to your worker you call it the same way except that you use a fetch function on the binding variable.

env.BINDING.fetch("https://blabla" ... )

First of all thanks for the fast reply, and yes you are understanding correctly I try to request a worker from the server-side code of my Page.

I am aware of service bindings but unfortunately Astro does not support Service Bindings (yet :tm:) - Documentation

I could ask in the Cloudflare Community Discord if Service Bindings are somehow possible using the @astrojs/cloudflare adapter.

(I could obviously just put the backend under a different domain, but that would give me headaches with cors).

I’ll keep this topic open until I get an answer :slight_smile:

Tyyyy again,
David

Edit: 2024-03-04
The @astrojs/cloudflare adapter will have Service Bindings in the near future, so this is resolved by @i40west comment on using Service bindings. Thanks :slight_smile:

1 Like

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.