@@ -83,36 +83,40 @@ export function modifyUrl(
8383 url : string ,
8484 urlModifier : ( urlParts : URLMeaningfulParts ) => Partial < URLMeaningfulParts > | void
8585) {
86- const parsed = parseUrl ( url , true ) as URLMeaningfulParts ;
86+ try {
87+ const parsed = parseUrl ( url , true ) as URLMeaningfulParts ;
8788
88- // Copy over the most specific version of each property. By default, the parsed url includes several
89- // conflicting properties (like path and pathname + search, or search and query) and keeping track
90- // of which property is actually used when they are formatted is harder than necessary.
91- const meaningfulParts : URLMeaningfulParts = {
92- auth : parsed . auth ,
93- hash : parsed . hash ,
94- hostname : parsed . hostname ,
95- pathname : parsed . pathname ,
96- port : parsed . port ,
97- protocol : parsed . protocol ,
98- query : parsed . query || { } ,
99- slashes : parsed . slashes ,
100- } ;
89+ // Copy over the most specific version of each property. By default, the parsed url includes several
90+ // conflicting properties (like path and pathname + search, or search and query) and keeping track
91+ // of which property is actually used when they are formatted is harder than necessary.
92+ const meaningfulParts : URLMeaningfulParts = {
93+ auth : parsed . auth ,
94+ hash : parsed . hash ,
95+ hostname : parsed . hostname ,
96+ pathname : parsed . pathname ,
97+ port : parsed . port ,
98+ protocol : parsed . protocol ,
99+ query : parsed . query || { } ,
100+ slashes : parsed . slashes ,
101+ } ;
101102
102- // The urlModifier modifies the meaningfulParts object, or returns a new one.
103- const modifiedParts = urlModifier ( meaningfulParts ) || meaningfulParts ;
103+ // The urlModifier modifies the meaningfulParts object, or returns a new one.
104+ const modifiedParts = urlModifier ( meaningfulParts ) || meaningfulParts ;
104105
105- // Format the modified/replaced meaningfulParts back into a url.
106- return formatUrl ( {
107- auth : modifiedParts . auth ,
108- hash : modifiedParts . hash ,
109- hostname : modifiedParts . hostname ,
110- pathname : modifiedParts . pathname ,
111- port : modifiedParts . port ,
112- protocol : modifiedParts . protocol ,
113- query : modifiedParts . query ,
114- slashes : modifiedParts . slashes ,
115- } as UrlObject ) ;
106+ // Format the modified/replaced meaningfulParts back into a url.
107+ return formatUrl ( {
108+ auth : modifiedParts . auth ,
109+ hash : modifiedParts . hash ,
110+ hostname : modifiedParts . hostname ,
111+ pathname : modifiedParts . pathname ,
112+ port : modifiedParts . port ,
113+ protocol : modifiedParts . protocol ,
114+ query : modifiedParts . query ,
115+ slashes : modifiedParts . slashes ,
116+ } as UrlObject ) ;
117+ } catch ( error ) {
118+ return url ; // Safe fallback to original url
119+ }
116120}
117121
118122/**
@@ -122,28 +126,36 @@ export function modifyUrl(
122126 * @public
123127 */
124128export function isRelativeUrl ( candidatePath : string ) {
125- // validate that `candidatePath` is not attempting a redirect to somewhere
126- // outside of this OpenSearch Dashboards install
127- const all = parseUrl ( candidatePath , false /* parseQueryString */ , true /* slashesDenoteHost */ ) ;
128- const { protocol, hostname, port } = all ;
129- // We should explicitly compare `protocol`, `port` and `hostname` to null to make sure these are not
130- // detected in the URL at all. For example `hostname` can be empty string for Node URL parser, but
131- // browser (because of various bwc reasons) processes URL differently (e.g. `///abc.com` - for browser
132- // hostname is `abc.com`, but for Node hostname is an empty string i.e. everything between schema (`//`)
133- // and the first slash that belongs to path.
134- if ( protocol !== null || hostname !== null || port !== null ) {
135- return false ;
129+ try {
130+ // validate that `candidatePath` is not attempting a redirect to somewhere
131+ // outside of this OpenSearch Dashboards install
132+ const all = parseUrl ( candidatePath , false /* parseQueryString */ , true /* slashesDenoteHost */ ) ;
133+ const { protocol, hostname, port } = all ;
134+ // We should explicitly compare `protocol`, `port` and `hostname` to null to make sure these are not
135+ // detected in the URL at all. For example `hostname` can be empty string for Node URL parser, but
136+ // browser (because of various bwc reasons) processes URL differently (e.g. `///abc.com` - for browser
137+ // hostname is `abc.com`, but for Node hostname is an empty string i.e. everything between schema (`//`)
138+ // and the first slash that belongs to path.
139+ if ( protocol !== null || hostname !== null || port !== null ) {
140+ return false ;
141+ }
142+ return true ;
143+ } catch ( error ) {
144+ return false ; // Safe fallback to "not relative"
136145 }
137- return true ;
138146}
139147
140148/**
141149 * Returns the origin (protocol + host + port) from given `url` if `url` is a valid absolute url, or null otherwise
142150 */
143151export function getUrlOrigin ( url : string ) : string | null {
144- const obj = parseUrl ( url ) ;
145- if ( ! obj . protocol && ! obj . hostname ) {
146- return null ;
152+ try {
153+ const obj = parseUrl ( url ) ;
154+ if ( ! obj . protocol && ! obj . hostname ) {
155+ return null ;
156+ }
157+ return `${ obj . protocol } //${ obj . hostname } ${ obj . port ? `:${ obj . port } ` : '' } ` ;
158+ } catch ( error ) {
159+ return null ; // Safe fallback to null
147160 }
148- return `${ obj . protocol } //${ obj . hostname } ${ obj . port ? `:${ obj . port } ` : '' } ` ;
149161}
0 commit comments