Accessing http url via cron returns error 531

The problem: in fetch() it works, in scheduled() does not.
Locally, this works too (http://localhost:8787/__scheduled?cron=*+*+*+*+*)

Testing: curl http://scheduled-bug.xray.app:8050/rpc/tip
Domain scheduled-bug.xray.app is unproxied in the CF DNS for accessing custom ports.

	async scheduled(event: ScheduledEvent, env: Env, ctx: ExecutionContext): Promise<void> {
		const delayedProcessing = async () => {
			if (event.cron === "* * * * *") {
				
				const response = await fetch("http://scheduled-bug.xray.app:8050/rpc/tip")
				console.log(response.status, await response.text())

			}
		}
		ctx.waitUntil(delayedProcessing())
	},

Logs from the deployed worker:

{
  "outcome": "ok",
  "scriptName": "xxx",
  "diagnosticsChannelEvents": [],
  "exceptions": [],
  "logs": [
    {
      "message": [
        521,
        "error code: 521"
      ],
      "level": "log",
      "timestamp": 1705156844153
    }
  ],
  "eventTimestamp": 1705156843859,
  "event": {
    "cron": "* * * * *",
    "scheduledTime": 1705156843000
  },
  "id": 21
}

Fetching custom ports isn’t going to work in a scheduled handler since it’ll never be a same-zone request, it isn’t attributed to a domain like the fetch handler is.

Okay, but why is proxied https domain is working as expected? I think this is inconsistent behavior since it works in fetch().

I think this is some problem that needs to be solved, as it leads to the problem of different query fetch() behavior. In local and production deployment.

This creates distrust in the platform, as there are flaws that can lead to problems hosting highly loaded applications.

I’m just trying to build an application to monitor the health of a service and write to KV storage. How can it be done in this situation?

The issue here is with the use of custom ports, and how Workers handles those.

Unless it’s a same-zone request, they will be sent to the default port for that scheme (i.e 80 for HTTP) and your origin isn’t listening (or accepting) connections on that port.

2 Likes

Ok, but how can I make a sub-domain to be in the same zone?

Proxied? “A” name? CNAME? But it doesn’t work as indicated in your picture

As I understood subrequests in fetch() and scheduled() should work the same way, but in scheduled() the custom port doesn’t work.

I think there is some problem here…

export default {

	// WORKS
	// Main fetch handler
	async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {

		const response = await fetch("http://scheduled-bug.xray.app:8050/rpc/tip")
		return new Response(response.body)

	},

    // NOT WORKING
	// Crons handler
	async scheduled(event: ScheduledEvent, env: Env, ctx: ExecutionContext): Promise<void> {
		const delayedProcessing = async () => {
			if (event.cron === "* * * * *") {

				const response = await fetch("http://scheduled-bug.xray.app:8050/rpc/tip")
				console.log(response.status, await response.text())


			}
		}
		ctx.waitUntil(delayedProcessing())
	},
}

What’s the URL of the Worker?

Fetching custom ports isn’t going to work in a scheduled handler since it’ll never be a same-zone request, it isn’t attributed to a domain like the fetch handler is.

To solve this problem, we added HAproxy on port 80, so that it would use the “HostResolver” header to roam to the correct ports.

Thanks for your help