2020-08-05 20:12:17 +02:00
|
|
|
import { getLocationOrigin } from '../../utils'
|
2020-09-03 20:26:52 +02:00
|
|
|
import { searchParamsToUrlQuery } from './querystring'
|
2020-08-05 20:12:17 +02:00
|
|
|
|
|
|
|
const DUMMY_BASE = new URL(
|
|
|
|
typeof window === 'undefined' ? 'http://n' : getLocationOrigin()
|
|
|
|
)
|
2020-07-13 18:08:12 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* 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.
|
2020-08-05 20:12:17 +02:00
|
|
|
* Absolute urls are rejected with one exception, in the browser, absolute urls that are on
|
|
|
|
* the current origin will be parsed as relative
|
2020-07-13 18:08:12 +02:00
|
|
|
*/
|
|
|
|
export function parseRelativeUrl(url: string, base?: string) {
|
|
|
|
const resolvedBase = base ? new URL(base, DUMMY_BASE) : DUMMY_BASE
|
2020-08-05 20:12:17 +02:00
|
|
|
const {
|
|
|
|
pathname,
|
|
|
|
searchParams,
|
|
|
|
search,
|
|
|
|
hash,
|
|
|
|
href,
|
|
|
|
origin,
|
|
|
|
protocol,
|
|
|
|
} = new URL(url, resolvedBase)
|
|
|
|
if (
|
|
|
|
origin !== DUMMY_BASE.origin ||
|
|
|
|
(protocol !== 'http:' && protocol !== 'https:')
|
|
|
|
) {
|
2020-07-13 18:08:12 +02:00
|
|
|
throw new Error('invariant: invalid relative URL')
|
|
|
|
}
|
|
|
|
return {
|
|
|
|
pathname,
|
2020-09-03 20:26:52 +02:00
|
|
|
query: searchParamsToUrlQuery(searchParams),
|
2020-07-13 18:08:12 +02:00
|
|
|
search,
|
|
|
|
hash,
|
|
|
|
href: href.slice(DUMMY_BASE.origin.length),
|
|
|
|
}
|
|
|
|
}
|