-
Notifications
You must be signed in to change notification settings - Fork 67
feat: Detect and report AJAX payloads #1651
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
Merged
Merged
Changes from all commits
Commits
Show all changes
41 commits
Select commit
Hold shift + click to select a range
6c9cbb6
basic changes in place to capture payload metadata
metal-messiah edb175f
shelving for now
metal-messiah 15b440a
add tests
metal-messiah 2489823
fix tests
metal-messiah 3fe3d02
Merge branch 'main' into ajax-payloads-wrap
metal-messiah 665920a
clean up gql
metal-messiah 13e14ae
clean up
metal-messiah 503f107
use constant
metal-messiah fa71019
fix jest tests
metal-messiah b9a2f6e
add basics of truncation
metal-messiah 8407eb9
basics in place for truncation and size eval for non-ascii
metal-messiah 1c531fa
cleanup
metal-messiah faeee5d
handle truncation and unicode text
metal-messiah 3d83dab
resolve merge conflicts
metal-messiah fd64c2a
fix test
metal-messiah 10641ec
add jest tests
metal-messiah 2b6552c
focus on aggregate
metal-messiah 37a4959
remove unused warning
metal-messiah 80ff822
move file to correct directory
metal-messiah 6f34f59
move file to correct directory
metal-messiah a026085
fix test paths
metal-messiah b3ea2f5
expose as experiment
metal-messiah 3aa0a0d
add to params so that it shows up for old spa events
metal-messiah 4b812b9
fix bad ee reference
metal-messiah 0a02d7c
fix merge conflicts
metal-messiah 14dc037
support new experiment pattern
metal-messiah ba4ba42
merge with main
metal-messiah ee4e978
update tests to check eventFilter
metal-messiah 40f1be1
extend to include default rules
metal-messiah 6367049
PR comment - truncate after scrubbing
metal-messiah 7aec8a6
PR comment - test main AJAX methods
metal-messiah 2e1d5f5
PR comment - use endTime
metal-messiah 176fba1
PR comment - gate responseBody
metal-messiah 3004409
PR comment - requestBody from Request instance
metal-messiah e41772d
PR comment - handle gql batched errors
metal-messiah 75fe265
PR comment - elevate ajaxRequest.id to help prevent errant truncation
metal-messiah d5626ec
PR comment - ensure truncation logic applies to browser interaction too
metal-messiah 1103907
PR comment - standardize canCapturePayload
metal-messiah e9e33c4
PR comment - jsdoc
metal-messiah 706e1d1
fix tests
metal-messiah 7fd5bfd
remove duplicated file
metal-messiah File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -29,3 +29,4 @@ packages/browser-agent-core/cjs | |
| tests/assets/test-builds/**/* | ||
| tests/assets/scripts/**/* | ||
| /.lambdatest | ||
| bam.json | ||
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,135 @@ | ||
| /** | ||
| * Copyright 2020-2026 New Relic, Inc. All rights reserved. | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
| import { stringify } from '../util/stringify' | ||
| import { CAPTURE_PAYLOAD_SETTINGS } from '../../features/ajax/constants' | ||
|
|
||
| /** | ||
| * Determines whether payload data should be captured based on the capture mode setting, | ||
| * HTTP status code, and GraphQL error status. | ||
| * @param {string} captureMode - The capture mode setting ('off', 'all', or 'failures') | ||
| * @param {number} statusCode - The HTTP status code | ||
| * @param {boolean} hasGQLErrors - Whether the response contains GraphQL errors | ||
| * @returns {boolean} True if payload should be captured | ||
| */ | ||
| export function canCapturePayload (captureMode, statusCode, hasGQLErrors) { | ||
| if (captureMode === CAPTURE_PAYLOAD_SETTINGS.ALL) return true | ||
| if (!captureMode || captureMode === CAPTURE_PAYLOAD_SETTINGS.OFF) return false | ||
|
|
||
| // Default "failures" mode | ||
| return statusCode === 0 || statusCode >= 400 || hasGQLErrors === true | ||
| } | ||
|
|
||
| /** | ||
| * Parses a query string into an object of key-value pairs. | ||
| * @param {string} search a query string starting with "?" or without (ex. new URL(...).search) | ||
| * @returns {Object|undefined} Parsed query parameters as key-value pairs. Returns undefined if no valid parameters are found. | ||
| */ | ||
| export function parseQueryString (search) { | ||
| if (!search || search.length === 0) return | ||
|
|
||
| const queryParams = {} | ||
| try { | ||
| const searchParams = new URLSearchParams(search) | ||
| searchParams.forEach(function (value, key) { | ||
| queryParams[key] = value | ||
| }) | ||
| } catch (e) { | ||
| // Fallback for environments without URLSearchParams | ||
| } | ||
|
|
||
| return queryParams | ||
| } | ||
|
|
||
| /** | ||
| * Determines if the given content type is likely to be human-readable (text-based). | ||
| * @param {Object} headers - The headers object containing content-type | ||
| * @param {*} data - The data to check | ||
| * @returns {boolean} True if the content type is human-readable (text-based) | ||
| */ | ||
| export function isLikelyHumanReadable (headers, data) { | ||
| if (!headers) return typeof data === 'string' | ||
| var contentType = headers['content-type'] | ||
| if (!contentType) return typeof data === 'string' | ||
| // Normalize to lowercase and extract the mime type (ignore charset, etc.) | ||
| var mimeType = contentType.toLowerCase().split(';')[0].trim() | ||
|
|
||
| // Check for text/* types | ||
| if (mimeType.indexOf('text/') === 0) return true | ||
|
|
||
| // Check for specific application/* types | ||
| var readableAppTypes = [ | ||
| '/json', | ||
| '/xml', | ||
| '/xhtml+xml', | ||
| '/ld+json', | ||
| '/yaml', | ||
| '/x-www-form-urlencoded' | ||
| ] | ||
|
|
||
| for (var i = 0; i < readableAppTypes.length; i++) { | ||
| if (mimeType === 'application' + readableAppTypes[i]) return true | ||
| } | ||
|
|
||
| return false | ||
| } | ||
|
|
||
| /** | ||
| * Truncates a string to ensure its UTF-8 byte length does not exceed 4092 bytes. If truncation is necessary, | ||
| * the string is cut off at a character boundary to avoid breaking multi-byte characters and " ..." is appended to indicate truncation. | ||
| * If not a string, it is first converted to a string using JSON.stringify. | ||
| * @param {*} data The data to truncate. | ||
| * @returns {string} | ||
| */ | ||
| export function truncateAsString (data) { | ||
| if (!data) return data | ||
| try { | ||
| if (typeof data !== 'string') data = stringify(data) | ||
| let bytes = 0 | ||
| let i = 0 | ||
| let needsEllipsis = false | ||
|
|
||
| while (i < data.length) { | ||
| const c = data.charCodeAt(i) | ||
| const charBytes = c < 0x80 ? 1 : c < 0x800 ? 2 : c < 0xD800 || c >= 0xE000 ? 3 : 4 | ||
|
|
||
| if (bytes + charBytes > 4092) { | ||
| needsEllipsis = true | ||
| break | ||
| } | ||
|
|
||
| bytes += charBytes | ||
| i += charBytes === 4 ? 2 : 1 | ||
| } | ||
|
|
||
| return data.slice(0, i) + (needsEllipsis ? ' ...' : '') | ||
| } catch (e) { | ||
| return data | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Creates string adder functions for BEL serialization with obfuscation and optional truncation. | ||
| * This ensures a single string table is used while providing separate handling for regular vs payload attributes. | ||
| * @param {Function} getAddStringContext - Function that creates a new string table context | ||
| * @param {Object} obfuscator - Optional obfuscator instance for string obfuscation | ||
| * @returns {{addString: Function, addStringWithTruncation: Function}} Object containing both string adder functions | ||
| */ | ||
| export function createStringAdders (getAddStringContext, obfuscator) { | ||
| const addStringRaw = getAddStringContext() | ||
|
|
||
| const processString = (str, shouldTruncate) => { | ||
| if (typeof str === 'undefined' || str === '') return addStringRaw(str) | ||
| if (typeof str !== 'string') str = stringify(str) | ||
| const obfuscated = obfuscator?.obfuscateString(str) ?? str | ||
| const processed = shouldTruncate ? truncateAsString(obfuscated) : obfuscated | ||
| return addStringRaw(processed) | ||
| } | ||
|
|
||
| return { | ||
| addString: (str) => processString(str, false), | ||
| addStringWithTruncation: (str) => processString(str, true) | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.