87826ee186
## Bug - [x] Related issues linked using `fixes #number` - [x] Integration tests added - [ ] Errors have helpful link attached, see `contributing.md` Fixes #36823 Closes #33084 The issue is caused by the `isLocalURL` function only checks if a URL starts with `/`, `#` or `?`. So a URL that starts with `.` will not be considered a "local URL". The PR fixes that by introducing a new util function `isAbsoluteUrl` that is fully compliant with [RFC3986](https://tools.ietf.org/html/rfc3986#section-4.3).
35 lines
1.1 KiB
TypeScript
35 lines
1.1 KiB
TypeScript
import { getLocationOrigin } from '../../utils'
|
|
import { searchParamsToUrlQuery } from './querystring'
|
|
|
|
/**
|
|
* Parses path-relative urls (e.g. `/hello/world?foo=bar`). If url isn't path-relative
|
|
* (e.g. `./hello`) then at least base must be.
|
|
* Absolute urls are rejected with one exception, in the browser, absolute urls that are on
|
|
* the current origin will be parsed as relative
|
|
*/
|
|
export function parseRelativeUrl(url: string, base?: string) {
|
|
const globalBase = new URL(
|
|
typeof window === 'undefined' ? 'http://n' : getLocationOrigin()
|
|
)
|
|
|
|
const resolvedBase = base
|
|
? new URL(base, globalBase)
|
|
: url.startsWith('.')
|
|
? new URL(typeof window === 'undefined' ? 'http://n' : window.location.href)
|
|
: globalBase
|
|
|
|
const { pathname, searchParams, search, hash, href, origin } = new URL(
|
|
url,
|
|
resolvedBase
|
|
)
|
|
if (origin !== globalBase.origin) {
|
|
throw new Error(`invariant: invalid relative URL, router received ${url}`)
|
|
}
|
|
return {
|
|
pathname,
|
|
query: searchParamsToUrlQuery(searchParams),
|
|
search,
|
|
hash,
|
|
href: href.slice(globalBase.origin.length),
|
|
}
|
|
}
|