BVB Source Codes

parse-server Show mongodbUrl.js Source code

Return Download parse-server: download mongodbUrl.js Source code - Download parse-server Source code - Type:.js
  1. // A slightly patched version of node's url module, with support for mongodb://
  2. // uris.
  3. //
  4. // See https://github.com/nodejs/node/blob/master/LICENSE for licensing
  5. // information
  6.  
  7. 'use strict';
  8.  
  9. const punycode = require('punycode');
  10.  
  11. exports.parse = urlParse;
  12. exports.resolve = urlResolve;
  13. exports.resolveObject = urlResolveObject;
  14. exports.format = urlFormat;
  15.  
  16. exports.Url = Url;
  17.  
  18. function Url() {
  19.   this.protocol = null;
  20.   this.slashes = null;
  21.   this.auth = null;
  22.   this.host = null;
  23.   this.port = null;
  24.   this.hostname = null;
  25.   this.hash = null;
  26.   this.search = null;
  27.   this.query = null;
  28.   this.pathname = null;
  29.   this.path = null;
  30.   this.href = null;
  31. }
  32.  
  33. // Reference: RFC 3986, RFC 1808, RFC 2396
  34.  
  35. // define these here so at least they only have to be
  36. // compiled once on the first module load.
  37. const protocolPattern = /^([a-z0-9.+-]+:)/i;
  38. const portPattern = /:[0-9]*$/;
  39.  
  40. // Special case for a simple path URL
  41. const simplePathPattern = /^(\/\/?(?!\/)[^\?\s]*)(\?[^\s]*)?$/;
  42.  
  43. const hostnameMaxLen = 255;
  44. // protocols that can allow "unsafe" and "unwise" chars.
  45. const unsafeProtocol = {
  46.   'javascript': true,
  47.   'javascript:': true
  48. };
  49. // protocols that never have a hostname.
  50. const hostlessProtocol = {
  51.   'javascript': true,
  52.   'javascript:': true
  53. };
  54. // protocols that always contain a // bit.
  55. const slashedProtocol = {
  56.   'http': true,
  57.   'http:': true,
  58.   'https': true,
  59.   'https:': true,
  60.   'ftp': true,
  61.   'ftp:': true,
  62.   'gopher': true,
  63.   'gopher:': true,
  64.   'file': true,
  65.   'file:': true
  66. };
  67. const querystring = require('querystring');
  68.  
  69. /* istanbul ignore next: improve coverage */
  70. function urlParse(url, parseQueryString, slashesDenoteHost) {
  71.   if (url instanceof Url) return url;
  72.  
  73.   var u = new Url();
  74.   u.parse(url, parseQueryString, slashesDenoteHost);
  75.   return u;
  76. }
  77.  
  78. /* istanbul ignore next: improve coverage */
  79. Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) {
  80.   if (typeof url !== 'string') {
  81.     throw new TypeError('Parameter "url" must be a string, not ' + typeof url);
  82.   }
  83.  
  84.   // Copy chrome, IE, opera backslash-handling behavior.
  85.   // Back slashes before the query string get converted to forward slashes
  86.   // See: https://code.google.com/p/chromium/issues/detail?id=25916
  87.   var hasHash = false;
  88.   var start = -1;
  89.   var end = -1;
  90.   var rest = '';
  91.   var lastPos = 0;
  92.   var i = 0;
  93.   for (var inWs = false, split = false; i < url.length; ++i) {
  94.     const code = url.charCodeAt(i);
  95.  
  96.     // Find first and last non-whitespace characters for trimming
  97.     const isWs = code === 32/* */ ||
  98.                  code === 9/*\t*/ ||
  99.                  code === 13/*\r*/ ||
  100.                  code === 10/*\n*/ ||
  101.                  code === 12/*\f*/ ||
  102.                  code === 160/*\u00A0*/ ||
  103.                  code === 65279/*\uFEFF*/;
  104.     if (start === -1) {
  105.       if (isWs)
  106.         continue;
  107.       lastPos = start = i;
  108.     } else {
  109.       if (inWs) {
  110.         if (!isWs) {
  111.           end = -1;
  112.           inWs = false;
  113.         }
  114.       } else if (isWs) {
  115.         end = i;
  116.         inWs = true;
  117.       }
  118.     }
  119.  
  120.     // Only convert backslashes while we haven't seen a split character
  121.     if (!split) {
  122.       switch (code) {
  123.       case 35: // '#'
  124.         hasHash = true;
  125.         // Fall through
  126.       case 63: // '?'
  127.         split = true;
  128.         break;
  129.       case 92: // '\\'
  130.         if (i - lastPos > 0)
  131.           rest += url.slice(lastPos, i);
  132.         rest += '/';
  133.         lastPos = i + 1;
  134.         break;
  135.       }
  136.     } else if (!hasHash && code === 35/*#*/) {
  137.       hasHash = true;
  138.     }
  139.   }
  140.  
  141.   // Check if string was non-empty (including strings with only whitespace)
  142.   if (start !== -1) {
  143.     if (lastPos === start) {
  144.       // We didn't convert any backslashes
  145.  
  146.       if (end === -1) {
  147.         if (start === 0)
  148.           rest = url;
  149.         else
  150.           rest = url.slice(start);
  151.       } else {
  152.         rest = url.slice(start, end);
  153.       }
  154.     } else if (end === -1 && lastPos < url.length) {
  155.       // We converted some backslashes and have only part of the entire string
  156.       rest += url.slice(lastPos);
  157.     } else if (end !== -1 && lastPos < end) {
  158.       // We converted some backslashes and have only part of the entire string
  159.       rest += url.slice(lastPos, end);
  160.     }
  161.   }
  162.  
  163.   if (!slashesDenoteHost && !hasHash) {
  164.     // Try fast path regexp
  165.     const simplePath = simplePathPattern.exec(rest);
  166.     if (simplePath) {
  167.       this.path = rest;
  168.       this.href = rest;
  169.       this.pathname = simplePath[1];
  170.       if (simplePath[2]) {
  171.         this.search = simplePath[2];
  172.         if (parseQueryString) {
  173.           this.query = querystring.parse(this.search.slice(1));
  174.         } else {
  175.           this.query = this.search.slice(1);
  176.         }
  177.       } else if (parseQueryString) {
  178.         this.search = '';
  179.         this.query = {};
  180.       }
  181.       return this;
  182.     }
  183.   }
  184.  
  185.   var proto = protocolPattern.exec(rest);
  186.   if (proto) {
  187.     proto = proto[0];
  188.     var lowerProto = proto.toLowerCase();
  189.     this.protocol = lowerProto;
  190.     rest = rest.slice(proto.length);
  191.   }
  192.  
  193.   // figure out if it's got a host
  194.   // user@server is *always* interpreted as a hostname, and url
  195.   // resolution will treat //foo/bar as host=foo,path=bar because that's
  196.   // how the browser resolves relative URLs.
  197.   if (slashesDenoteHost || proto || /^\/\/[^@\/]+@[^@\/]+/.test(rest)) {
  198.     var slashes = rest.charCodeAt(0) === 47/*/*/ &&
  199.                   rest.charCodeAt(1) === 47/*/*/;
  200.     if (slashes && !(proto && hostlessProtocol[proto])) {
  201.       rest = rest.slice(2);
  202.       this.slashes = true;
  203.     }
  204.   }
  205.  
  206.   if (!hostlessProtocol[proto] &&
  207.       (slashes || (proto && !slashedProtocol[proto]))) {
  208.  
  209.     // there's a hostname.
  210.     // the first instance of /, ?, ;, or # ends the host.
  211.     //
  212.     // If there is an @ in the hostname, then non-host chars *are* allowed
  213.     // to the left of the last @ sign, unless some host-ending character
  214.     // comes *before* the @-sign.
  215.     // URLs are obnoxious.
  216.     //
  217.     // ex:
  218.     // http://a@b@c/ => user:a@b host:c
  219.     // http://a@b?@c => user:a host:b path:/?@c
  220.  
  221.     // v0.12 TODO(isaacs): This is not quite how Chrome does things.
  222.     // Review our test case against browsers more comprehensively.
  223.  
  224.     var hostEnd = -1;
  225.     var atSign = -1;
  226.     var nonHost = -1;
  227.     for (i = 0; i < rest.length; ++i) {
  228.       switch (rest.charCodeAt(i)) {
  229.       case 9:   // '\t'
  230.       case 10:  // '\n'
  231.       case 13:  // '\r'
  232.       case 32:  // ' '
  233.       case 34:  // '"'
  234.       case 37:  // '%'
  235.       case 39:  // '\''
  236.       case 59:  // ';'
  237.       case 60:  // '<'
  238.       case 62:  // '>'
  239.       case 92:  // '\\'
  240.       case 94:  // '^'
  241.       case 96:  // '`'
  242.       case 123: // '{'
  243.       case 124: // '|'
  244.       case 125: // '}'
  245.           // Characters that are never ever allowed in a hostname from RFC 2396
  246.         if (nonHost === -1)
  247.           nonHost = i;
  248.         break;
  249.       case 35: // '#'
  250.       case 47: // '/'
  251.       case 63: // '?'
  252.           // Find the first instance of any host-ending characters
  253.         if (nonHost === -1)
  254.           nonHost = i;
  255.         hostEnd = i;
  256.         break;
  257.       case 64: // '@'
  258.           // At this point, either we have an explicit point where the
  259.           // auth portion cannot go past, or the last @ char is the decider.
  260.         atSign = i;
  261.         nonHost = -1;
  262.         break;
  263.       }
  264.       if (hostEnd !== -1)
  265.         break;
  266.     }
  267.     start = 0;
  268.     if (atSign !== -1) {
  269.       this.auth = decodeURIComponent(rest.slice(0, atSign));
  270.       start = atSign + 1;
  271.     }
  272.     if (nonHost === -1) {
  273.       this.host = rest.slice(start);
  274.       rest = '';
  275.     } else {
  276.       this.host = rest.slice(start, nonHost);
  277.       rest = rest.slice(nonHost);
  278.     }
  279.  
  280.     // pull out port.
  281.     this.parseHost();
  282.  
  283.     // we've indicated that there is a hostname,
  284.     // so even if it's empty, it has to be present.
  285.     if (typeof this.hostname !== 'string')
  286.       this.hostname = '';
  287.  
  288.     var hostname = this.hostname;
  289.  
  290.     // if hostname begins with [ and ends with ]
  291.     // assume that it's an IPv6 address.
  292.     var ipv6Hostname = hostname.charCodeAt(0) === 91/*[*/ &&
  293.                        hostname.charCodeAt(hostname.length - 1) === 93/*]*/;
  294.  
  295.     // validate a little.
  296.     if (!ipv6Hostname) {
  297.       const result = validateHostname(this, rest, hostname);
  298.       if (result !== undefined)
  299.         rest = result;
  300.     }
  301.  
  302.     if (this.hostname.length > hostnameMaxLen) {
  303.       this.hostname = '';
  304.     } else {
  305.       // hostnames are always lower case.
  306.       this.hostname = this.hostname.toLowerCase();
  307.     }
  308.  
  309.     if (!ipv6Hostname) {
  310.       // IDNA Support: Returns a punycoded representation of "domain".
  311.       // It only converts parts of the domain name that
  312.       // have non-ASCII characters, i.e. it doesn't matter if
  313.       // you call it with a domain that already is ASCII-only.
  314.       this.hostname = punycode.toASCII(this.hostname);
  315.     }
  316.  
  317.     var p = this.port ? ':' + this.port : '';
  318.     var h = this.hostname || '';
  319.     this.host = h + p;
  320.  
  321.     // strip [ and ] from the hostname
  322.     // the host field still retains them, though
  323.     if (ipv6Hostname) {
  324.       this.hostname = this.hostname.slice(1, -1);
  325.       if (rest[0] !== '/') {
  326.         rest = '/' + rest;
  327.       }
  328.     }
  329.   }
  330.  
  331.   // now rest is set to the post-host stuff.
  332.   // chop off any delim chars.
  333.   if (!unsafeProtocol[lowerProto]) {
  334.     // First, make 100% sure that any "autoEscape" chars get
  335.     // escaped, even if encodeURIComponent doesn't think they
  336.     // need to be.
  337.     const result = autoEscapeStr(rest);
  338.     if (result !== undefined)
  339.       rest = result;
  340.   }
  341.  
  342.   var questionIdx = -1;
  343.   var hashIdx = -1;
  344.   for (i = 0; i < rest.length; ++i) {
  345.     const code = rest.charCodeAt(i);
  346.     if (code === 35/*#*/) {
  347.       this.hash = rest.slice(i);
  348.       hashIdx = i;
  349.       break;
  350.     } else if (code === 63/*?*/ && questionIdx === -1) {
  351.       questionIdx = i;
  352.     }
  353.   }
  354.  
  355.   if (questionIdx !== -1) {
  356.     if (hashIdx === -1) {
  357.       this.search = rest.slice(questionIdx);
  358.       this.query = rest.slice(questionIdx + 1);
  359.     } else {
  360.       this.search = rest.slice(questionIdx, hashIdx);
  361.       this.query = rest.slice(questionIdx + 1, hashIdx);
  362.     }
  363.     if (parseQueryString) {
  364.       this.query = querystring.parse(this.query);
  365.     }
  366.   } else if (parseQueryString) {
  367.     // no query string, but parseQueryString still requested
  368.     this.search = '';
  369.     this.query = {};
  370.   }
  371.  
  372.   var firstIdx = (questionIdx !== -1 &&
  373.                   (hashIdx === -1 || questionIdx < hashIdx)
  374.                   ? questionIdx
  375.                   : hashIdx);
  376.   if (firstIdx === -1) {
  377.     if (rest.length > 0)
  378.       this.pathname = rest;
  379.   } else if (firstIdx > 0) {
  380.     this.pathname = rest.slice(0, firstIdx);
  381.   }
  382.   if (slashedProtocol[lowerProto] &&
  383.       this.hostname && !this.pathname) {
  384.     this.pathname = '/';
  385.   }
  386.  
  387.   // to support http.request
  388.   if (this.pathname || this.search) {
  389.     const p = this.pathname || '';
  390.     const s = this.search || '';
  391.     this.path = p + s;
  392.   }
  393.  
  394.   // finally, reconstruct the href based on what has been validated.
  395.   this.href = this.format();
  396.   return this;
  397. };
  398.  
  399. /* istanbul ignore next: improve coverage */
  400. function validateHostname(self, rest, hostname) {
  401.   for (var i = 0, lastPos; i <= hostname.length; ++i) {
  402.     var code;
  403.     if (i < hostname.length)
  404.       code = hostname.charCodeAt(i);
  405.     if (code === 46/*.*/ || i === hostname.length) {
  406.       if (i - lastPos > 0) {
  407.         if (i - lastPos > 63) {
  408.           self.hostname = hostname.slice(0, lastPos + 63);
  409.           return '/' + hostname.slice(lastPos + 63) + rest;
  410.         }
  411.       }
  412.       lastPos = i + 1;
  413.       continue;
  414.     } else if ((code >= 48/*0*/ && code <= 57/*9*/) ||
  415.                (code >= 97/*a*/ && code <= 122/*z*/) ||
  416.                code === 45/*-*/ ||
  417.                (code >= 65/*A*/ && code <= 90/*Z*/) ||
  418.                code === 43/*+*/ ||
  419.                code === 95/*_*/ ||
  420.                /* BEGIN MONGO URI PATCH */
  421.                code === 44/*,*/ ||
  422.                code === 58/*:*/ ||
  423.                /* END MONGO URI PATCH */
  424.                code > 127) {
  425.       continue;
  426.     }
  427.     // Invalid host character
  428.     self.hostname = hostname.slice(0, i);
  429.     if (i < hostname.length)
  430.       return '/' + hostname.slice(i) + rest;
  431.     break;
  432.   }
  433. }
  434.  
  435. /* istanbul ignore next: improve coverage */
  436. function autoEscapeStr(rest) {
  437.   var newRest = '';
  438.   var lastPos = 0;
  439.   for (var i = 0; i < rest.length; ++i) {
  440.     // Automatically escape all delimiters and unwise characters from RFC 2396
  441.     // Also escape single quotes in case of an XSS attack
  442.     switch (rest.charCodeAt(i)) {
  443.     case 9:   // '\t'
  444.       if (i - lastPos > 0)
  445.         newRest += rest.slice(lastPos, i);
  446.       newRest += '%09';
  447.       lastPos = i + 1;
  448.       break;
  449.     case 10:  // '\n'
  450.       if (i - lastPos > 0)
  451.         newRest += rest.slice(lastPos, i);
  452.       newRest += '%0A';
  453.       lastPos = i + 1;
  454.       break;
  455.     case 13:  // '\r'
  456.       if (i - lastPos > 0)
  457.         newRest += rest.slice(lastPos, i);
  458.       newRest += '%0D';
  459.       lastPos = i + 1;
  460.       break;
  461.     case 32:  // ' '
  462.       if (i - lastPos > 0)
  463.         newRest += rest.slice(lastPos, i);
  464.       newRest += '%20';
  465.       lastPos = i + 1;
  466.       break;
  467.     case 34:  // '"'
  468.       if (i - lastPos > 0)
  469.         newRest += rest.slice(lastPos, i);
  470.       newRest += '%22';
  471.       lastPos = i + 1;
  472.       break;
  473.     case 39:  // '\''
  474.       if (i - lastPos > 0)
  475.         newRest += rest.slice(lastPos, i);
  476.       newRest += '%27';
  477.       lastPos = i + 1;
  478.       break;
  479.     case 60:  // '<'
  480.       if (i - lastPos > 0)
  481.         newRest += rest.slice(lastPos, i);
  482.       newRest += '%3C';
  483.       lastPos = i + 1;
  484.       break;
  485.     case 62:  // '>'
  486.       if (i - lastPos > 0)
  487.         newRest += rest.slice(lastPos, i);
  488.       newRest += '%3E';
  489.       lastPos = i + 1;
  490.       break;
  491.     case 92:  // '\\'
  492.       if (i - lastPos > 0)
  493.         newRest += rest.slice(lastPos, i);
  494.       newRest += '%5C';
  495.       lastPos = i + 1;
  496.       break;
  497.     case 94:  // '^'
  498.       if (i - lastPos > 0)
  499.         newRest += rest.slice(lastPos, i);
  500.       newRest += '%5E';
  501.       lastPos = i + 1;
  502.       break;
  503.     case 96:  // '`'
  504.       if (i - lastPos > 0)
  505.         newRest += rest.slice(lastPos, i);
  506.       newRest += '%60';
  507.       lastPos = i + 1;
  508.       break;
  509.     case 123: // '{'
  510.       if (i - lastPos > 0)
  511.         newRest += rest.slice(lastPos, i);
  512.       newRest += '%7B';
  513.       lastPos = i + 1;
  514.       break;
  515.     case 124: // '|'
  516.       if (i - lastPos > 0)
  517.         newRest += rest.slice(lastPos, i);
  518.       newRest += '%7C';
  519.       lastPos = i + 1;
  520.       break;
  521.     case 125: // '}'
  522.       if (i - lastPos > 0)
  523.         newRest += rest.slice(lastPos, i);
  524.       newRest += '%7D';
  525.       lastPos = i + 1;
  526.       break;
  527.     }
  528.   }
  529.   if (lastPos === 0)
  530.     return;
  531.   if (lastPos < rest.length)
  532.     return newRest + rest.slice(lastPos);
  533.   else
  534.     return newRest;
  535. }
  536.  
  537. // format a parsed object into a url string
  538. /* istanbul ignore next: improve coverage */
  539. function urlFormat(obj) {
  540.   // ensure it's an object, and not a string url.
  541.   // If it's an obj, this is a no-op.
  542.   // this way, you can call url_format() on strings
  543.   // to clean up potentially wonky urls.
  544.   if (typeof obj === 'string') obj = urlParse(obj);
  545.  
  546.   else if (typeof obj !== 'object' || obj === null)
  547.     throw new TypeError('Parameter "urlObj" must be an object, not ' +
  548.                         obj === null ? 'null' : typeof obj);
  549.  
  550.   else if (!(obj instanceof Url)) return Url.prototype.format.call(obj);
  551.  
  552.   return obj.format();
  553. }
  554.  
  555. /* istanbul ignore next: improve coverage */
  556. Url.prototype.format = function() {
  557.   var auth = this.auth || '';
  558.   if (auth) {
  559.     auth = encodeAuth(auth);
  560.     auth += '@';
  561.   }
  562.  
  563.   var protocol = this.protocol || '';
  564.   var pathname = this.pathname || '';
  565.   var hash = this.hash || '';
  566.   var host = false;
  567.   var query = '';
  568.  
  569.   if (this.host) {
  570.     host = auth + this.host;
  571.   } else if (this.hostname) {
  572.     host = auth + (this.hostname.indexOf(':') === -1 ?
  573.         this.hostname :
  574.         '[' + this.hostname + ']');
  575.     if (this.port) {
  576.       host += ':' + this.port;
  577.     }
  578.   }
  579.  
  580.   if (this.query !== null && typeof this.query === 'object')
  581.     query = querystring.stringify(this.query);
  582.  
  583.   var search = this.search || (query && ('?' + query)) || '';
  584.  
  585.   if (protocol && protocol.charCodeAt(protocol.length - 1) !== 58/*:*/)
  586.     protocol += ':';
  587.  
  588.   var newPathname = '';
  589.   var lastPos = 0;
  590.   for (var i = 0; i < pathname.length; ++i) {
  591.     switch (pathname.charCodeAt(i)) {
  592.     case 35: // '#'
  593.       if (i - lastPos > 0)
  594.         newPathname += pathname.slice(lastPos, i);
  595.       newPathname += '%23';
  596.       lastPos = i + 1;
  597.       break;
  598.     case 63: // '?'
  599.       if (i - lastPos > 0)
  600.         newPathname += pathname.slice(lastPos, i);
  601.       newPathname += '%3F';
  602.       lastPos = i + 1;
  603.       break;
  604.     }
  605.   }
  606.   if (lastPos > 0) {
  607.     if (lastPos !== pathname.length)
  608.       pathname = newPathname + pathname.slice(lastPos);
  609.     else
  610.       pathname = newPathname;
  611.   }
  612.  
  613.   // only the slashedProtocols get the //.  Not mailto:, xmpp:, etc.
  614.   // unless they had them to begin with.
  615.   if (this.slashes ||
  616.       (!protocol || slashedProtocol[protocol]) && host !== false) {
  617.     host = '//' + (host || '');
  618.     if (pathname && pathname.charCodeAt(0) !== 47/*/*/)
  619.       pathname = '/' + pathname;
  620.   } else if (!host) {
  621.     host = '';
  622.   }
  623.  
  624.   search = search.replace('#', '%23');
  625.  
  626.   if (hash && hash.charCodeAt(0) !== 35/*#*/) hash = '#' + hash;
  627.   if (search && search.charCodeAt(0) !== 63/*?*/) search = '?' + search;
  628.  
  629.   return protocol + host + pathname + search + hash;
  630. };
  631.  
  632. /* istanbul ignore next: improve coverage */
  633. function urlResolve(source, relative) {
  634.   return urlParse(source, false, true).resolve(relative);
  635. }
  636.  
  637. /* istanbul ignore next: improve coverage */
  638. Url.prototype.resolve = function(relative) {
  639.   return this.resolveObject(urlParse(relative, false, true)).format();
  640. };
  641.  
  642. /* istanbul ignore next: improve coverage */
  643. function urlResolveObject(source, relative) {
  644.   if (!source) return relative;
  645.   return urlParse(source, false, true).resolveObject(relative);
  646. }
  647.  
  648. /* istanbul ignore next: improve coverage */
  649. Url.prototype.resolveObject = function(relative) {
  650.   if (typeof relative === 'string') {
  651.     var rel = new Url();
  652.     rel.parse(relative, false, true);
  653.     relative = rel;
  654.   }
  655.  
  656.   var result = new Url();
  657.   var tkeys = Object.keys(this);
  658.   for (var tk = 0; tk < tkeys.length; tk++) {
  659.     var tkey = tkeys[tk];
  660.     result[tkey] = this[tkey];
  661.   }
  662.  
  663.   // hash is always overridden, no matter what.
  664.   // even href="" will remove it.
  665.   result.hash = relative.hash;
  666.  
  667.   // if the relative url is empty, then there's nothing left to do here.
  668.   if (relative.href === '') {
  669.     result.href = result.format();
  670.     return result;
  671.   }
  672.  
  673.   // hrefs like //foo/bar always cut to the protocol.
  674.   if (relative.slashes && !relative.protocol) {
  675.     // take everything except the protocol from relative
  676.     var rkeys = Object.keys(relative);
  677.     for (var rk = 0; rk < rkeys.length; rk++) {
  678.       var rkey = rkeys[rk];
  679.       if (rkey !== 'protocol')
  680.         result[rkey] = relative[rkey];
  681.     }
  682.  
  683.     //urlParse appends trailing / to urls like http://www.example.com
  684.     if (slashedProtocol[result.protocol] &&
  685.         result.hostname && !result.pathname) {
  686.       result.path = result.pathname = '/';
  687.     }
  688.  
  689.     result.href = result.format();
  690.     return result;
  691.   }
  692.  
  693.   if (relative.protocol && relative.protocol !== result.protocol) {
  694.     // if it's a known url protocol, then changing
  695.     // the protocol does weird things
  696.     // first, if it's not file:, then we MUST have a host,
  697.     // and if there was a path
  698.     // to begin with, then we MUST have a path.
  699.     // if it is file:, then the host is dropped,
  700.     // because that's known to be hostless.
  701.     // anything else is assumed to be absolute.
  702.     if (!slashedProtocol[relative.protocol]) {
  703.       var keys = Object.keys(relative);
  704.       for (var v = 0; v < keys.length; v++) {
  705.         var k = keys[v];
  706.         result[k] = relative[k];
  707.       }
  708.       result.href = result.format();
  709.       return result;
  710.     }
  711.  
  712.     result.protocol = relative.protocol;
  713.     if (!relative.host &&
  714.         !/^file:?$/.test(relative.protocol) &&
  715.         !hostlessProtocol[relative.protocol]) {
  716.       const relPath = (relative.pathname || '').split('/');
  717.       while (relPath.length && !(relative.host = relPath.shift()));
  718.       if (!relative.host) relative.host = '';
  719.       if (!relative.hostname) relative.hostname = '';
  720.       if (relPath[0] !== '') relPath.unshift('');
  721.       if (relPath.length < 2) relPath.unshift('');
  722.       result.pathname = relPath.join('/');
  723.     } else {
  724.       result.pathname = relative.pathname;
  725.     }
  726.     result.search = relative.search;
  727.     result.query = relative.query;
  728.     result.host = relative.host || '';
  729.     result.auth = relative.auth;
  730.     result.hostname = relative.hostname || relative.host;
  731.     result.port = relative.port;
  732.     // to support http.request
  733.     if (result.pathname || result.search) {
  734.       var p = result.pathname || '';
  735.       var s = result.search || '';
  736.       result.path = p + s;
  737.     }
  738.     result.slashes = result.slashes || relative.slashes;
  739.     result.href = result.format();
  740.     return result;
  741.   }
  742.  
  743.   var isSourceAbs = (result.pathname && result.pathname.charAt(0) === '/');
  744.   var isRelAbs = (
  745.       relative.host ||
  746.       relative.pathname && relative.pathname.charAt(0) === '/'
  747.   );
  748.   var mustEndAbs = (isRelAbs || isSourceAbs ||
  749.                     (result.host && relative.pathname));
  750.   var removeAllDots = mustEndAbs;
  751.   var srcPath = result.pathname && result.pathname.split('/') || [];
  752.   var relPath = relative.pathname && relative.pathname.split('/') || [];
  753.   var psychotic = result.protocol && !slashedProtocol[result.protocol];
  754.  
  755.   // if the url is a non-slashed url, then relative
  756.   // links like ../.. should be able
  757.   // to crawl up to the hostname, as well.  This is strange.
  758.   // result.protocol has already been set by now.
  759.   // Later on, put the first path part into the host field.
  760.   if (psychotic) {
  761.     result.hostname = '';
  762.     result.port = null;
  763.     if (result.host) {
  764.       if (srcPath[0] === '') srcPath[0] = result.host;
  765.       else srcPath.unshift(result.host);
  766.     }
  767.     result.host = '';
  768.     if (relative.protocol) {
  769.       relative.hostname = null;
  770.       relative.port = null;
  771.       if (relative.host) {
  772.         if (relPath[0] === '') relPath[0] = relative.host;
  773.         else relPath.unshift(relative.host);
  774.       }
  775.       relative.host = null;
  776.     }
  777.     mustEndAbs = mustEndAbs && (relPath[0] === '' || srcPath[0] === '');
  778.   }
  779.  
  780.   if (isRelAbs) {
  781.     // it's absolute.
  782.     result.host = (relative.host || relative.host === '') ?
  783.                   relative.host : result.host;
  784.     result.hostname = (relative.hostname || relative.hostname === '') ?
  785.                       relative.hostname : result.hostname;
  786.     result.search = relative.search;
  787.     result.query = relative.query;
  788.     srcPath = relPath;
  789.     // fall through to the dot-handling below.
  790.   } else if (relPath.length) {
  791.     // it's relative
  792.     // throw away the existing file, and take the new path instead.
  793.     if (!srcPath) srcPath = [];
  794.     srcPath.pop();
  795.     srcPath = srcPath.concat(relPath);
  796.     result.search = relative.search;
  797.     result.query = relative.query;
  798.   } else if (relative.search !== null && relative.search !== undefined) {
  799.     // just pull out the search.
  800.     // like href='?foo'.
  801.     // Put this after the other two cases because it simplifies the booleans
  802.     if (psychotic) {
  803.       result.hostname = result.host = srcPath.shift();
  804.       //occasionally the auth can get stuck only in host
  805.       //this especially happens in cases like
  806.       //url.resolveObject('mailto:local1@domain1', 'local2@domain2')
  807.       const authInHost = result.host && result.host.indexOf('@') > 0 ?
  808.                        result.host.split('@') : false;
  809.       if (authInHost) {
  810.         result.auth = authInHost.shift();
  811.         result.host = result.hostname = authInHost.shift();
  812.       }
  813.     }
  814.     result.search = relative.search;
  815.     result.query = relative.query;
  816.     //to support http.request
  817.     if (result.pathname !== null || result.search !== null) {
  818.       result.path = (result.pathname ? result.pathname : '') +
  819.                     (result.search ? result.search : '');
  820.     }
  821.     result.href = result.format();
  822.     return result;
  823.   }
  824.  
  825.   if (!srcPath.length) {
  826.     // no path at all.  easy.
  827.     // we've already handled the other stuff above.
  828.     result.pathname = null;
  829.     //to support http.request
  830.     if (result.search) {
  831.       result.path = '/' + result.search;
  832.     } else {
  833.       result.path = null;
  834.     }
  835.     result.href = result.format();
  836.     return result;
  837.   }
  838.  
  839.   // if a url ENDs in . or .., then it must get a trailing slash.
  840.   // however, if it ends in anything else non-slashy,
  841.   // then it must NOT get a trailing slash.
  842.   var last = srcPath.slice(-1)[0];
  843.   var hasTrailingSlash = (
  844.       (result.host || relative.host || srcPath.length > 1) &&
  845.       (last === '.' || last === '..') || last === '');
  846.  
  847.   // strip single dots, resolve double dots to parent dir
  848.   // if the path tries to go above the root, `up` ends up > 0
  849.   var up = 0;
  850.   for (var i = srcPath.length; i >= 0; i--) {
  851.     last = srcPath[i];
  852.     if (last === '.') {
  853.       spliceOne(srcPath, i);
  854.     } else if (last === '..') {
  855.       spliceOne(srcPath, i);
  856.       up++;
  857.     } else if (up) {
  858.       spliceOne(srcPath, i);
  859.       up--;
  860.     }
  861.   }
  862.  
  863.   // if the path is allowed to go above the root, restore leading ..s
  864.   if (!mustEndAbs && !removeAllDots) {
  865.     for (; up--; up) {
  866.       srcPath.unshift('..');
  867.     }
  868.   }
  869.  
  870.   if (mustEndAbs && srcPath[0] !== '' &&
  871.       (!srcPath[0] || srcPath[0].charAt(0) !== '/')) {
  872.     srcPath.unshift('');
  873.   }
  874.  
  875.   if (hasTrailingSlash && (srcPath.join('/').substr(-1) !== '/')) {
  876.     srcPath.push('');
  877.   }
  878.  
  879.   var isAbsolute = srcPath[0] === '' ||
  880.       (srcPath[0] && srcPath[0].charAt(0) === '/');
  881.  
  882.   // put the host back
  883.   if (psychotic) {
  884.     result.hostname = result.host = isAbsolute ? '' :
  885.                                     srcPath.length ? srcPath.shift() : '';
  886.     //occasionally the auth can get stuck only in host
  887.     //this especially happens in cases like
  888.     //url.resolveObject('mailto:local1@domain1', 'local2@domain2')
  889.     const authInHost = result.host && result.host.indexOf('@') > 0 ?
  890.                      result.host.split('@') : false;
  891.     if (authInHost) {
  892.       result.auth = authInHost.shift();
  893.       result.host = result.hostname = authInHost.shift();
  894.     }
  895.   }
  896.  
  897.   mustEndAbs = mustEndAbs || (result.host && srcPath.length);
  898.  
  899.   if (mustEndAbs && !isAbsolute) {
  900.     srcPath.unshift('');
  901.   }
  902.  
  903.   if (!srcPath.length) {
  904.     result.pathname = null;
  905.     result.path = null;
  906.   } else {
  907.     result.pathname = srcPath.join('/');
  908.   }
  909.  
  910.   //to support request.http
  911.   if (result.pathname !== null || result.search !== null) {
  912.     result.path = (result.pathname ? result.pathname : '') +
  913.                   (result.search ? result.search : '');
  914.   }
  915.   result.auth = relative.auth || result.auth;
  916.   result.slashes = result.slashes || relative.slashes;
  917.   result.href = result.format();
  918.   return result;
  919. };
  920.  
  921. /* istanbul ignore next: improve coverage */
  922. Url.prototype.parseHost = function() {
  923.   var host = this.host;
  924.   var port = portPattern.exec(host);
  925.   if (port) {
  926.     port = port[0];
  927.     if (port !== ':') {
  928.       this.port = port.slice(1);
  929.     }
  930.     host = host.slice(0, host.length - port.length);
  931.   }
  932.   if (host) this.hostname = host;
  933. };
  934.  
  935. // About 1.5x faster than the two-arg version of Array#splice().
  936. /* istanbul ignore next: improve coverage */
  937. function spliceOne(list, index) {
  938.   for (var i = index, k = i + 1, n = list.length; k < n; i += 1, k += 1)
  939.     list[i] = list[k];
  940.   list.pop();
  941. }
  942.  
  943. var hexTable = new Array(256);
  944. for (var i = 0; i < 256; ++i)
  945.   hexTable[i] = '%' + ((i < 16 ? '0' : '') + i.toString(16)).toUpperCase();
  946. /* istanbul ignore next: improve coverage */
  947. function encodeAuth(str) {
  948.   // faster encodeURIComponent alternative for encoding auth uri components
  949.   var out = '';
  950.   var lastPos = 0;
  951.   for (var i = 0; i < str.length; ++i) {
  952.     var c = str.charCodeAt(i);
  953.  
  954.     // These characters do not need escaping:
  955.     // ! - . _ ~
  956.     // ' ( ) * :
  957.     // digits
  958.     // alpha (uppercase)
  959.     // alpha (lowercase)
  960.     if (c === 0x21 || c === 0x2D || c === 0x2E || c === 0x5F || c === 0x7E ||
  961.         (c >= 0x27 && c <= 0x2A) ||
  962.         (c >= 0x30 && c <= 0x3A) ||
  963.         (c >= 0x41 && c <= 0x5A) ||
  964.         (c >= 0x61 && c <= 0x7A)) {
  965.       continue;
  966.     }
  967.  
  968.     if (i - lastPos > 0)
  969.       out += str.slice(lastPos, i);
  970.  
  971.     lastPos = i + 1;
  972.  
  973.     // Other ASCII characters
  974.     if (c < 0x80) {
  975.       out += hexTable[c];
  976.       continue;
  977.     }
  978.  
  979.     // Multi-byte characters ...
  980.     if (c < 0x800) {
  981.       out += hexTable[0xC0 | (c >> 6)] + hexTable[0x80 | (c & 0x3F)];
  982.       continue;
  983.     }
  984.     if (c < 0xD800 || c >= 0xE000) {
  985.       out += hexTable[0xE0 | (c >> 12)] +
  986.              hexTable[0x80 | ((c >> 6) & 0x3F)] +
  987.              hexTable[0x80 | (c & 0x3F)];
  988.       continue;
  989.     }
  990.     // Surrogate pair
  991.     ++i;
  992.     var c2;
  993.     if (i < str.length)
  994.       c2 = str.charCodeAt(i) & 0x3FF;
  995.     else
  996.       c2 = 0;
  997.     c = 0x10000 + (((c & 0x3FF) << 10) | c2);
  998.     out += hexTable[0xF0 | (c >> 18)] +
  999.            hexTable[0x80 | ((c >> 12) & 0x3F)] +
  1000.            hexTable[0x80 | ((c >> 6) & 0x3F)] +
  1001.            hexTable[0x80 | (c & 0x3F)];
  1002.   }
  1003.   if (lastPos === 0)
  1004.     return str;
  1005.   if (lastPos < str.length)
  1006.     return out + str.slice(lastPos);
  1007.   return out;
  1008. }
  1009.  
