@@ -3,14 +3,13 @@ import { Dsn, DsnComponents, DsnLike, DsnProtocol } from '@sentry/types';
33import { isDebugBuild } from './env' ;
44import { SentryError } from './error' ;
55
6+ /** Regular expression used to parse a Dsn. */
7+ const DSN_REGEX = / ^ (?: ( \w + ) : ) \/ \/ (?: ( \w + ) (?: : ( \w + ) ) ? @ ) ( [ \w . - ] + ) (?: : ( \d + ) ) ? \/ ( .+ ) / ;
8+
69function isValidProtocol ( protocol ?: string ) : protocol is DsnProtocol {
710 return protocol === 'http' || protocol === 'https' ;
811}
912
10- function normalizeProtocol ( input : string ) : string {
11- return input . replace ( / : $ / , '' ) ;
12- }
13-
1413/**
1514 * Renders the string representation of this Dsn.
1615 *
@@ -21,28 +20,38 @@ function normalizeProtocol(input: string): string {
2120 * @param withPassword When set to true, the password will be included.
2221 */
2322function dsntoString ( dsn : Dsn , withPassword : boolean = false ) : string {
24- const { host, port , path, pass, projectId, protocol, publicKey } = dsn ;
23+ const { host, path, pass, port , projectId, protocol, publicKey } = dsn ;
2524 return (
2625 `${ protocol } ://${ publicKey } ${ withPassword && pass ? `:${ pass } ` : '' } ` +
27- `@${ host } ${ port ? `:${ port } ` : '' } ${ path } / ${ projectId } `
26+ `@${ host } ${ port ? `:${ port } ` : '' } / ${ path ? ` ${ path } /` : path } ${ projectId } `
2827 ) ;
2928}
3029
3130function dsnFromString ( str : string ) : Dsn {
32- const url = new URL ( str ) ;
33-
34- const pathComponents = url . pathname . split ( '/' ) ;
35- const projectId = pathComponents . pop ( ) ;
36-
37- return dsnFromComponents ( {
38- host : url . hostname ,
39- pass : url . password ,
40- path : pathComponents . join ( '/' ) ,
41- projectId : projectId || '' ,
42- port : url . port ,
43- protocol : normalizeProtocol ( url . protocol ) as DsnProtocol ,
44- publicKey : url . username ,
45- } ) ;
31+ const match = DSN_REGEX . exec ( str ) ;
32+
33+ if ( ! match ) {
34+ throw new SentryError ( 'Invalid Dsn' ) ;
35+ }
36+
37+ const [ protocol , publicKey , pass = '' , host , port = '' , lastPath ] = match . slice ( 1 ) ;
38+ let path = '' ;
39+ let projectId = lastPath ;
40+
41+ const split = projectId . split ( '/' ) ;
42+ if ( split . length > 1 ) {
43+ path = split . slice ( 0 , - 1 ) . join ( '/' ) ;
44+ projectId = split . pop ( ) as string ;
45+ }
46+
47+ if ( projectId ) {
48+ const projectMatch = projectId . match ( / ^ \d + / ) ;
49+ if ( projectMatch ) {
50+ projectId = projectMatch [ 0 ] ;
51+ }
52+ }
53+
54+ return dsnFromComponents ( { host, pass, path, projectId, port, protocol : protocol as DsnProtocol , publicKey } ) ;
4655}
4756
4857function dsnFromComponents ( components : DsnComponents ) : Dsn {
0 commit comments