123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188 |
- 'use strict'
- const UUID_REG = /^[\da-f]{8}\b-[\da-f]{4}\b-[\da-f]{4}\b-[\da-f]{4}\b-[\da-f]{12}$/iu
- const URN_REG = /([\da-z][\d\-a-z]{0,31}):((?:[\w!$'()*+,\-.:;=@]|%[\da-f]{2})+)/iu
- function isSecure (wsComponents) {
- return typeof wsComponents.secure === 'boolean' ? wsComponents.secure : String(wsComponents.scheme).toLowerCase() === 'wss'
- }
- function httpParse (components) {
- if (!components.host) {
- components.error = components.error || 'HTTP URIs must have a host.'
- }
- return components
- }
- function httpSerialize (components) {
- const secure = String(components.scheme).toLowerCase() === 'https'
- // normalize the default port
- if (components.port === (secure ? 443 : 80) || components.port === '') {
- components.port = undefined
- }
- // normalize the empty path
- if (!components.path) {
- components.path = '/'
- }
- // NOTE: We do not parse query strings for HTTP URIs
- // as WWW Form Url Encoded query strings are part of the HTML4+ spec,
- // and not the HTTP spec.
- return components
- }
- function wsParse (wsComponents) {
- // indicate if the secure flag is set
- wsComponents.secure = isSecure(wsComponents)
- // construct resouce name
- wsComponents.resourceName = (wsComponents.path || '/') + (wsComponents.query ? '?' + wsComponents.query : '')
- wsComponents.path = undefined
- wsComponents.query = undefined
- return wsComponents
- }
- function wsSerialize (wsComponents) {
- // normalize the default port
- if (wsComponents.port === (isSecure(wsComponents) ? 443 : 80) || wsComponents.port === '') {
- wsComponents.port = undefined
- }
- // ensure scheme matches secure flag
- if (typeof wsComponents.secure === 'boolean') {
- wsComponents.scheme = (wsComponents.secure ? 'wss' : 'ws')
- wsComponents.secure = undefined
- }
- // reconstruct path from resource name
- if (wsComponents.resourceName) {
- const [path, query] = wsComponents.resourceName.split('?')
- wsComponents.path = (path && path !== '/' ? path : undefined)
- wsComponents.query = query
- wsComponents.resourceName = undefined
- }
- // forbid fragment component
- wsComponents.fragment = undefined
- return wsComponents
- }
- function urnParse (urnComponents, options) {
- if (!urnComponents.path) {
- urnComponents.error = 'URN can not be parsed'
- return urnComponents
- }
- const matches = urnComponents.path.match(URN_REG)
- if (matches) {
- const scheme = options.scheme || urnComponents.scheme || 'urn'
- urnComponents.nid = matches[1].toLowerCase()
- urnComponents.nss = matches[2]
- const urnScheme = `${scheme}:${options.nid || urnComponents.nid}`
- const schemeHandler = SCHEMES[urnScheme]
- urnComponents.path = undefined
- if (schemeHandler) {
- urnComponents = schemeHandler.parse(urnComponents, options)
- }
- } else {
- urnComponents.error = urnComponents.error || 'URN can not be parsed.'
- }
- return urnComponents
- }
- function urnSerialize (urnComponents, options) {
- const scheme = options.scheme || urnComponents.scheme || 'urn'
- const nid = urnComponents.nid.toLowerCase()
- const urnScheme = `${scheme}:${options.nid || nid}`
- const schemeHandler = SCHEMES[urnScheme]
- if (schemeHandler) {
- urnComponents = schemeHandler.serialize(urnComponents, options)
- }
- const uriComponents = urnComponents
- const nss = urnComponents.nss
- uriComponents.path = `${nid || options.nid}:${nss}`
- options.skipEscape = true
- return uriComponents
- }
- function urnuuidParse (urnComponents, options) {
- const uuidComponents = urnComponents
- uuidComponents.uuid = uuidComponents.nss
- uuidComponents.nss = undefined
- if (!options.tolerant && (!uuidComponents.uuid || !UUID_REG.test(uuidComponents.uuid))) {
- uuidComponents.error = uuidComponents.error || 'UUID is not valid.'
- }
- return uuidComponents
- }
- function urnuuidSerialize (uuidComponents) {
- const urnComponents = uuidComponents
- // normalize UUID
- urnComponents.nss = (uuidComponents.uuid || '').toLowerCase()
- return urnComponents
- }
- const http = {
- scheme: 'http',
- domainHost: true,
- parse: httpParse,
- serialize: httpSerialize
- }
- const https = {
- scheme: 'https',
- domainHost: http.domainHost,
- parse: httpParse,
- serialize: httpSerialize
- }
- const ws = {
- scheme: 'ws',
- domainHost: true,
- parse: wsParse,
- serialize: wsSerialize
- }
- const wss = {
- scheme: 'wss',
- domainHost: ws.domainHost,
- parse: ws.parse,
- serialize: ws.serialize
- }
- const urn = {
- scheme: 'urn',
- parse: urnParse,
- serialize: urnSerialize,
- skipNormalize: true
- }
- const urnuuid = {
- scheme: 'urn:uuid',
- parse: urnuuidParse,
- serialize: urnuuidSerialize,
- skipNormalize: true
- }
- const SCHEMES = {
- http,
- https,
- ws,
- wss,
- urn,
- 'urn:uuid': urnuuid
- }
- module.exports = SCHEMES
|