downloadmongodbUrl.js Source code - Download parse-server Source code
Related Source Codes/Software:
react-boilerplate - 2017-06-07
webtorrent - Streaming torrent client for the web ... 2017-06-06
machine-learning-for-software-engineers - A complete daily plan for studying to become a mac... 2017-06-06
upterm - A terminal emulator for the 21st century. 2017-06-06
lottie-android - Render After Effects animations natively on Androi... 2017-06-07
AsyncDisplayKit - Smooth asynchronous user interfaces for iOS apps. ... 2017-06-07
ionicons - The premium icon font for Ionic ... 2017-06-07
storybook - 2017-06-07
prettier - Prettier is an opinionated JavaScript formatter. ... 2017-06-08
CRYENGINE - CRYENGINE is a powerful real-time game development... 2017-06-11
postal - 2017-06-11
reactide - Reactide is the first dedicated IDE for React web ... 2017-06-11
rkt - rkt is a pod-native container engine for Linux. It... 2017-06-11
uWebSockets - Tiny WebSockets https://for... 2017-06-11
realworld - TodoMVC for the RealWorld - Exemplary fullstack Me... 2017-06-11
goreplay - GoReplay is an open-source tool for capturing and ... 2017-06-10
pyenv - Simple Python version management 2017-06-10
redux-saga - An alternative side effect model for Redux apps ... 2017-06-10
angular-starter - 2017-06-10

 Back to top