| 'use strict' |
|
|
| const { isUUID } = require('./utils') |
| const URN_REG = /([\da-z][\d\-a-z]{0,31}):((?:[\w!$'()*+,\-.:;=@]|%[\da-f]{2})+)/iu |
|
|
| const supportedSchemeNames = (['http', 'https', 'ws', |
| 'wss', 'urn', 'urn:uuid']) |
|
|
| |
|
|
| |
| |
| |
| |
| function isValidSchemeName (name) { |
| return supportedSchemeNames.indexOf( (name)) !== -1 |
| } |
|
|
| |
| |
| |
| |
| |
| |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| |
| |
| |
| |
| function wsIsSecure (wsComponent) { |
| if (wsComponent.secure === true) { |
| return true |
| } else if (wsComponent.secure === false) { |
| return false |
| } else if (wsComponent.scheme) { |
| return ( |
| wsComponent.scheme.length === 3 && |
| (wsComponent.scheme[0] === 'w' || wsComponent.scheme[0] === 'W') && |
| (wsComponent.scheme[1] === 's' || wsComponent.scheme[1] === 'S') && |
| (wsComponent.scheme[2] === 's' || wsComponent.scheme[2] === 'S') |
| ) |
| } else { |
| return false |
| } |
| } |
|
|
| |
| function httpParse (component) { |
| if (!component.host) { |
| component.error = component.error || 'HTTP URIs must have a host.' |
| } |
|
|
| return component |
| } |
|
|
| |
| function httpSerialize (component) { |
| const secure = String(component.scheme).toLowerCase() === 'https' |
|
|
| |
| if (component.port === (secure ? 443 : 80) || component.port === '') { |
| component.port = undefined |
| } |
|
|
| |
| if (!component.path) { |
| component.path = '/' |
| } |
|
|
| |
| |
| |
|
|
| return component |
| } |
|
|
| |
| function wsParse (wsComponent) { |
| |
| wsComponent.secure = wsIsSecure(wsComponent) |
|
|
| |
| wsComponent.resourceName = (wsComponent.path || '/') + (wsComponent.query ? '?' + wsComponent.query : '') |
| wsComponent.path = undefined |
| wsComponent.query = undefined |
|
|
| return wsComponent |
| } |
|
|
| |
| function wsSerialize (wsComponent) { |
| |
| if (wsComponent.port === (wsIsSecure(wsComponent) ? 443 : 80) || wsComponent.port === '') { |
| wsComponent.port = undefined |
| } |
|
|
| |
| if (typeof wsComponent.secure === 'boolean') { |
| wsComponent.scheme = (wsComponent.secure ? 'wss' : 'ws') |
| wsComponent.secure = undefined |
| } |
|
|
| |
| if (wsComponent.resourceName) { |
| const [path, query] = wsComponent.resourceName.split('?') |
| wsComponent.path = (path && path !== '/' ? path : undefined) |
| wsComponent.query = query |
| wsComponent.resourceName = undefined |
| } |
|
|
| |
| wsComponent.fragment = undefined |
|
|
| return wsComponent |
| } |
|
|
| |
| function urnParse (urnComponent, options) { |
| if (!urnComponent.path) { |
| urnComponent.error = 'URN can not be parsed' |
| return urnComponent |
| } |
| const matches = urnComponent.path.match(URN_REG) |
| if (matches) { |
| const scheme = options.scheme || urnComponent.scheme || 'urn' |
| urnComponent.nid = matches[1].toLowerCase() |
| urnComponent.nss = matches[2] |
| const urnScheme = `${scheme}:${options.nid || urnComponent.nid}` |
| const schemeHandler = getSchemeHandler(urnScheme) |
| urnComponent.path = undefined |
|
|
| if (schemeHandler) { |
| urnComponent = schemeHandler.parse(urnComponent, options) |
| } |
| } else { |
| urnComponent.error = urnComponent.error || 'URN can not be parsed.' |
| } |
|
|
| return urnComponent |
| } |
|
|
| |
| function urnSerialize (urnComponent, options) { |
| if (urnComponent.nid === undefined) { |
| throw new Error('URN without nid cannot be serialized') |
| } |
| const scheme = options.scheme || urnComponent.scheme || 'urn' |
| const nid = urnComponent.nid.toLowerCase() |
| const urnScheme = `${scheme}:${options.nid || nid}` |
| const schemeHandler = getSchemeHandler(urnScheme) |
|
|
| if (schemeHandler) { |
| urnComponent = schemeHandler.serialize(urnComponent, options) |
| } |
|
|
| const uriComponent = urnComponent |
| const nss = urnComponent.nss |
| uriComponent.path = `${nid || options.nid}:${nss}` |
|
|
| options.skipEscape = true |
| return uriComponent |
| } |
|
|
| |
| function urnuuidParse (urnComponent, options) { |
| const uuidComponent = urnComponent |
| uuidComponent.uuid = uuidComponent.nss |
| uuidComponent.nss = undefined |
|
|
| if (!options.tolerant && (!uuidComponent.uuid || !isUUID(uuidComponent.uuid))) { |
| uuidComponent.error = uuidComponent.error || 'UUID is not valid.' |
| } |
|
|
| return uuidComponent |
| } |
|
|
| |
| function urnuuidSerialize (uuidComponent) { |
| const urnComponent = uuidComponent |
| |
| urnComponent.nss = (uuidComponent.uuid || '').toLowerCase() |
| return urnComponent |
| } |
|
|
| 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 |
| }) |
|
|
| Object.setPrototypeOf(SCHEMES, null) |
|
|
| |
| |
| |
| |
| function getSchemeHandler (scheme) { |
| return ( |
| scheme && ( |
| SCHEMES[ (scheme)] || |
| SCHEMES[(scheme.toLowerCase())]) |
| ) || |
| undefined |
| } |
|
|
| module.exports = { |
| wsIsSecure, |
| SCHEMES, |
| isValidSchemeName, |
| getSchemeHandler, |
| } |
|
|