Instantly share code, notes, and snippets.
Last active
November 20, 2025 12:31
-
Star
0
(0)
You must be signed in to star a gist -
Fork
0
(0)
You must be signed in to fork a gist
-
-
Save EduardoAC/0291e44b6d81d8ac45f66c1e8424c71e to your computer and use it in GitHub Desktop.
Meaure cookie size and reporting from cURL request
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
| #!/usr/bin/env node | |
| import fs from 'fs'; | |
| import path from 'path'; | |
| import { fileURLToPath } from 'url'; | |
| // Get __dirname equivalent in ES modules | |
| const __filename = fileURLToPath(import.meta.url); | |
| const __dirname = path.dirname(__filename); | |
| // Read the curl request file | |
| const curlFilePath = '{path}/curl-request-size.txt'; | |
| try { | |
| const curlCommand = fs.readFileSync(curlFilePath, 'utf-8'); | |
| // Extract the Cookie header using regex | |
| const cookieMatch = curlCommand.match(/-H "Cookie: ([^"]+)"/); | |
| if (!cookieMatch) { | |
| console.error('β No Cookie header found in the curl command'); | |
| process.exit(1); | |
| } | |
| const cookieHeader = cookieMatch[1]; | |
| // Calculate sizes | |
| const cookieBytes = Buffer.byteLength(cookieHeader, 'utf8'); | |
| const cookieKB = (cookieBytes / 1024).toFixed(2); | |
| const totalHeaderBytes = Buffer.byteLength(`Cookie: ${cookieHeader}`, 'utf8'); | |
| const totalHeaderKB = (totalHeaderBytes / 1024).toFixed(2); | |
| // Helper function to parse URL into components | |
| const parseURL = (urlString) => { | |
| try { | |
| const url = new URL(urlString); | |
| const parts = { | |
| scheme: url.protocol.replace(':', ''), | |
| protocol: url.protocol, | |
| hostname: url.hostname, | |
| port: url.port || (url.protocol === 'https:' ? '443' : url.protocol === 'http:' ? '80' : ''), | |
| pathname: url.pathname, | |
| search: url.search, | |
| hash: url.hash, | |
| origin: url.origin | |
| }; | |
| // Parse query string | |
| const queryParams = []; | |
| url.searchParams.forEach((value, key) => { | |
| const size = Buffer.byteLength(`${key}=${value}`, 'utf8'); | |
| queryParams.push({ | |
| key, | |
| value, | |
| decodedValue: decodeURIComponent(value), | |
| size | |
| }); | |
| }); | |
| // Sort query params by size (largest first) | |
| queryParams.sort((a, b) => b.size - a.size); | |
| return { parts, queryParams }; | |
| } catch (e) { | |
| return null; | |
| } | |
| }; | |
| // Helper function to decode and analyze cookie structure | |
| const analyzeCookieStructure = (name, value) => { | |
| const analysis = { | |
| rawSize: Buffer.byteLength(value, 'utf8'), | |
| components: [] | |
| }; | |
| try { | |
| // Try to decode URL encoding | |
| const decoded = decodeURIComponent(value); | |
| // Check for different structures | |
| if (name === 'dtSa' && decoded.includes('|')) { | |
| // Dynatrace Session Analytics - pipe-delimited | |
| const parts = decoded.split('|'); | |
| analysis.structure = 'Dynatrace Session Analytics (pipe-delimited)'; | |
| const dtSaLabels = [ | |
| 'Session Active', 'Visit Type', 'Visit ID', 'Page Title', 'Page Group', | |
| 'Timestamp', 'Session ID', 'Current URL', 'Reserved 1', 'Reserved 2', 'Reserved 3', 'Reserved 4' | |
| ]; | |
| parts.forEach((part, idx) => { | |
| const size = Buffer.byteLength(part, 'utf8'); | |
| if (size > 20) { // Only show significant parts | |
| let label = dtSaLabels[idx] || `Field ${idx + 1}`; | |
| let purpose = ''; | |
| let parsedUrl = null; | |
| if (part.startsWith('http')) { | |
| label = dtSaLabels[idx] || `URL`; | |
| purpose = 'Full page URL being tracked by analytics'; | |
| parsedUrl = parseURL(part); | |
| } else if (/^\d{13}$/.test(part)) { | |
| purpose = 'Unix timestamp in milliseconds'; | |
| } else if (idx === 0) { | |
| purpose = 'Session state indicator'; | |
| } | |
| analysis.components.push({ | |
| label, | |
| value: part, | |
| size, | |
| percentage: ((size / analysis.rawSize) * 100).toFixed(1), | |
| purpose, | |
| parsedUrl | |
| }); | |
| } | |
| }); | |
| } else if (name === 'ak_bmsc' && decoded.includes('~')) { | |
| // Akamai Bot Manager cookie | |
| const parts = decoded.split('~'); | |
| analysis.structure = 'Akamai Bot Manager (tilde-delimited)'; | |
| const akLabels = ['Hash/Signature', 'Session Counter', 'Bot Detection Data']; | |
| parts.forEach((part, idx) => { | |
| const size = Buffer.byteLength(part, 'utf8'); | |
| if (size > 10) { | |
| analysis.components.push({ | |
| label: akLabels[idx] || `Segment ${idx + 1}`, | |
| value: part, | |
| size, | |
| percentage: ((size / analysis.rawSize) * 100).toFixed(1), | |
| purpose: idx === 0 ? 'Cookie signature/hash' : | |
| idx === 1 ? 'Session counter or timestamp' : | |
| idx === 2 ? 'Encrypted bot detection signals (user behavior, device fingerprint, etc.)' : '' | |
| }); | |
| } | |
| }); | |
| } else if (name === 'bm_sv' && decoded.includes('~')) { | |
| // Akamai Bot Manager sensor value | |
| const parts = decoded.split('~'); | |
| analysis.structure = 'Akamai Bot Manager Sensor (tilde-delimited)'; | |
| const bmLabels = ['Hash/Signature', 'Sensor Data']; | |
| parts.forEach((part, idx) => { | |
| const size = Buffer.byteLength(part, 'utf8'); | |
| if (size > 10) { | |
| analysis.components.push({ | |
| label: bmLabels[idx] || `Segment ${idx + 1}`, | |
| value: part, | |
| size, | |
| percentage: ((size / analysis.rawSize) * 100).toFixed(1), | |
| purpose: idx === 0 ? 'Cookie integrity hash' : | |
| idx === 1 ? 'Real-time sensor data (mouse movements, clicks, scrolling patterns, etc.)' : '' | |
| }); | |
| } | |
| }); | |
| } else if (decoded.includes('~')) { | |
| // Generic tilde-delimited structure | |
| const parts = decoded.split('~'); | |
| analysis.structure = 'tilde-delimited'; | |
| parts.forEach((part, idx) => { | |
| const size = Buffer.byteLength(part, 'utf8'); | |
| if (size > 10) { | |
| analysis.components.push({ | |
| label: `Segment ${idx + 1}`, | |
| value: part, | |
| size, | |
| percentage: ((size / analysis.rawSize) * 100).toFixed(1), | |
| purpose: '' | |
| }); | |
| } | |
| }); | |
| } else if (name === 'dtCookie' && decoded.includes('_')) { | |
| // Dynatrace Cookie - configuration data | |
| const parts = decoded.split('_'); | |
| analysis.structure = 'Dynatrace Configuration (underscore key-value)'; | |
| const dtCookieKeys = { | |
| 'v': 'Version', | |
| 'srv': 'Server ID', | |
| 'sn': 'Session Number', | |
| 'perc': 'Sampling Percentage', | |
| 'ol': 'Offline Mode', | |
| 'mul': 'Multiple Tabs', | |
| 'app': 'Application ID', | |
| 'rcs': 'Resource Collection Strategy' | |
| }; | |
| parts.forEach((part, idx) => { | |
| const size = Buffer.byteLength(part, 'utf8'); | |
| if (size > 5) { | |
| const [key, ...vals] = part.split(/(?<=^\d+\$)|(?<=^[a-z]+\-)/); | |
| const fieldKey = key || part.substring(0, 3); | |
| const label = dtCookieKeys[fieldKey] || `Field ${idx + 1}`; | |
| analysis.components.push({ | |
| label: `${label} (${part.split(/[\s-]/)[0]})`, | |
| value: part, | |
| size, | |
| percentage: ((size / analysis.rawSize) * 100).toFixed(1), | |
| purpose: dtCookieKeys[fieldKey] ? 'Dynatrace monitoring configuration' : 'Configuration parameter' | |
| }); | |
| } | |
| }); | |
| } else if (name === 'dtPC' && decoded.includes('_')) { | |
| // Dynatrace PC - Page Context | |
| const parts = decoded.split('_'); | |
| analysis.structure = 'Dynatrace Page Context (underscore-delimited)'; | |
| parts.forEach((part, idx) => { | |
| const size = Buffer.byteLength(part, 'utf8'); | |
| if (size > 5) { | |
| const label = idx === 0 ? 'Page/Session Identifier' : `Context Field ${idx}`; | |
| analysis.components.push({ | |
| label, | |
| value: part, | |
| size, | |
| percentage: ((size / analysis.rawSize) * 100).toFixed(1), | |
| purpose: idx === 0 ? 'Unique page visit identifier' : 'Page context data for correlation' | |
| }); | |
| } | |
| }); | |
| } else if (decoded.includes('_') && name.includes('dt')) { | |
| // Generic Dynatrace underscore structure | |
| const parts = decoded.split('_'); | |
| analysis.structure = 'Dynatrace (underscore key-value)'; | |
| parts.forEach((part, idx) => { | |
| const size = Buffer.byteLength(part, 'utf8'); | |
| if (size > 5) { | |
| analysis.components.push({ | |
| label: `Field ${idx + 1}`, | |
| value: part, | |
| size, | |
| percentage: ((size / analysis.rawSize) * 100).toFixed(1), | |
| purpose: 'Dynatrace monitoring data' | |
| }); | |
| } | |
| }); | |
| } else if (name.startsWith('amp_')) { | |
| // Amplitude Analytics cookie | |
| const parts = decoded.split('.'); | |
| analysis.structure = 'Amplitude Analytics (dot-delimited)'; | |
| const ampLabels = ['Device ID', 'User/Session Info (base64)', 'Empty', 'Session ID', 'Event ID', 'Event Count', 'Session Events', 'Sequence']; | |
| parts.forEach((part, idx) => { | |
| const size = Buffer.byteLength(part, 'utf8'); | |
| analysis.components.push({ | |
| label: ampLabels[idx] || `Token ${idx + 1}`, | |
| value: part, | |
| size, | |
| percentage: ((size / analysis.rawSize) * 100).toFixed(1), | |
| purpose: idx === 0 ? 'Device identifier for tracking' : | |
| idx === 1 ? 'Encoded user/session metadata' : | |
| idx === 3 || idx === 4 ? 'Session/event tracking IDs' : | |
| idx === 5 || idx === 6 || idx === 7 ? 'Event counters for analytics' : '' | |
| }); | |
| }); | |
| } else if (decoded.includes('.')) { | |
| // Generic dot-delimited structure | |
| const parts = decoded.split('.'); | |
| analysis.structure = 'dot-delimited'; | |
| parts.forEach((part, idx) => { | |
| const size = Buffer.byteLength(part, 'utf8'); | |
| analysis.components.push({ | |
| label: `Token ${idx + 1}`, | |
| value: part, | |
| size, | |
| percentage: ((size / analysis.rawSize) * 100).toFixed(1), | |
| purpose: '' | |
| }); | |
| }); | |
| } else if (name.startsWith('TS0')) { | |
| // Traffic Server cookie | |
| analysis.structure = 'Traffic Server Session Token'; | |
| analysis.components.push({ | |
| label: 'Session Token', | |
| value: decoded, | |
| size: analysis.rawSize, | |
| percentage: '100.0', | |
| purpose: 'Load balancer or CDN session persistence token' | |
| }); | |
| } else if (name === 'JSESSIONID') { | |
| analysis.structure = 'Java Session ID'; | |
| analysis.components.push({ | |
| label: 'Session Identifier', | |
| value: decoded, | |
| size: analysis.rawSize, | |
| percentage: '100.0', | |
| purpose: 'Java application server session tracking' | |
| }); | |
| } else if (name === 'PIM-SESSION-ID') { | |
| analysis.structure = 'Payment Integration Manager Session'; | |
| analysis.components.push({ | |
| label: 'Payment Session ID', | |
| value: decoded, | |
| size: analysis.rawSize, | |
| percentage: '100.0', | |
| purpose: 'SafeCharge/Nuvei payment session identifier' | |
| }); | |
| } else if (name.startsWith('rx')) { | |
| // RxVisitor or rxvt - RUM (Real User Monitoring) | |
| analysis.structure = 'Real User Monitoring (RUM)'; | |
| if (decoded.includes('|')) { | |
| const parts = decoded.split('|'); | |
| parts.forEach((part, idx) => { | |
| const size = Buffer.byteLength(part, 'utf8'); | |
| analysis.components.push({ | |
| label: idx === 0 ? 'Expiration Timestamp' : `Field ${idx + 1}`, | |
| value: part, | |
| size, | |
| percentage: ((size / analysis.rawSize) * 100).toFixed(1), | |
| purpose: idx === 0 ? 'Cookie expiration time' : 'Visitor tracking data' | |
| }); | |
| }); | |
| } else { | |
| analysis.components.push({ | |
| label: 'Visitor ID', | |
| value: decoded, | |
| size: analysis.rawSize, | |
| percentage: '100.0', | |
| purpose: 'Unique visitor identifier for performance monitoring' | |
| }); | |
| } | |
| } else if (name === 'themeId') { | |
| analysis.structure = 'UI Theme Preference'; | |
| analysis.components.push({ | |
| label: 'Theme ID', | |
| value: decoded, | |
| size: analysis.rawSize, | |
| percentage: '100.0', | |
| purpose: 'User interface theme selection' | |
| }); | |
| } else { | |
| // Single value or unknown structure | |
| analysis.structure = 'single-value'; | |
| analysis.components.push({ | |
| label: 'Value', | |
| value: decoded, | |
| size: analysis.rawSize, | |
| percentage: '100.0', | |
| purpose: '' | |
| }); | |
| } | |
| } catch (e) { | |
| // If decoding fails, treat as raw | |
| analysis.structure = 'raw/encoded'; | |
| analysis.components.push({ | |
| label: 'Encoded value', | |
| value: value, | |
| size: analysis.rawSize, | |
| percentage: '100.0', | |
| purpose: 'Unable to decode - may be encrypted or binary' | |
| }); | |
| } | |
| return analysis; | |
| }; | |
| // Parse individual cookies | |
| const cookies = cookieHeader.split('; '); | |
| const cookieDetails = cookies.map(cookie => { | |
| const [name, ...valueParts] = cookie.split('='); | |
| const value = valueParts.join('='); | |
| const size = Buffer.byteLength(cookie, 'utf8'); | |
| const structure = analyzeCookieStructure(name, value); | |
| return { name, value, size, structure }; | |
| }); | |
| // Sort by size (largest first) | |
| cookieDetails.sort((a, b) => b.size - a.size); | |
| // Display results | |
| console.log('πͺ Cookie Size Analysis'); | |
| console.log('β'.repeat(80)); | |
| console.log(`\nπ Total Cookie Size:`); | |
| console.log(` Cookie value: ${cookieBytes} bytes (${cookieKB} KB)`); | |
| console.log(` Full header: ${totalHeaderBytes} bytes (${totalHeaderKB} KB)`); | |
| console.log(`\nπ Number of cookies: ${cookies.length}`); | |
| console.log(`\nπ Individual Cookies (ranked by size - highest on top):`); | |
| console.log('β'.repeat(80)); | |
| cookieDetails.forEach((cookie, index) => { | |
| const sizeKB = (cookie.size / 1024).toFixed(2); | |
| const percentage = ((cookie.size / cookieBytes) * 100).toFixed(1); | |
| console.log(`\n${index + 1}. πͺ ${cookie.name}`); | |
| console.log(` π Size: ${cookie.size} bytes (${sizeKB} KB) - ${percentage}% of total cookie header`); | |
| console.log(` π Structure: ${cookie.structure.structure}`); | |
| // Show breakdown of components | |
| if (cookie.structure.components.length > 0) { | |
| console.log(` π Breakdown:`); | |
| cookie.structure.components.forEach((comp, compIdx) => { | |
| const compKB = (comp.size / 1024).toFixed(2); | |
| console.log(` ${compIdx + 1}. ${comp.label}`); | |
| console.log(` Size: ${comp.size} bytes (${compKB} KB) - ${comp.percentage}% of this cookie`); | |
| if (comp.purpose) { | |
| console.log(` Purpose: ${comp.purpose}`); | |
| } | |
| // If this component has a parsed URL, display it in detail | |
| if (comp.parsedUrl) { | |
| const { parts, queryParams } = comp.parsedUrl; | |
| console.log(`\n π URL COMPONENTS:`); | |
| console.log(` ββ Scheme: ${parts.scheme}`); | |
| console.log(` ββ Protocol: ${parts.protocol}`); | |
| console.log(` ββ Hostname: ${parts.hostname}`); | |
| console.log(` ββ Port: ${parts.port}`); | |
| console.log(` ββ Pathname: ${parts.pathname}`); | |
| console.log(` ββ Origin: ${parts.origin}`); | |
| if (queryParams.length > 0) { | |
| console.log(`\n π QUERY STRING PARAMETERS (${queryParams.length} total, sorted by size):`); | |
| console.log(` ${'β'.repeat(70)}`); | |
| queryParams.forEach((param, paramIdx) => { | |
| const paramKB = (param.size / 1024).toFixed(3); | |
| const paramPercent = ((param.size / comp.size) * 100).toFixed(1); | |
| console.log(`\n ${paramIdx + 1}. ${param.key}`); | |
| console.log(` Size: ${param.size} bytes (${paramKB} KB) - ${paramPercent}% of URL`); | |
| console.log(` Encoded: ${param.value.substring(0, 100)}${param.value.length > 100 ? '...' : ''}`); | |
| // Show decoded value if different | |
| if (param.value !== param.decodedValue) { | |
| const displayValue = param.decodedValue.length > 150 | |
| ? param.decodedValue.substring(0, 150) + '...' | |
| : param.decodedValue; | |
| console.log(` Decoded: ${displayValue}`); | |
| } | |
| }); | |
| console.log(` ${'β'.repeat(70)}\n`); | |
| } | |
| } else { | |
| console.log(` Content: ${comp.value}`); | |
| } | |
| }); | |
| } | |
| }); | |
| // Check against common limits | |
| console.log('\nβ οΈ Size Limits Check:'); | |
| console.log('β'.repeat(80)); | |
| console.log(`Browser limit (per cookie): ~4 KB`); | |
| console.log(`Total header size limit: ~8-16 KB (varies by server)`); | |
| console.log(`Current total header size: ${totalHeaderKB} KB`); | |
| if (totalHeaderBytes > 8192) { | |
| console.log('\nβ οΈ WARNING: Cookie header exceeds 8 KB, may cause issues with some servers!'); | |
| } else { | |
| console.log('\nβ Cookie header size is within reasonable limits'); | |
| } | |
| } catch (error) { | |
| console.error('β Error:', error.message); | |
| process.exit(1); | |
| } | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment