Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

馃悰 BUG: wrangler dev throws if finding a non-iterable middleware export #5420

Closed
kwhitley opened this issue Mar 27, 2024 · 6 comments 路 Fixed by #5703
Closed

馃悰 BUG: wrangler dev throws if finding a non-iterable middleware export #5420

kwhitley opened this issue Mar 27, 2024 · 6 comments 路 Fixed by #5703
Labels
bug Something that isn't working

Comments

@kwhitley
Copy link

Which Cloudflare product(s) does this pertain to?

Wrangler core

What version(s) of the tool(s) are you using?

3.39.0 [Wrangler]

What version of Node are you using?

20.10.0

What operating system and version are you using?

Mac Ventura 13

Describe the Bug

Observed Behavior

wrangler dev throws if it finds an export named "middleware", but cannot iterate it.

Expected Behavior

If requesting a hidden exported property (middleware) and iterating over it, there should at least be checks to verify if the item is iterable before attempting to iterate.

TLDR; It should not throw.

Error Reproduction

Create a simple file with the following content, then launch it using wrangler dev:

export default {
  middleware: () => {}, // wrangler dev attempts to iterate this, throwing
}

The same script runs fine in production/deployed but cannot be run locally.

Why this matters

itty-router routers have a Proxy trap on the prototype chain. If we export our router directly, a request from the runtime to "middleware" returns a function (via that trap). This throws when wrangler tries to iterate it without checking to see if it's iterable/an array.

import { Router } from 'itty-router'

export default Router() // this doesn't work locally

export default { ...Router() } // but this does, as the prototype chain is stripped

Please provide a link to a minimal reproduction

No response

Please provide any relevant error logs

image

Fun Fact

We used a Proxy to identify that the property "middleware" was being requested from the export (the logs showed nothing).

@kwhitley kwhitley added the bug Something that isn't working label Mar 27, 2024
@kwhitley
Copy link
Author

kwhitley commented Apr 5, 2024

Any update on this? I'm more than happy to contribute if possible, so we can remove disclaimers like this
https://itty.dev/itty-router/guides/cloudflare-workers

@penalosa
Copy link
Contributor

@kwhitley Just to check, does itty-router have a middleware property?

@kwhitley
Copy link
Author

It does not, but it has a proxy prototype that will intercept a request to middleware and return a function. So to the outside, it looks like we do have that property... as a function.

A tiny safety check that confirms that middleware is iterable before iterating should work here though (because that check would fail if it's determined to be a function).

@penalosa
Copy link
Contributor

We can definitely add that check (as the linked PR does), but is there any reason itty-router returns a function for the middleware property? Ideally it should only return a function for the fetch property, and pass through to the underlying object otherwise

@kwhitley
Copy link
Author

kwhitley commented Apr 25, 2024

Itty allows (unknown) properties to be read off the underlying object as methods/route handlers, in order to maintain its tiny footprint and support virtually any current/future HTTP verb.

For instance, accessing router.post responds with a route handler (function) that will ultimately register on the POST http method. Likewise for any other attributes not defined on the underlying object itself, so router.middleware is simply interpreted as the user trying to create a route handler matching the MIDDLEWARE http method :)

@kwhitley
Copy link
Author

This is why our current wrangler dev workaround of export default { ...router } works, even though it looks pointless. It strips off the proxy prototype from the object, returning only the current tangible values, and none of the intercept behavior. A bit of random trivia there!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something that isn't working
Projects
Status: Done
Development

Successfully merging a pull request may close this issue.

2 participants