-
Notifications
You must be signed in to change notification settings - Fork 253
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
add sendPayloadChecksums config option and implement Bugsnag-Integrity header #2221
base: next
Are you sure you want to change the base?
Changes from 1 commit
14dca7e
b2d4819
4044c31
ebad38a
af9731d
c81a572
7177ddf
9de0065
97f8402
a6d6e67
c06add0
ff5cd1b
503eae3
b1e0b1f
c415a67
a801c57
6409517
c8f48cc
277bdde
cfd61b2
79cac2d
2db23b7
59ec656
983fcb4
5b3788c
acda730
283b77d
1eec649
9d7c759
b46beae
190e226
b68c890
d38cc52
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
const { TextDecoder, TextEncoder } = require('node:util') | ||
const crypto = require('crypto') | ||
|
||
const JSDOMEnvironment = require('jest-environment-jsdom') | ||
|
||
class FixJSDOMEnvironment extends JSDOMEnvironment { | ||
constructor (...args) { | ||
super(...args) | ||
|
||
this.global.TextEncoder = TextEncoder | ||
this.global.TextDecoder = TextDecoder | ||
this.global.crypto = { | ||
subtle: crypto.webcrypto.subtle | ||
} | ||
} | ||
} | ||
|
||
module.exports = FixJSDOMEnvironment |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,37 @@ | ||
import payload from '@bugsnag/core/lib/json-payload' | ||
|
||
const delivery = (client, fetch = global.fetch) => ({ | ||
async function addIntegrityHeader (windowOrWorkerGlobalScope, requestBody, headers) { | ||
if (windowOrWorkerGlobalScope.isSecureContext && windowOrWorkerGlobalScope.crypto && windowOrWorkerGlobalScope.crypto.subtle && windowOrWorkerGlobalScope.crypto.subtle.digest && typeof TextEncoder === 'function') { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
const msgUint8 = new TextEncoder().encode(requestBody) | ||
const hashBuffer = await windowOrWorkerGlobalScope.crypto.subtle.digest('SHA-1', msgUint8) | ||
const hashArray = Array.from(new Uint8Array(hashBuffer)) | ||
const hashHex = hashArray | ||
.map((b) => b.toString(16).padStart(2, '0')) | ||
.join('') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
||
headers['Bugsnag-Integrity'] = 'sha1 ' + hashHex | ||
} | ||
} | ||
|
||
const delivery = (client, fetch = global.fetch, windowOrWorkerGlobalScope = window) => ({ | ||
sendEvent: (event, cb = () => {}) => { | ||
const url = client._config.endpoints.notify | ||
|
||
fetch(url, { | ||
method: 'POST', | ||
headers: { | ||
'Content-Type': 'application/json', | ||
'Bugsnag-Api-Key': event.apiKey || client._config.apiKey, | ||
'Bugsnag-Payload-Version': '4', | ||
'Bugsnag-Sent-At': (new Date()).toISOString() | ||
}, | ||
body: payload.event(event, client._config.redactedKeys) | ||
}).then(() => { | ||
const body = payload.event(event, client._config.redactedKeys) | ||
const headers = { | ||
'Content-Type': 'application/json', | ||
'Bugsnag-Api-Key': event.apiKey || client._config.apiKey, | ||
'Bugsnag-Payload-Version': '4', | ||
'Bugsnag-Sent-At': (new Date()).toISOString() | ||
} | ||
|
||
addIntegrityHeader(windowOrWorkerGlobalScope, body, headers).then(() => | ||
fetch(url, { | ||
method: 'POST', | ||
headers, | ||
body | ||
}) | ||
).then(() => { | ||
cb(null) | ||
}).catch(err => { | ||
client._logger.error(err) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -36,7 +36,7 @@ export const Bugsnag = { | |
// configure a client with user supplied options | ||
const bugsnag = new Client(opts, schema, internalPlugins, { name, version, url }) | ||
|
||
bugsnag._setDelivery(delivery) | ||
bugsnag._setDelivery(client => delivery(client, undefined, self)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same way the global |
||
|
||
bugsnag._logger.debug('Loaded!') | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
More info: https://mswjs.io/docs/migrations/1.x-to-2.x/#requestresponsetextencoder-is-not-defined-jest
We could also use https://github.com/mswjs/jest-fixed-jsdom but would still need to manually add the crypto APIs
I think this is fairly simple and clear
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For future reference, when we come to upgrade jest, it will need rewriting like this:
This is because
JSDOMEnvironment
is an ES6 class but we transpile classes in our code down to es5. This is how I managed to get it to work having an es5 class extend from an es6 class