dsn.js
1 import { logger } from './logger.js'; 2 3 /** Regular expression used to parse a Dsn. */ 4 const DSN_REGEX = /^(?:(\w+):)\/\/(?:(\w+)(?::(\w+)?)?@)([\w.-]+)(?::(\d+))?\/(.+)/; 5 6 function isValidProtocol(protocol) { 7 return protocol === 'http' || protocol === 'https'; 8 } 9 10 /** 11 * Renders the string representation of this Dsn. 12 * 13 * By default, this will render the public representation without the password 14 * component. To get the deprecated private representation, set `withPassword` 15 * to true. 16 * 17 * @param withPassword When set to true, the password will be included. 18 */ 19 function dsnToString(dsn, withPassword = false) { 20 const { host, path, pass, port, projectId, protocol, publicKey } = dsn; 21 return ( 22 `${protocol}://${publicKey}${withPassword && pass ? `:${pass}` : ''}` + 23 `@${host}${port ? `:${port}` : ''}/${path ? `${path}/` : path}${projectId}` 24 ); 25 } 26 27 /** 28 * Parses a Dsn from a given string. 29 * 30 * @param str A Dsn as string 31 * @returns Dsn as DsnComponents or undefined if @param str is not a valid DSN string 32 */ 33 function dsnFromString(str) { 34 const match = DSN_REGEX.exec(str); 35 36 if (!match) { 37 // This should be logged to the console 38 // eslint-disable-next-line no-console 39 console.error(`Invalid Sentry Dsn: ${str}`); 40 return undefined; 41 } 42 43 const [protocol, publicKey, pass = '', host, port = '', lastPath] = match.slice(1); 44 let path = ''; 45 let projectId = lastPath; 46 47 const split = projectId.split('/'); 48 if (split.length > 1) { 49 path = split.slice(0, -1).join('/'); 50 projectId = split.pop() ; 51 } 52 53 if (projectId) { 54 const projectMatch = projectId.match(/^\d+/); 55 if (projectMatch) { 56 projectId = projectMatch[0]; 57 } 58 } 59 60 return dsnFromComponents({ host, pass, path, projectId, port, protocol: protocol , publicKey }); 61 } 62 63 function dsnFromComponents(components) { 64 return { 65 protocol: components.protocol, 66 publicKey: components.publicKey || '', 67 pass: components.pass || '', 68 host: components.host, 69 port: components.port || '', 70 path: components.path || '', 71 projectId: components.projectId, 72 }; 73 } 74 75 function validateDsn(dsn) { 76 if (!(typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__)) { 77 return true; 78 } 79 80 const { port, projectId, protocol } = dsn; 81 82 const requiredComponents = ['protocol', 'publicKey', 'host', 'projectId']; 83 const hasMissingRequiredComponent = requiredComponents.find(component => { 84 if (!dsn[component]) { 85 logger.error(`Invalid Sentry Dsn: ${component} missing`); 86 return true; 87 } 88 return false; 89 }); 90 91 if (hasMissingRequiredComponent) { 92 return false; 93 } 94 95 if (!projectId.match(/^\d+$/)) { 96 logger.error(`Invalid Sentry Dsn: Invalid projectId ${projectId}`); 97 return false; 98 } 99 100 if (!isValidProtocol(protocol)) { 101 logger.error(`Invalid Sentry Dsn: Invalid protocol ${protocol}`); 102 return false; 103 } 104 105 if (port && isNaN(parseInt(port, 10))) { 106 logger.error(`Invalid Sentry Dsn: Invalid port ${port}`); 107 return false; 108 } 109 110 return true; 111 } 112 113 /** 114 * Creates a valid Sentry Dsn object, identifying a Sentry instance and project. 115 * @returns a valid DsnComponents object or `undefined` if @param from is an invalid DSN source 116 */ 117 function makeDsn(from) { 118 const components = typeof from === 'string' ? dsnFromString(from) : dsnFromComponents(from); 119 if (!components || !validateDsn(components)) { 120 return undefined; 121 } 122 return components; 123 } 124 125 export { dsnFromString, dsnToString, makeDsn }; 126 //# sourceMappingURL=dsn.js.map