Skip to content

Commit

Permalink
fix: improve the worker integrity warning (#2091)
Browse files Browse the repository at this point in the history
  • Loading branch information
kettanaito committed Mar 16, 2024
1 parent a0f8021 commit e749355
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 46 deletions.
5 changes: 4 additions & 1 deletion src/browser/setupWorker/glossary.ts
Expand Up @@ -54,7 +54,10 @@ export type ServiceWorkerIncomingResponse = Pick<
*/
export interface ServiceWorkerIncomingEventsMap {
MOCKING_ENABLED: boolean
INTEGRITY_CHECK_RESPONSE: string
INTEGRITY_CHECK_RESPONSE: {
packageVersion: string
checksum: string
}
KEEPALIVE_RESPONSE: never
REQUEST: ServiceWorkerIncomingRequest
RESPONSE: ServiceWorkerIncomingResponse
Expand Down
28 changes: 9 additions & 19 deletions src/browser/setupWorker/start/createStartHandler.ts
@@ -1,10 +1,9 @@
import { until } from '@open-draft/until'
import { devUtils } from '~/core/utils/internal/devUtils'
import { getWorkerInstance } from './utils/getWorkerInstance'
import { enableMocking } from './utils/enableMocking'
import { SetupWorkerInternalContext, StartHandler } from '../glossary'
import { createRequestListener } from './createRequestListener'
import { requestIntegrityCheck } from '../../utils/requestIntegrityCheck'
import { checkWorkerIntegrity } from '../../utils/checkWorkerIntegrity'
import { createResponseListener } from './createResponseListener'
import { validateWorkerScope } from './utils/validateWorkerScope'

Expand Down Expand Up @@ -74,23 +73,14 @@ Please consider using a custom "serviceWorker.url" option to point to the actual
window.clearInterval(context.keepAliveInterval)
})

// Check if the active Service Worker is the latest published one
const integrityCheckResult = await until(() =>
requestIntegrityCheck(context, worker),
)

if (integrityCheckResult.error) {
devUtils.warn(`\
Detected outdated Service Worker: ${integrityCheckResult.error.message}
The mocking is still enabled, but it's highly recommended that you update your Service Worker by running:
$ npx msw init <PUBLIC_DIR>
This is necessary to ensure that the Service Worker is in sync with the library to guarantee its stability.
If this message still persists after updating, please report an issue: https://github.com/open-draft/msw/issues\
`)
}
// Check if the active Service Worker has been generated
// by the currently installed version of MSW.
await checkWorkerIntegrity(context).catch((error) => {
devUtils.error(
'Error while checking the worker script integrity. Please report this on GitHub (https://github.com/mswjs/msw/issues), including the original error below.',
)
console.error(error)
})

context.keepAliveInterval = window.setInterval(
() => context.workerChannel.send('KEEPALIVE_REQUEST'),
Expand Down
34 changes: 34 additions & 0 deletions src/browser/utils/checkWorkerIntegrity.ts
@@ -0,0 +1,34 @@
import { devUtils } from '~/core/utils/internal/devUtils'
import type { SetupWorkerInternalContext } from '../setupWorker/glossary'

/**
* Check whether the registered Service Worker has been
* generated by the installed version of the library.
* Prints a warning message if the worker scripts mismatch.
*/
export async function checkWorkerIntegrity(
context: SetupWorkerInternalContext,
): Promise<void> {
// Request the integrity checksum from the registered worker.
context.workerChannel.send('INTEGRITY_CHECK_REQUEST')

const { payload } = await context.events.once('INTEGRITY_CHECK_RESPONSE')

// Compare the response from the Service Worker and the
// global variable set during the build.

// The integrity is validated based on the worker script's checksum
// that's derived from its minified content during the build.
// The "SERVICE_WORKER_CHECKSUM" global variable is injected by the build.
if (payload.checksum !== SERVICE_WORKER_CHECKSUM) {
devUtils.warn(
`The currently registered Service Worker has been generated by a different version of MSW (${payload.packageVersion}) and may not be fully compatible with the installed version.
It's recommended you update your worker script by running this command:
\u2022 npx msw init <PUBLIC_DIR>
You can also automate this process and make the worker script update automatically upon the library installations. Read more: https://mswjs.io/docs/cli/init.`,
)
}
}
23 changes: 0 additions & 23 deletions src/browser/utils/requestIntegrityCheck.ts

This file was deleted.

8 changes: 6 additions & 2 deletions src/mockServiceWorker.js
Expand Up @@ -2,12 +2,13 @@
/* tslint:disable */

/**
* Mock Service Worker (<PACKAGE_VERSION>).
* Mock Service Worker.
* @see https://github.com/mswjs/msw
* - Please do NOT modify this file.
* - Please do NOT serve this file on production.
*/

const PACKAGE_VERSION = '<PACKAGE_VERSION>'
const INTEGRITY_CHECKSUM = '<INTEGRITY_CHECKSUM>'
const IS_MOCKED_RESPONSE = Symbol('isMockedResponse')
const activeClientIds = new Set()
Expand Down Expand Up @@ -48,7 +49,10 @@ self.addEventListener('message', async function (event) {
case 'INTEGRITY_CHECK_REQUEST': {
sendToClient(client, {
type: 'INTEGRITY_CHECK_RESPONSE',
payload: INTEGRITY_CHECKSUM,
payload: {
packageVersion: PACKAGE_VERSION,
checksum: INTEGRITY_CHECKSUM,
},
})
break
}
Expand Down
9 changes: 8 additions & 1 deletion test/browser/msw-api/integrity-check.test.ts
Expand Up @@ -2,6 +2,7 @@ import * as fs from 'fs'
import * as path from 'path'
import { test, expect } from '../playwright.extend'
import copyServiceWorker from '../../../config/copyServiceWorker'
import { version } from '../../../package.json'

const { SERVICE_WORKER_SOURCE_PATH } = require('../../../config/constants')

Expand Down Expand Up @@ -67,7 +68,13 @@ test('errors when activating the worker with an outdated integrity', async ({
// Produces a meaningful error in the browser's console.
expect(consoleSpy.get('warning')).toEqual(
expect.arrayContaining([
expect.stringContaining('[MSW] Detected outdated Service Worker'),
`[MSW] The currently registered Service Worker has been generated by a different version of MSW (${version}) and may not be fully compatible with the installed version.
It's recommended you update your worker script by running this command:
\u2022 npx msw init <PUBLIC_DIR>
You can also automate this process and make the worker script update automatically upon the library installations. Read more: https://mswjs.io/docs/cli/init.`,
]),
)
})
Expand Down

0 comments on commit e749355

Please sign in to comment.