[Bug]: Proxy always pointing to port of last web regardless of role
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.
- The web service exposes an HTTP server which simply returns "Hello world" for all requests. It has the roles
["frontend", "backend"]. - The background service is a node script which just runs forever. It has the roles
["background"]. It does not expose an HTTP server. - The shopify.app.toml in the root defines the
web_directoriesoption 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.
- Clone the repo
- Run
pnpm install - Run
pnpm run dev --resetand create a new app - Open the dev store and see the error
Error forwarding web request: AggregateErrorwhen Cloudflare tries to route the request to thebackgroundservice - Exit the process
- Swap the
web_directoriesso that it now reads[ "background", "web" ] - Run
pnpm run devagain - See that the dev store now loads the "Hello world" response correctly, because Cloudflare is correctly routing to the
webservice, not thebackgroundservice
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
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.