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’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Explicitly disallow fetch() caching #102

Merged
merged 2 commits into from
Apr 6, 2023
Merged

Explicitly disallow fetch() caching #102

merged 2 commits into from
Apr 6, 2023

Conversation

mattrobenolt
Copy link
Member

@mattrobenolt mattrobenolt commented Apr 5, 2023

For the sake of our customers, I don't feel it's worth us fighting that "this implementation is wrong" with our customers in the middle.

If this hack were specific to an implementation of fetch, I'd feel differently, but given this is in the spec, and we're just being overly explicit, rather than relying on a "default" behavior, I'm more ok with it.

I still firmly disagree with implementations that are choosing to cache POST, especially also with an Authorization header, but there's only so much I/we can control.

See context: vercel/next.js#46856

Fixes: cloudflare/workers-sdk#101 cloudflare/workers-sdk#99

@mattrobenolt mattrobenolt requested review from dgraham and iheanyi April 5, 2023 23:07
@mattrobenolt mattrobenolt force-pushed the disallow-fetch-caching branch 2 times, most recently from 4cb7502 to d81e465 Compare April 5, 2023 23:20
For the sake of our customers, I don't feel it's worth us fighting that "this implementation is wrong" with our customers in the middle.

If this hack were specific to an implementation of fetch, I'd feel differently, but given this is in the spec, and we're just being overly explicit, rather than relying on a "default" behavior, I'm more ok with it.

I still firmly disagree with implementations that are choosing to cache POST, _especially_ also with an Authorization header, but there's only so much I/we can control.

See context: vercel/next.js#46856

Fixes: #101 #99
@mattrobenolt mattrobenolt force-pushed the disallow-fetch-caching branch from d81e465 to da8f41d Compare April 6, 2023 01:03
Copy link
Member

@dgraham dgraham left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

src/index.ts Outdated Show resolved Hide resolved
@dgraham dgraham enabled auto-merge April 6, 2023 16:29
@dgraham dgraham merged commit a493ee6 into main Apr 6, 2023
@dgraham dgraham deleted the disallow-fetch-caching branch April 6, 2023 16:30
@ryespresso
Copy link

FYI, this breaks cloudflare workers. Any thoughts on how to fix this?

The 'cache' field on 'RequestInitializerDict' is not implemented.

@mattrobenolt
Copy link
Member Author

sigh, we can just revert it. I'm not sure how we can make everything happy, and this seemed like a backwards compatible change since this field is in the fetch spec. I'm guessing the extra field can't just be ignored because of TypeScript being too strict?

As a TypeScript noob, can we just have an arbitrary dict here? Since in most things, this would be ignored as extraneous.

@mattrobenolt
Copy link
Member Author

I don't think there's much we can do other than maybe open an issue over here? https://github.com/cloudflare/workers-sdk Beyond us reverting.

@iheanyi
Copy link
Member

iheanyi commented Apr 6, 2023

@ryeshrimp Yikes, sorry for breaking your application. To move forward, you have two options.

  1. You can pin the previous version of 1.6.0 to your package.json since this is the last-known good version of the package.

  2. I'm not sure if this will work within Cloudflare, but could you use a custom package like undici and use the fetch from that in your application? See the example below.

import { connect } from '@planetscale/database'
import { fetch } from 'undici'

const config = {
  fetch,
  host: '<host>',
  username: '<user>',
  password: '<password>'
}

const conn = connect(config)
const results = await conn.execute('select 1 from dual')
console.log(results)

@dgraham
Copy link
Member

dgraham commented Apr 6, 2023

@ryespresso
Copy link

ryespresso commented Apr 7, 2023

Thanks for making the bug report @dgraham. And thanks for the options @iheanyi. Happily using 1.6 for now. We'll see how cloudflare responds. Will try option 2 in a bit

@sjc5
Copy link

sjc5 commented Apr 9, 2023

FYI, this breaks cloudflare workers. Any thoughts on how to fix this?

The 'cache' field on 'RequestInitializerDict' is not implemented.

+1 on noticing the breaking, and +1 on pinning to 1.6.0 fixing it. Glad to see I'm not alone.

@chocolatkey
Copy link

