cli icon indicating copy to clipboard operation
cli copied to clipboard

[Bug]: Proxy always pointing to port of last web regardless of role

Open dangreaves opened this issue 1 year ago • 1 comments

Please confirm that you have:

  • [X] Searched existing issues to see if your issue is a duplicate. (If you’ve found a duplicate issue, feel free to add additional information in a comment on it.)
  • [X] Reproduced the issue in the latest CLI version.

In which of these areas are you experiencing a problem?

App

Expected behavior

For an app with two processes, a frontend role and a background role, the Cloudflare proxy should always point to the frontend process, not the background process, regardless of the order in which the webs are discovered.

Actual behavior

The port which the Cloudflare proxy is pointed to is dependant on the order that the "webs" are defined either via the web_directories config, or the automatic directory scanning.

The Cloudflare proxy is always pointed at the port of the "last" web the CLI finds, regardless of what the roles config is set for that service.

If the "last" web does not expose an HTTP server, the CLI will fail with a Error forwarding web request: AggregateError error when it tries to connect Cloudflare.

Verbose output

% pnpm run dev

> root@ dev /Users/dangreaves/projects/wrong-port-repro
> shopify app dev

╭─ info ───────────────────────────────────────────────────╮
│                                                          │
│  Using shopify.app.toml:                                 │
│                                                          │
│    • Org:             Bared Footwear                     │
│    • App:             wrong-port-repro                   │
│    • Dev store:                                          │
│      bared-footwear-checkout-preview.myshopify.com       │
│    • Update URLs:     Yes                                │
│                                                          │
│   You can pass `--reset` to your command to reset your   │
│  app configuration.                                      │
│                                                          │
╰──────────────────────────────────────────────────────────╯


13:56:37 │      graphiql │ GraphiQL server started on port
3457
13:56:37 │    background │ background process started
13:56:37 │           web │ web process started

────────────────────────────────────────────────────────────
Error forwarding web request: AggregateError

────────────────────────────────────────────────────────────

› Press d │ toggle development store preview: ✔ on
› Press g │ open GraphiQL (Admin API) in your browser
› Press p │ preview in your browser
› Press q │ quit

Preview URL: https://bared-footwear-checkout-preview.myshopi
fy.com/admin/oauth/redirect_from_cli?client_id=864ad7734402d
60cea02b3de429ccc5d
GraphiQL URL: http://localhost:3457/graphiql

Reproduction steps

I have created a minimal reproduction (https://github.com/dangreaves/shopify-wrong-port-repro). This repo contains two very simple services or "webs" as Shopify calls them.

  1. The web service exposes an HTTP server which simply returns "Hello world" for all requests. It has the roles ["frontend", "backend"].
  2. The background service is a node script which just runs forever. It has the roles ["background"]. It does not expose an HTTP server.
  3. The shopify.app.toml in the root defines the web_directories option as [ "web", "background" ].

Note that the background web is listed last. This might happen without the web_directories option if you rely on the default directory scanning, meaning this bug is hard to find.

  1. Clone the repo
  2. Run pnpm install
  3. Run pnpm run dev --reset and create a new app
  4. Open the dev store and see the error Error forwarding web request: AggregateError when Cloudflare tries to route the request to the background service
  5. Exit the process
  6. Swap the web_directories so that it now reads [ "background", "web" ]
  7. Run pnpm run dev again
  8. See that the dev store now loads the "Hello world" response correctly, because Cloudflare is correctly routing to the web service, not the background service

I have tracked the error down to the setupWebProcesses method in the app CLI.

This method receives an array of all the webs, no matter what their roles are. However, it then assigns a static type of "web" to all of them, losing their actual roles.

The output from this method is then passed through lots of other methods until it eventually reaches the createProcessDefinitionsForProxies method, which is responsible for generating the "default" rule. This rule looks like http://localhost:3001 and is what is supposed to point Cloudflare at the frontend service. However in reality because of the above, this default rule always just points to the "last" service resolved by the CLI.

Finally, we get all the way down to the actual error thrown in the getProxyServerRequestListener method, because it's trying to route Cloudflare to a service which does not actually expose a port.

Other reports of this issue

  • https://stackoverflow.com/questions/77922555/error-with-background-process-shopify-web-toml
  • https://community.shopify.com/c/technical-q-a/issues-with-shopify-web-toml-background-role/m-p/2422009

Operating System

Mac OS Sonoma

Shopify CLI version (check your project's package.json if you're not sure)

3.65.3

Shell

No response

Node version (run node -v if you're not sure)

v20.11.0

What language and version are you using in your application?

No response

dangreaves avatar Aug 11 '24 04:08 dangreaves

Hi @dangreaves, thank you for submitting this beautifully crafted issue! The minimal reproduction made this super easy to understand and start investigating. I hope to follow up soon with a fix.

amcaplan avatar Aug 15 '24 21:08 amcaplan