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

fix(live): detect CORS errors #910

Merged
merged 1 commit into from
Nov 6, 2024
Merged

fix(live): detect CORS errors #910

merged 1 commit into from
Nov 6, 2024

Conversation

stipsan
Copy link
Member

@stipsan stipsan commented Nov 5, 2024

Detects CORS errors and throws a custom error:

CorsOriginError: The current origin is not allowed to connect to the Live Content API. 
Add it here: https://sanity.io/manage/project/hiomol4a/api?cors=add&origin=https%3A%2F%2Fexample.com

Go to https://example.com and run this snippet in your console to see the error for yourself:

const {createClient} = await import('https://esm.sh/@sanity/client@canary')

const client = createClient({
    projectId: 'hiomol4a',
    dataset: 'fashion-show',
    useCdn: true,
    apiVersion: 'X'
})

client.live.events().subscribe({next: (event) => console.log(event), error: err => console.error(err)})

Userland can use the CorsOriginError export to handle CORS differently than other errors:

import {CorsOriginError, createClient} from '@sanity/client'

const client = createClient({
  // ...
})

client.live.events().subscribe({
  next: (event) => {
    // ...
  },
  error: (err) => {
    if(err instanceof CorsOriginError) {
      toast.warn(err.message)
    } else {
      toast.error(err)
    }
  }
})

Copy link

New dependencies detected. Learn more about Socket for GitHub ↗︎

Package New capabilities Transitives Size Publisher
npm/msw@2.6.0 environment, filesystem, shell +56 10.1 MB kettanaito

View full report↗︎

@@ -24,6 +27,29 @@ const testSse = async (onRequest: OnRequest, options: ClientConfig = {}) => {
describe.skipIf(typeof EdgeRuntime === 'string' || typeof document !== 'undefined')(
'.live.events()',
() => {
const server = setupServer(
Copy link
Member Author

Choose a reason for hiding this comment

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

As explained further down, nock isn't able to intercept global.fetch, so we use msw for this.
We might be able to use msw instead of nock, but it feels out of scope for this PR.

Comment on lines +247 to +253
global.fetch = async (info, init) => {
const response = await restoreFetch(info, init)
if (!response.headers.has('access-control-allow-origin')) {
throw new Error('CORS preflight request failed')
}
return response
}
Copy link
Member Author

@stipsan stipsan Nov 5, 2024

Choose a reason for hiding this comment

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

global.fetch is based on undici in node, which doesn't actually implement CORS, so we have to resort to some trickery to mimic the behaviour we want.

@stipsan stipsan disabled auto-merge November 6, 2024 09:00
@stipsan stipsan merged commit 553cb38 into main Nov 6, 2024
15 checks passed
@stipsan stipsan deleted the handle-cors-on-live branch November 6, 2024 09:00
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.

1 participant