chocolatkey commented Apr 9, 2023

If you want to fix cloudflare workers + 1.7.0, override the fetch option in the config:

fetch: (url: string, init: RequestInit<RequestInitCfProperties>) => {
    delete (init as any)["cache"]; // Remove cache header
    return fetch(url, init);
}

@rjvim
Copy link

rjvim commented Apr 14, 2023

@chocolatkey Pretty new to CF Workers, so not sure how to use the above solution.

The following is code is init'ing a new CF Worker project which uses fetch.

export default {
  async fetch(
    request: Request,
    env: Env,
    ctx: ExecutionContext
  ): Promise<Response> {
    return await router.handle(request);
  },
};

How can I override the fetch in this scenario? Any help please?

@chocolatkey
Copy link

chocolatkey commented Apr 14, 2023

@rjvim I guess I wasn't specific enough in my example, the fetch property is part of the config you can send to the planetscale connect function. For example:

import { connect } from '@planetscale/database'

const config = {
  host: 'xxx',
  username: 'xxx',
  password: 'xxx',
  fetch: (url: string, init: RequestInit<RequestInitCfProperties>) => {
    delete (init as any)["cache"]; // Remove cache header
    return fetch(url, init);
  }
}

const conn = connect(config)

P.S. do this outside the request handling function, it will get reused between requests to the worker

@@ -265,7 +266,8 @@ async function postJSON<T>(config: Config, url: string | URL, body = {}): Promis
'Content-Type': 'application/json',
'User-Agent': `database-js/${Version}`,
Authorization: `Basic ${auth}`
}
},
cache: 'no-store'
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This broke all Cloudflare deployments 😅

cc @dgraham

image

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@a-eid
Copy link

a-eid commented Jun 3, 2023

@iheanyi undici does not seem to work with cloudflare workers, reverting to 1.6.0 also produces the same error.

@rishavs
Copy link

rishavs commented Jun 26, 2023

@rjvim I guess I wasn't specific enough in my example, the fetch property is part of the config you can send to the planetscale connect function. For example:

import { connect } from '@planetscale/database'

const config = {
  host: 'xxx',
  username: 'xxx',
  password: 'xxx',
  fetch: (url: string, init: RequestInit<RequestInitCfProperties>) => {
    delete (init as any)["cache"]; // Remove cache header
    return fetch(url, init);
  }
}

const conn = connect(config)

P.S. do this outside the request handling function, it will get reused between requests to the worker

Thanks @chocolatkey . For those looking for a solution, I can confirm this works. Also, as its just a couple of lines of change, reverting this - once workers fix their bugs, will be easy.

@ian-speckart
Copy link

@rjvim I guess I wasn't specific enough in my example, the fetch property is part of the config you can send to the planetscale connect function. For example:

import { connect } from '@planetscale/database'

const config = {
  host: 'xxx',
  username: 'xxx',
  password: 'xxx',
  fetch: (url: string, init: RequestInit<RequestInitCfProperties>) => {
    delete (init as any)["cache"]; // Remove cache header
    return fetch(url, init);
  }
}

const conn = connect(config)

P.S. do this outside the request handling function, it will get reused between requests to the worker

I confirm that the issue persists and that the solution works.

"P.S. do this outside the request handling function, it will get reused between requests to the worker"

@rjvim Is that something we should be doing, though?
I'm asking because the username and password are inside the env object, which is accessible inside the request handling function.
The only way to create the connection outside is to hardcode the credentials in the worker, without using environment variables.

Also, Planetscale said that their serverless driver uses a connection factory that provides fresh connections (I'm using that with your solution): https://github.com/planetscale/database-js#connection-factory

@mateusedua
Copy link

mateusedua commented Sep 19, 2023

Just like chocolatkey mentioned above, this works perfectly.

const config = {
    host: "",
    username: "",
    password: "",
    fetch: (url, init) => {
        delete (init)["cache"];
        return fetch(url, init);
    }
}

export default config

moka-ayumu added a commit to moka-station/frontend that referenced this pull request Nov 8, 2023
moka-ayumu added a commit to moka-station/frontend that referenced this pull request Nov 8, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

implement --polyfill-node / config.polyfill_node