function request(url, options, callback) { if (!callback) return request(url, {}, options); if (typeof options == "string") return request(url, {method: options}, callback); var method = options.method || "GET"; var headers = options.headers || {}; var body = options.body || ""; var contentType = options.contentType || "application/x-www-form-urlencoded; charset=UTF-8"; var timeout = options.hasOwnProperty("timeout") ? options.timeout : 10000; var async = options.sync !== true; var parsedUrl = parseUrl(url, options.query); if (contentType === "application/json") headers.Accept = headers.Accept || "application/json"; if (options.username) { headers.Authorization = "Basic " + btoa(options.username + ":" + options.password); } var xhr = new XHR(); if (options.overrideMimeType) xhr.overrideMimeType = options.overrideMimeType; // From MDN: Note: You need to add the event listeners before // calling open() on the request. Otherwise the progress events // will not fire. if (options.progress) { var obj = method == "PUT" ? xhr.upload : xhr; obj.onprogress = function(e) { if (e.lengthComputable) options.progress(e.loaded, e.total); }; } xhr.open(method, URL.format(parsedUrl), async); headers["Content-Type"] = contentType; for (var header in headers) xhr.setRequestHeader(header, headers[header]); // encode body if (typeof body == "object") { if (contentType.indexOf("application/json") === 0) { try { body = JSON.stringify(body); } catch (e) { return done(new Error("Could not serialize body as json")); } } else if (contentType.indexOf("application/x-www-form-urlencoded") === 0) { body = qs.stringify(body); } else if (["[object File]", "[object Blob]"].indexOf(Object.prototype.toString.call(body)) > -1) { // pass as is xhr.overrideMimeType = body.type; } else { body = body.toString(); } } var timer; var timedout = false; if (timeout) { timer = setTimeout(function() { timedout = true; xhr.abort(); var err = new Error("Timeout"); err.code = "ETIMEOUT"; done(err); }, timeout); } xhr.send(body || ""); var abort = xhr.abort; xhr.abort = function(){ clearTimeout(timer); abort.call(xhr); }; xhr.onload = function(e) { var res = { body: xhr.responseText, status: xhr.status, headers: parseHeaders(xhr.getAllResponseHeaders()) }; var data = xhr.responseText; if ((options.overrideMimeType || res.headers["content-type"]) .indexOf("application/json") === 0 ) { try { data = JSON.parse(data); } catch (e) { return done(e); } } if (this.status > 299) { var err = new Error(xhr.responseText); err.code = xhr.status; if (debug) console.error("HTTP error " + this.status + ": " + xhr.responseText); return done(err, data, res); } done(null, data, res); }; xhr.onerror = function(e) { if (typeof XMLHttpRequestProgressEvent == "function" && e instanceof XMLHttpRequestProgressEvent) { // No useful information in this object. // Possibly CORS error if code was 0. var err = new Error("Failed to retrieve resource from " + parsedUrl.host); err.cause = e; err.code = e.target.status; return done(err); } e.code = e.target.status; done(e); }; var called = false; function done(err, data, res) { timer && clearTimeout(timer); if (called) return; called = true; callback(err, data, res); } return xhr; }
const getRegistryNormalizedSlash = (npm)=> url.format(url.parse(npm.getRegistry(npm)))
HttpServer.prototype.parseUrl_ = function(urlString) { var parsed = url.parse(urlString); parsed.pathname = url.resolve('/', parsed.pathname); return url.parse(url.format(parsed), true); };
return self._shouldLoadUserProfile(iss, sub, (shouldLoadUserProfileError, load) => { if (shouldLoadUserProfileError) { return next(shouldLoadUserProfileError); } if (load && self._options._isV2) { log.warn(`Azure v2.0 does not have a 'userinfo' endpoint, we will use the claims in id_token for the profile.`) } else if (load) { // make sure we get an access_token if (!access_token) return self.fail("we want to access userinfo endpoint, but access_token is not received"); let parsedUrl; try { parsedUrl = url.parse(config.userInfoURL, true); } catch (urlParseException) { return next( new InternalOpenIDError( `Failed to parse config property 'userInfoURL' with value ${config.userInfoURL}`, urlParseException ) ); } parsedUrl.query.schema = 'openid'; delete parsedUrl.search; // delete operations are slow; should we rather just overwrite it with {} const userInfoURL = url.format(parsedUrl); // ask oauth2 to use authorization header to bearer access token oauth2.useAuthorizationHeaderforGET(true); return oauth2.get(userInfoURL, access_token, (getUserInfoError, body) => { if (getUserInfoError) { return next(new InternalOAuthError('failed to fetch user profile', getUserInfoError)); } log.info('Profile loaded from MS identity', body); var userinfoReceived = null; // use try / catch around JSON.parse --> could fail unexpectedly try { userinfoReceived = JSON.parse(body); } catch (ex) { return next(ex); } // make sure the 'sub' in userinfo is the same as the one in 'id_token' if (userinfoReceived.sub !== jwtClaims.sub) { log.error('sub in userinfo is ' + userinfoReceived.sub + ', but does not match sub in id_token, which is ' + id_token.sub); return self.fail('sub received in userinfo and id_token do not match'); } return onProfileLoaded(self, { req, sub, iss, profile: makeProfileObject(userinfoReceived, body), jwtClaims, access_token, refresh_token, params, }); }); } // lets do an id_token fallback. We use id_token over userInfo endpoint for now return onProfileLoaded(self, { req, sub, iss, profile: makeProfileObject(jwtClaims, jwtClaimsStr), jwtClaims, access_token, refresh_token, params, }); });
return function(options) { return url_js.format({ query: options, host: this.urls[urlKey] }); }
$.param = function(params) { return url.format({query: params}).substring(1); };
jsonApi._concatenateUrlPrefix = config => url.format({ protocol: config.protocol, hostname: config.hostname, port: config.port, pathname: config.base })
set port(value) { const url = Object.assign(URL.parse(this._url), { port: value }); this.assign(URL.format(url)); }
set protocol(value) { const url = Object.assign(URL.parse(this._url), { protocol: value }); this.assign(URL.format(url)); }
return function() { var args = Array.prototype.slice.call( arguments ); // Parse the arguments into a query parameter object var params = _.reduce( args, function( memo, value, index ) { // Walk through the provided required params, one by one var key = requiredParams[ index ]; // Values are usually strings or numbers, but they may also be an array // of strings (relevant for values like predictionsbyroutes' "routes" // parameter); if they are arrays, join the values with commas. value = _.isArray( value ) ? value.join( ',' ) : value; // An object of param hashes may be passed in, if ( _.isObject( value ) ) { memo = _.merge( memo, value ); } else { // as may individual values for required parameter keys if ( _.isString( key ) ) { memo[ key ] = value; } } return memo; }, {}); try { _.each( requiredParams, function( key ) { if ( _.isUndefined( params[ key ] ) ) { throw new Error( 'missing required parameter: ' + key ); } }); } catch ( err ) { return Promise.reject( err ); } var queryString = url.format({ query: _.merge( params, { // Always submit API key and request JSON format /*jshint -W106 */// Disable underscore_case warnings: the API uses them api_key: config.apiKey, format: 'json' }) }); // console.log(config.api.root + query + queryString); var request = rest.get( config.apiRoot + query + queryString ); return new Promise(function( resolve, reject ) { function handleSuccess( data ) { resolve( data ); } function handleFailure( err, response ) { reject( err ); } // Long-term it may make sense not to handle all errors the same... request // https://github.com/danwrong/restler#events .on( 'success', handleSuccess ) .on( 'error', handleFailure ) .on( 'fail', handleFailure ) .on( 'timeout', handleFailure ); }); };
set pathname(value) { const url = Object.assign(URL.parse(this._url), { pathname: value }); this.assign(URL.format(url)); }
app.get('/login', function(req, res) { var submit_url = url.format({ pathname: '/authenticate', query: {redirect: req.query.redirect || '/documents' }}); res.render('static/login', { submit_url: submit_url }); });
_getOptionsFromUrl(reqUrl) { // `true` to parse the query param as an object. const urlObj = nullthrows(url.parse(reqUrl, true)); const urlQuery = nullthrows(urlObj.query); const pathname = urlObj.pathname ? decodeURIComponent(urlObj.pathname) : ''; let isMap = false; // Backwards compatibility. Options used to be as added as '.' to the // entry module name. We can safely remove these options. const entryFile = pathname. replace(/^\//, ''). split('.'). filter(part => { if (part === 'map') { isMap = true; return false; } if ( part === 'includeRequire' || part === 'runModule' || part === 'bundle' || part === 'delta' || part === 'assets') { return false; } return true; }). join('.') + '.js'; const absoluteEntryFile = getEntryAbsolutePath(this._config, entryFile); // try to get the platform from the url const platform = urlQuery.platform || parsePlatformFilePath(pathname, this._platforms).platform; const deltaBundleId = urlQuery.deltaBundleId; const dev = this._getBoolOptionFromQuery(urlQuery, 'dev', true); const minify = this._getBoolOptionFromQuery(urlQuery, 'minify', false); const excludeSource = this._getBoolOptionFromQuery( urlQuery, 'excludeSource', false); const includeSource = this._getBoolOptionFromQuery( urlQuery, 'inlineSourceMap', false); const customTransformOptions = parseCustomTransformOptions(urlObj); return { sourceMapUrl: url.format(_extends({}, urlObj, { pathname: pathname.replace(/\.(bundle|delta)$/, '.map') })), bundleType: isMap ? 'map' : deltaBundleId ? 'delta' : 'bundle', customTransformOptions, entryFile: absoluteEntryFile, deltaBundleId, dev, minify, excludeSource, hot: true, runModule: this._getBoolOptionFromQuery(urlObj.query, 'runModule', true), inlineSourceMap: includeSource, platform, entryModuleOnly: this._getBoolOptionFromQuery( urlObj.query, 'entryModuleOnly', false), onProgress: null }; }
const ignoredParams = { bundleType: null, onProgress: null, deltaBundleId: null, excludeSource: null, sourceMapUrl: null };return JSON.stringify(Object.assign({}, options, ignoredParams));}_prepareDeltaBundler(req, mres) {const options = this._getOptionsFromUrl(url.format(_extends({}, url.parse(req.url), { protocol: 'http', host: req.headers.host }))); const buildID = this.getNewBuildID(); if (this._config.reporter) { options.onProgress = (transformedFileCount, totalFileCount) => { mres.writeChunk( { 'Content-Type': 'application/json' }, JSON.stringify({ done: transformedFileCount, total: totalFileCount })); this._reporter.update({ buildID, type: 'bundle_transform_progressed', transformedFileCount, totalFileCount }); }; } /* $FlowFixMe(>=0.63.0 site=react_native_fb) This comment suppresses an * error found when Flow v0.63 was deployed. To see the error delete this * comment and run Flow. */ this._reporter.update({ buildID, bundleDetails: { entryFile: options.entryFile, platform: options.platform, dev: options.dev, minify: options.minify, bundleType: options.bundleType }, type: 'bundle_build_started' }); return { options, buildID }; }
if (require.main === module) { let path = require('path'); let fs = require('fs'); let url = require('url'); let fileUrl = require('file-url'); let treeKill = require('tree-kill'); let { start: efStart } = require('electron-forge'); let [, , buildDir, baseUrl, testPageUrl, id] = process.argv; let emberAppDir = path.join(buildDir, 'ember'); let baseObj = url.parse(baseUrl); let testPageObj = url.parse(testPageUrl, true); // Build testem.js URL baseObj.pathname = '/testem.js'; let testemJsUrl = url.format(baseObj); // Process the HTML to: // * inject our getTestemId() script so the testem client can extract the ID // from the query params and be able to communicate with the testem server // * rewrite the testem.js script to use an absolute URL pointing to the // testem server let testPagePath = path.join(emberAppDir, path.join.apply(null, testPageObj.pathname.split('/'))); let htmlContent = fs.readFileSync(testPagePath, 'utf8').toString(); htmlContent = htmlContent.replace(/^(\s*)<head>/m, [ '$1<head>', '$1 <script>', '$1 window.getTestemId = function() {', // FIXME: It should be safe to replace "\?" with "?" below due to context -- need to check though // eslint-disable-next-line no-useless-escape '$1 var match = window.location.search.match(/[\?&]testemId=([^\?&]+)/);',
dump(output = process.stdout) { for (let entry = this.first, i = 1; entry; entry = entry.next, ++i) output.write(`${i}: ${URL.format(entry.url)}\n`); }
Request.prototype.init = function (options) { // init() contains all the code to setup the request object. // the actual outgoing request is not started until start() is called // this function is called from both the constructor and on redirect. var self = this if (!options) { options = {} } self.headers = self.headers ? copy(self.headers) : {} // Delete headers with value undefined since they break // ClientRequest.OutgoingMessage.setHeader in node 0.12 for (var headerName in self.headers) { if (typeof self.headers[headerName] === 'undefined') { delete self.headers[headerName] } } caseless.httpify(self, self.headers) if (!self.method) { self.method = options.method || 'GET' } if (!self.localAddress) { self.localAddress = options.localAddress } self._qs.init(options) debug(options) if (!self.pool && self.pool !== false) { self.pool = globalPool } self.dests = self.dests || [] self.__isRequestRequest = true // Protect against double callback if (!self._callback && self.callback) { self._callback = self.callback self.callback = function () { if (self._callbackCalled) { return // Print a warning maybe? } self._callbackCalled = true self._callback.apply(self, arguments) } self.on('error', self.callback.bind()) self.on('complete', self.callback.bind(self, null)) } // People use this property instead all the time, so support it if (!self.uri && self.url) { self.uri = self.url delete self.url } // If there's a baseUrl, then use it as the base URL (i.e. uri must be // specified as a relative path and is appended to baseUrl). if (self.baseUrl) { if (typeof self.baseUrl !== 'string') { return self.emit('error', new Error('options.baseUrl must be a string')) } if (typeof self.uri !== 'string') { return self.emit('error', new Error('options.uri must be a string when using options.baseUrl')) } if (self.uri.indexOf('//') === 0 || self.uri.indexOf('://') !== -1) { return self.emit('error', new Error('options.uri must be a path when using options.baseUrl')) } // Handle all cases to make sure that there's only one slash between // baseUrl and uri. var baseUrlEndsWithSlash = self.baseUrl.lastIndexOf('/') === self.baseUrl.length - 1 var uriStartsWithSlash = self.uri.indexOf('/') === 0 if (baseUrlEndsWithSlash && uriStartsWithSlash) { self.uri = self.baseUrl + self.uri.slice(1) } else if (baseUrlEndsWithSlash || uriStartsWithSlash) { self.uri = self.baseUrl + self.uri } else if (self.uri === '') { self.uri = self.baseUrl } else { self.uri = self.baseUrl + '/' + self.uri } delete self.baseUrl } // A URI is needed by this point, emit error if we haven't been able to get one if (!self.uri) { return self.emit('error', new Error('options.uri is a required argument')) } // If a string URI/URL was given, parse it into a URL object if (typeof self.uri === 'string') { self.uri = url.parse(self.uri) } // DEPRECATED: Warning for users of the old Unix Sockets URL Scheme if (self.uri.protocol === 'unix:') { return self.emit('error', new Error('`unix://` URL scheme is no longer supported. Please use the format `http://unix:SOCKET:PATH`')) } // Support Unix Sockets if (self.uri.host === 'unix') { // Get the socket & request paths from the URL var unixParts = self.uri.path.split(':') , host = unixParts[0] , path = unixParts[1] // Apply unix properties to request self.socketPath = host self.uri.pathname = path self.uri.path = path self.uri.host = host self.uri.hostname = host self.uri.isUnix = true } if (self.strictSSL === false) { self.rejectUnauthorized = false } if (!self.uri.pathname) {self.uri.pathname = '/'} if (!(self.uri.host || (self.uri.hostname && self.uri.port)) && !self.uri.isUnix) { // Invalid URI: it may generate lot of bad errors, like 'TypeError: Cannot call method `indexOf` of undefined' in CookieJar // Detect and reject it as soon as possible var faultyUri = url.format(self.uri) var message = 'Invalid URI "' + faultyUri + '"' if (Object.keys(options).length === 0) { // No option ? This can be the sign of a redirect // As this is a case where the user cannot do anything (they didn't call request directly with this URL) // they should be warned that it can be caused by a redirection (can save some hair) message += '. This can be caused by a crappy redirection.' } // This error was fatal return self.emit('error', new Error(message)) } if (!self.hasOwnProperty('proxy')) { self.proxy = getProxyFromURI(self.uri) } self.tunnel = self._tunnel.isEnabled(options) if (self.proxy) { self._tunnel.setup(options) } self._redirect.onRequest(options) self.setHost = false if (!self.hasHeader('host')) { var hostHeaderName = self.originalHostHeaderName || 'host' self.setHeader(hostHeaderName, self.uri.hostname) if (self.uri.port) { if ( !(self.uri.port === 80 && self.uri.protocol === 'http:') && !(self.uri.port === 443 && self.uri.protocol === 'https:') ) { self.setHeader(hostHeaderName, self.getHeader('host') + (':' + self.uri.port) ) } } self.setHost = true } self.jar(self._jar || options.jar) if (!self.uri.port) { if (self.uri.protocol === 'http:') {self.uri.port = 80} else if (self.uri.protocol === 'https:') {self.uri.port = 443} } if (self.proxy && !self.tunnel) { self.port = self.proxy.port self.host = self.proxy.hostname } else { self.port = self.uri.port self.host = self.uri.hostname } if (options.form) { self.form(options.form) } if (options.formData) { var formData = options.formData var requestForm = self.form() var appendFormValue = function (key, value) { if (value.hasOwnProperty('value') && value.hasOwnProperty('options')) { requestForm.append(key, value.value, value.options) } else { requestForm.append(key, value) } } for (var formKey in formData) { if (formData.hasOwnProperty(formKey)) { var formValue = formData[formKey] if (formValue instanceof Array) { for (var j = 0; j < formValue.length; j++) { appendFormValue(formKey, formValue[j]) } } else { appendFormValue(formKey, formValue) } } } } if (options.qs) { self.qs(options.qs) } if (self.uri.path) { self.path = self.uri.path } else { self.path = self.uri.pathname + (self.uri.search || '') } if (self.path.length === 0) { self.path = '/' } // Auth must happen last in case signing is dependent on other headers if (options.aws) { self.aws(options.aws) } if (options.hawk) { self.hawk(options.hawk) } if (options.httpSignature) { self.httpSignature(options.httpSignature) } if (options.auth) { if (Object.prototype.hasOwnProperty.call(options.auth, 'username')) { options.auth.user = options.auth.username } if (Object.prototype.hasOwnProperty.call(options.auth, 'password')) { options.auth.pass = options.auth.password } self.auth( options.auth.user, options.auth.pass, options.auth.sendImmediately, options.auth.bearer ) } if (self.gzip && !self.hasHeader('accept-encoding')) { self.setHeader('accept-encoding', 'gzip') } if (self.uri.auth && !self.hasHeader('authorization')) { var uriAuthPieces = self.uri.auth.split(':').map(function(item) {return self._qs.unescape(item)}) self.auth(uriAuthPieces[0], uriAuthPieces.slice(1).join(':'), true) } if (!self.tunnel && self.proxy && self.proxy.auth && !self.hasHeader('proxy-authorization')) { var proxyAuthPieces = self.proxy.auth.split(':').map(function(item) {return self._qs.unescape(item)}) var authHeader = 'Basic ' + toBase64(proxyAuthPieces.join(':')) self.setHeader('proxy-authorization', authHeader) } if (self.proxy && !self.tunnel) { self.path = (self.uri.protocol + '//' + self.uri.host + self.path) } if (options.json) { self.json(options.json) } if (options.multipart) { self.multipart(options.multipart) } if (options.time) { self.timing = true self.elapsedTime = self.elapsedTime || 0 } if (self.body) { var length = 0 if (!Buffer.isBuffer(self.body)) { if (Array.isArray(self.body)) { for (var i = 0; i < self.body.length; i++) { length += self.body[i].length } } else { self.body = new Buffer(self.body) length = self.body.length } } else { length = self.body.length } if (length) { if (!self.hasHeader('content-length')) { self.setHeader('content-length', length) } } else { self.emit('error', new Error('Argument error, options.body.')) } } if (options.oauth) { self.oauth(options.oauth) } else if (self._oauth.params && self.hasHeader('authorization')) { self.oauth(self._oauth.params) } var protocol = self.proxy && !self.tunnel ? self.proxy.protocol : self.uri.protocol , defaultModules = {'http:':http, 'https:':https} , httpModules = self.httpModules || {} self.httpModule = httpModules[protocol] || defaultModules[protocol] if (!self.httpModule) { return self.emit('error', new Error('Invalid protocol: ' + protocol)) } if (options.ca) { self.ca = options.ca } if (!self.agent) { if (options.agentOptions) { self.agentOptions = options.agentOptions } if (options.agentClass) { self.agentClass = options.agentClass } else if (options.forever) { self.agentClass = protocol === 'http:' ? ForeverAgent : ForeverAgent.SSL } else { self.agentClass = self.httpModule.Agent } } if (self.pool === false) { self.agent = false } else { self.agent = self.agent || self.getNewAgent() } self.on('pipe', function (src) { if (self.ntick && self._started) { self.emit('error', new Error('You cannot pipe to this stream after the outbound request has started.')) } self.src = src if (isReadStream(src)) { if (!self.hasHeader('content-type')) { self.setHeader('content-type', mime.lookup(src.path)) } } else { if (src.headers) { for (var i in src.headers) { if (!self.hasHeader(i)) { self.setHeader(i, src.headers[i]) } } } if (self._json && !self.hasHeader('content-type')) { self.setHeader('content-type', 'application/json') } if (src.method && !self.explicitMethod) { self.method = src.method } } // self.on('pipe', function () { // console.error('You have already piped to this stream. Pipeing twice is likely to break the request.') // }) }) defer(function () { if (self._aborted) { return } var end = function () { if (self._form) { if (!self._auth.hasAuth) { self._form.pipe(self) } else if (self._auth.hasAuth && self._auth.sentAuth) { self._form.pipe(self) } } if (self._multipart && self._multipart.chunked) { self._multipart.body.pipe(self) } if (self.body) { if (Array.isArray(self.body)) { self.body.forEach(function (part) { self.write(part) }) } else { self.write(self.body) } self.end() } else if (self.requestBodyStream) { console.warn('options.requestBodyStream is deprecated, please pass the request object to stream.pipe.') self.requestBodyStream.pipe(self) } else if (!self.src) { if (self._auth.hasAuth && !self._auth.sentAuth) { self.end() return } if (self.method !== 'GET' && typeof self.method !== 'undefined') { self.setHeader('content-length', 0) } self.end() } } if (self._form && !self.hasHeader('content-length')) { // Before ending the request, we had to compute the length of the whole form, asyncly self.setHeader(self._form.getHeaders()) self._form.getLength(function (err, length) { if (!err) { self.setHeader('content-length', length) } end() }) } else { end() } self.ntick = true }) }
set href(href) { this.assign(URL.format(href)); }
function get(url, opts, cb) { var parsedUrl = typeof url === 'string' ? urlLib.parse(prependHttp(url)) : url; var fn = parsedUrl.protocol === 'https:' ? https : http; var arg = objectAssign({}, parsedUrl, opts); url = typeof url === 'string' ? prependHttp(url) : urlLib.format(url); if (arg.agent === undefined) { arg.agent = infinityAgent[fn === https ? 'https' : 'http'].globalAgent; if (process.version.indexOf('v0.10') === 0 && fn === https && ( typeof opts.ca !== 'undefined' || typeof opts.cert !== 'undefined' || typeof opts.ciphers !== 'undefined' || typeof opts.key !== 'undefined' || typeof opts.passphrase !== 'undefined' || typeof opts.pfx !== 'undefined' || typeof opts.rejectUnauthorized !== 'undefined')) { arg.agent = new (infinityAgent.https.Agent)(opts); } } if (query) { arg.path = (arg.path ? arg.path.split('?')[0] : '') + '?' + (typeof query === 'string' ? query : querystring.stringify(query)); query = undefined; } var req = fn.request(arg, function (response) { var statusCode = response.statusCode; var res = response; if (proxy) { proxy.emit('response', res); } // auto-redirect only for GET and HEAD methods if (statuses.redirect[statusCode] && 'location' in res.headers && (opts.method === 'GET' || opts.method === 'HEAD')) { res.resume(); // discard response if (++redirectCount > 10) { cb(new GotError('Redirected 10 times. Aborting.'), undefined, res); return; } delete opts.host; delete opts.hostname; delete opts.port; delete opts.path; if (proxy) { proxy.emit('redirect', res, opts); } get(urlLib.resolve(url, res.headers.location), opts, cb); return; } if (['gzip', 'deflate'].indexOf(res.headers['content-encoding']) !== -1) { res = res.pipe(zlib.createUnzip()); } if (statusCode < 200 || statusCode > 299) { readAllStream(res, encoding, function (err, data) { err = new GotError(opts.method + ' ' + url + ' response code is ' + statusCode + ' (' + statuses[statusCode] + ')', err); err.code = statusCode; if (data && json) { try { data = JSON.parse(data); } catch (e) { err = new GotError('Parsing ' + url + ' response failed', new GotError(e.message, err)); } } cb(err, data, response); }); return; } // pipe the response to the proxy if in proxy mode if (proxy) { proxy.setReadable(res); return; } readAllStream(res, encoding, function (err, data) { if (err) { err = new GotError('Reading ' + url + ' response failed', err); } else if (json) { try { data = JSON.parse(data); } catch (e) { err = new GotError('Parsing ' + url + ' response failed', e); } } cb(err, data, response); }); }).once('error', function (err) { cb(new GotError('Request to ' + url + ' failed', err)); }); if (timeout) { timedOut(req, timeout); } if (!proxy) { if (isStream.readable(body)) { body.pipe(req); } else { req.end(body); } return; } if (body) { proxy.write = function () { throw new Error('got\'s stream is not writable when options.body is used'); }; if (isStream.readable(body)) { body.pipe(req); } else { req.end(body); } return; } if (opts.method === 'POST' || opts.method === 'PUT' || opts.method === 'PATCH') { proxy.setWritable(req); return; } req.end(); }
set hash(value) { const url = Object.assign(URL.parse(this._url), { hash: value }); this.assign(URL.format(url)); }
else { let port = 3000; if(config.webserver.https) { port = config.webserver.https.port; if(!path.isAbsolute(config.webserver.https.keyPath)) { config.webserver.https.keyPath = path.join(__dirname, '..', config.webserver.https.keyPath); } if(!path.isAbsolute(config.webserver.https.certPath)) { config.webserver.https.certPath = path.join(__dirname, '..', config.webserver.https.certPath); } } else if(config.webserver.http && config.webserver.http.port) { port = config.webserver.http.port; } config.webserver.port = port; config.webserver.baseUrl = url.format({ protocol: config.webserver.https ? 'https' : 'http', hostname: config.webserver.hostname, port: port === 80 || port === 434 ? null : port }); } config.errors = includeAll({ dirname: path.join(__dirname, '..', 'errors'), filter: /(.+)\.js$/ }); config.env = process.env.NODE_ENV || 'development'; config.root = path.resolve(__dirname, '../'); module.exports = config;
.then(function (port) { newConfig.server = newConfig.server || {}; newConfig.server.port = port; newConfig.url = url.format(_.extend({}, url.parse(newConfig.url), {port: port, host: null})); var newConfigFile = path.join(config.paths.appRoot, 'config.test' + port + '.js'); return new Promise(function (resolve, reject) { fs.writeFile(newConfigFile, 'module.exports = {' + envName + ': ' + JSON.stringify(newConfig) + '}', function (err) { if (err) { return reject(err); } // setup process environment for the forked Ghost to use the new config file var env = _.clone(process.env), baseKill, child, pingTries = 0, pingCheck, pingStop = function () { if (pingCheck) { clearInterval(pingCheck); pingCheck = undefined; return true; } return false; }; env.GHOST_CONFIG = newConfigFile; env.NODE_ENV = envName; child = cp.fork(path.join(config.paths.appRoot, 'index.js'), {env: env}); // return the port to make it easier to do requests child.port = port; // periodic check until forked Ghost is running and is listening on the port pingCheck = setInterval(function () { var socket = net.connect(port); socket.on('connect', function () { socket.end(); if (pingStop()) { resolve(child); } }); socket.on('error', function (err) { /*jshint unused:false*/ pingTries = pingTries + 1; // continue checking if (pingTries >= 50 && pingStop()) { child.kill(); reject(new Error('Timed out waiting for child process')); } }); }, 200); child.on('exit', function (code, signal) { /*jshint unused:false*/ child.exited = true; fs.unlink(newConfigFile, function () { // swallow any errors -- file may not exist if fork() failed }); if (pingStop()) { reject(new Error('Child process exit code: ' + code)); } }); // override kill() to have an async callback baseKill = child.kill; child.kill = function (signal, cb) { if (typeof signal === 'function') { cb = signal; signal = undefined; } if (cb) { child.on('exit', function () { cb(); }); } if (child.exited) { process.nextTick(cb); } else { baseKill.apply(child, [signal]); } }; }); }); });
import DiscoverPage from './pages/discover_page'; import SettingsPage from './pages/settings_page'; import HeaderPage from './pages/header_page'; import VisualizePage from './pages/visualize_page'; import ShieldPage from './pages/shield_page'; import ConsolePage from './pages/console_page'; const kbnInternVars = global.__kibana__intern__; exports.bdd = kbnInternVars.bdd; exports.intern = kbnInternVars.intern; exports.config = exports.intern.config; exports.defaultTimeout = exports.config.defaultTimeout; exports.defaultTryTimeout = exports.config.defaultTryTimeout; exports.defaultFindTimeout = exports.config.defaultFindTimeout; exports.scenarioManager = new ScenarioManager(url.format(exports.config.servers.elasticsearch)); defineDelayedExport('remote', (suite) => suite.remote); defineDelayedExport('common', () => new Common()); defineDelayedExport('discoverPage', () => new DiscoverPage()); defineDelayedExport('headerPage', () => new HeaderPage()); defineDelayedExport('settingsPage', () => new SettingsPage()); defineDelayedExport('visualizePage', () => new VisualizePage()); defineDelayedExport('shieldPage', () => new ShieldPage()); defineDelayedExport('consolePage', () => new ConsolePage()); // creates an export for values that aren't actually avaialable until // until tests start to run. These getters will throw errors if the export // is accessed before it's available, hopefully making debugging easier. // Once the first before() handler is called the onEarliestBefore() handlers // will fire and rewrite all of these exports to be their correct value.
}, function(err, config) { if (err) { return process.exit(0); } // defaults config.concurrency = config.concurrency && parseInt(config.concurrency, 10) || 1; config.streams = config.streams && parseInt(config.streams, 10) || 1; config.limit = config.limit && parseInt(config.limit, 100) || 0; config.changes_feed_timeout = config.changes_feed_timeout && parseInt(config.changes_feed_timeout, 10) || 10000; config.convert_process_timeout = config.convert_process_timeout && parseInt(config.convert_process_timeout, 10) || 60000; couchmagick.info('using config ' + JSON.stringify(config).replace(/"password":"******"/, '"password":"******"')); // TODO: validate config var couch = url.format({ protocol: 'http', hostname: config.address, port: config.port, auth: config.auth && config.auth.username && config.auth.password ? [ config.auth.username, config.auth.password ].join(':') : null }); var options = { limit: config.limit, feed: 'continuous', changes_feed_timeout: config.changes_feed_timeout, convert_process_timeout: config.convert_process_timeout, concurrency: config.concurrency }; function listen(db, next) { couchmagick.info('Listening on ' + db); var stream = magick(url.resolve(couch, db), options); stream.on('error', couchmagick.error); stream.on('data', function(data) { if (data.response) { couchmagick.info(data.response); } }); stream.on('end', next); } // main loop ;) function run(err) { if (err) { process.exit(0); } // get list of all databases // TODO: listen to db changes nano(couch).db.list(function(err, dbs) { if (err) { couchmagick.error('Can not get _all_dbs: ' + err.description); return process.exit(0); } async.eachLimit(dbs, config.streams, listen, run); }); } run(); });
'auth': 'isaacschlueter', 'hostname': 'jabber.org' } }; for (var u in parseTests) { var actual = url.parse(u), expected = parseTests[u]; for (var i in expected) { var e = JSON.stringify(expected[i]), a = JSON.stringify(actual[i]); assert.equal(e, a, 'parse(' + u + ').' + i + ' == ' + e + '\nactual: ' + a); } var expected = u, actual = url.format(parseTests[u]); assert.equal(expected, actual, 'format(' + u + ') == ' + u + '\nactual:' + actual); } var parseTestsWithQueryString = { '/foo/bar?baz=quux#frag' : { 'href': '/foo/bar?baz=quux#frag', 'hash': '#frag', 'search': '?baz=quux', 'query': { 'baz': 'quux' }, 'pathname': '/foo/bar' },
var parseFullUrl=url.parse(fullurl); console.log(parseFullUrl); var urlObject={ protocol:"http", auth:"wsp/wangshi", hostname:"wangshiping.net", port:8080, pathname:"wsp/test", serach:"query=aaa&id=1", hash:"#lala" }; var parseurl=url.format(urlObject); console.log(parseurl); // 给定一个 基础url 路径,向浏览器一样处理 href 路径 // // url.resolve() console.log(url.resolve("/one/two/three","four")); console.log(url.resolve("/one/two/three","/four")); console.log(url.resolve("/one/two/three","four.html")); console.log(url.resolve("http://example.com","/wsp")); console.log(url.resolve("http://example.com/wsp","/one/two")); console.log(url.resolve("http://example.com/wsp","/one/two.html")); console.log(url.resolve("http://example.com/wsp","one/two.html"));
Request.prototype.init = function (options) { // init() contains all the code to setup the request object. // the actual outgoing request is not started until start() is called // this function is called from both the constructor and on redirect. var self = this if (!options) options = {} self.method = options.method || 'GET' debug(options) if (!self.pool && self.pool !== false) self.pool = globalPool self.dests = self.dests || [] self.__isRequestRequest = true // Protect against double callback if (!self._callback && self.callback) { self._callback = self.callback self.callback = function () { if (self._callbackCalled) return // Print a warning maybe? self._callbackCalled = true self._callback.apply(self, arguments) } self.on('error', self.callback.bind()) self.on('complete', self.callback.bind(self, null)) } if (self.url) { // People use this property instead all the time so why not just support it. self.uri = self.url delete self.url } if (!self.uri) { // this will throw if unhandled but is handleable when in a redirect return self.emit('error', new Error("options.uri is a required argument")) } else { if (typeof self.uri == "string") self.uri = url.parse(self.uri) } if (self.proxy) { if (typeof self.proxy == 'string') self.proxy = url.parse(self.proxy) // do the HTTP CONNECT dance using koichik/node-tunnel if (http.globalAgent && self.uri.protocol === "https:") { var tunnelFn = self.proxy.protocol === "http:" ? tunnel.httpsOverHttp : tunnel.httpsOverHttps var tunnelOptions = { proxy: { host: self.proxy.hostname , port: +self.proxy.port , proxyAuth: self.proxy.auth , headers: { Host: self.uri.hostname + ':' + (self.uri.port || self.uri.protocol === 'https:' ? 443 : 80) }} , ca: this.ca } self.agent = tunnelFn(tunnelOptions) self.tunnel = true } } if (!self.uri.host || !self.uri.pathname) { // Invalid URI: it may generate lot of bad errors, like "TypeError: Cannot call method 'indexOf' of undefined" in CookieJar // Detect and reject it as soon as possible var faultyUri = url.format(self.uri) var message = 'Invalid URI "' + faultyUri + '"' if (Object.keys(options).length === 0) { // No option ? This can be the sign of a redirect // As this is a case where the user cannot do anything (he didn't call request directly with this URL) // he should be warned that it can be caused by a redirection (can save some hair) message += '. This can be caused by a crappy redirection.' } self.emit('error', new Error(message)) return // This error was fatal } self._redirectsFollowed = self._redirectsFollowed || 0 self.maxRedirects = (self.maxRedirects !== undefined) ? self.maxRedirects : 10 self.followRedirect = (self.followRedirect !== undefined) ? self.followRedirect : true self.followAllRedirects = (self.followAllRedirects !== undefined) ? self.followAllRedirects : false if (self.followRedirect || self.followAllRedirects) self.redirects = self.redirects || [] self.headers = self.headers ? copy(self.headers) : {} self.setHost = false if (!(self.headers.host || self.headers.Host)) { self.headers.host = self.uri.hostname if (self.uri.port) { if ( !(self.uri.port === 80 && self.uri.protocol === 'http:') && !(self.uri.port === 443 && self.uri.protocol === 'https:') ) self.headers.host += (':'+self.uri.port) } self.setHost = true } self.jar(self._jar || options.jar) if (!self.uri.pathname) {self.uri.pathname = '/'} if (!self.uri.port) { if (self.uri.protocol == 'http:') {self.uri.port = 80} else if (self.uri.protocol == 'https:') {self.uri.port = 443} } if (self.proxy && !self.tunnel) { self.port = self.proxy.port self.host = self.proxy.hostname } else { self.port = self.uri.port self.host = self.uri.hostname } self.clientErrorHandler = function (error) { if (self._aborted) return if (self.req && self.req._reusedSocket && error.code === 'ECONNRESET' && self.agent.addRequestNoreuse) { self.agent = { addRequest: self.agent.addRequestNoreuse.bind(self.agent) } self.start() self.req.end() return } if (self.timeout && self.timeoutTimer) { clearTimeout(self.timeoutTimer) self.timeoutTimer = null } self.emit('error', error) } self._parserErrorHandler = function (error) { if (this.res) { if (this.res.request) { this.res.request.emit('error', error) } else { this.res.emit('error', error) } } else { this._httpMessage.emit('error', error) } } if (options.form) { self.form(options.form) } if (options.qs) self.qs(options.qs) if (self.uri.path) { self.path = self.uri.path } else { self.path = self.uri.pathname + (self.uri.search || "") } if (self.path.length === 0) self.path = '/' // Auth must happen last in case signing is dependent on other headers if (options.oauth) { self.oauth(options.oauth) } if (options.aws) { self.aws(options.aws) } if (options.hawk) { self.hawk(options.hawk) } if (options.auth) { self.auth( options.auth.user || options.auth.username, options.auth.pass || options.auth.password, options.auth.sendImmediately) } if (self.uri.auth && !self.headers.authorization) { var authPieces = self.uri.auth.split(':').map(function(item){ return querystring.unescape(item) }) self.auth(authPieces[0], authPieces[1], true) } if (self.proxy && self.proxy.auth && !self.headers['proxy-authorization'] && !self.tunnel) { self.headers['proxy-authorization'] = "Basic " + toBase64(self.proxy.auth.split(':').map(function(item){ return querystring.unescape(item)}).join(':')) } if (self.proxy && !self.tunnel) self.path = (self.uri.protocol + '//' + self.uri.host + self.path) if (options.json) { self.json(options.json) } else if (options.multipart) { self.boundary = uuid() self.multipart(options.multipart) } if (self.body) { var length = 0 if (!Buffer.isBuffer(self.body)) { if (Array.isArray(self.body)) { for (var i = 0; i < self.body.length; i++) { length += self.body[i].length } } else { self.body = new Buffer(self.body) length = self.body.length } } else { length = self.body.length } if (length) { if(!self.headers['content-length'] && !self.headers['Content-Length']) self.headers['content-length'] = length } else { throw new Error('Argument error, options.body.') } } var protocol = self.proxy && !self.tunnel ? self.proxy.protocol : self.uri.protocol , defaultModules = {'http:':http, 'https:':https} , httpModules = self.httpModules || {} ; self.httpModule = httpModules[protocol] || defaultModules[protocol] if (!self.httpModule) return this.emit('error', new Error("Invalid protocol")) if (options.ca) self.ca = options.ca if (!self.agent) { if (options.agentOptions) self.agentOptions = options.agentOptions if (options.agentClass) { self.agentClass = options.agentClass } else if (options.forever) { self.agentClass = protocol === 'http:' ? ForeverAgent : ForeverAgent.SSL } else { self.agentClass = self.httpModule.Agent } } if (self.strictSSL === false) { self.rejectUnauthorized = false } if (self.pool === false) { self.agent = false } else { self.agent = self.agent || self.getAgent() if (self.maxSockets) { // Don't use our pooling if node has the refactored client self.agent.maxSockets = self.maxSockets } if (self.pool.maxSockets) { // Don't use our pooling if node has the refactored client self.agent.maxSockets = self.pool.maxSockets } } self.once('pipe', function (src) { if (self.ntick && self._started) throw new Error("You cannot pipe to this stream after the outbound request has started.") self.src = src if (isReadStream(src)) { if (!self.headers['content-type'] && !self.headers['Content-Type']) self.headers['content-type'] = mime.lookup(src.path) } else { if (src.headers) { for (var i in src.headers) { if (!self.headers[i]) { self.headers[i] = src.headers[i] } } } if (self._json && !self.headers['content-type'] && !self.headers['Content-Type']) self.headers['content-type'] = 'application/json' if (src.method && !self.method) { self.method = src.method } } self.on('pipe', function () { console.error("You have already piped to this stream. Pipeing twice is likely to break the request.") }) }) process.nextTick(function () { if (self._aborted) return if (self._form) { self.setHeaders(self._form.getHeaders()) self._form.pipe(self) } if (self.body) { if (Array.isArray(self.body)) { self.body.forEach(function (part) { self.write(part) }) } else { self.write(self.body) } self.end() } else if (self.requestBodyStream) { console.warn("options.requestBodyStream is deprecated, please pass the request object to stream.pipe.") self.requestBodyStream.pipe(self) } else if (!self.src) { if (self.method !== 'GET' && typeof self.method !== 'undefined') { self.headers['content-length'] = 0 } self.end() } self.ntick = true }) }
export default function config(pkg = {}, argv = process.argv) { argv = { dev: false, prod: false, static: false, server: false, ...minimist(argv), } if (argv.production) { process.env.NODE_ENV = "production" if (!pkg.homepage) { throw new Error( "Your package.json require a 'homepage' field" ) } } let baseUrl if (argv.baseurl) { baseUrl = url.parse(argv.baseurl) } else { const prodBaseUrl = pkg.homepage ? url.parse(pkg.homepage) : {} baseUrl = argv.production ? prodBaseUrl : { ...url.parse("http://0.0.0.0:3000/"), // get base from prod url pathname: prodBaseUrl.pathname, } } // ensure trailing slash if (!baseUrl.pathname.endsWith("/")) { baseUrl.pathname = baseUrl.pathname + "/" } // update baseUrl.href since pathname has been updated baseUrl = url.parse(url.format(baseUrl)) const consts = { ...{ __DEV__: false, __PROD__: false, __STATIC__: false, __SERVER__: false, __DEVTOOLS__: false, }, __BASE_URL__: baseUrl, __DEV__: Boolean(argv.dev), __PROD__: Boolean(argv.production), __STATIC__: Boolean(argv.static), __SERVER__: Boolean(argv.server), __DEVTOOLS__: Boolean(argv.devtools), ...argv.production && { "process.env": { NODE_ENV: JSON.stringify("production"), }, }, } return { ...argv, consts, baseUrl, } }
exports['db.grantPublicReadAccess / revokePublicReadAccess'] = function (test) { var hoodie = new PluginAPI(DEFAULT_OPTIONS); var db_url = COUCH.url + '/foo'; var db_url_testuser1 = url.parse(db_url); db_url_testuser1.auth = 'user/testuser1:testing'; db_url_testuser1 = url.format(db_url_testuser1); var db_url_testuser2 = url.parse(db_url); db_url_testuser2.auth = 'user/testuser2:testing'; db_url_testuser2 = url.format(db_url_testuser2); hoodie.database.add('foo', function (err, db) { if (err) { return test.done(err); } var ignoreErrs = function (fn) { return function (callback) { fn(function () { var args = Array.prototype.slice.call(arguments, 1); return callback.apply(this, [null].concat(args)); }); }; }; var opt = {data: {asdf: 123}}; var userdoc1 = { id: 'testuser1', password: '******' }; var userdoc2 = { id: 'testuser2', password: '******' }; var tasks = [ async.apply(hoodie.account.add, 'user', userdoc1), async.apply(hoodie.account.add, 'user', userdoc2), async.apply(db.grantWriteAccess, 'user', 'testuser1'), db.grantPublicReadAccess, async.apply(couchr.get, db_url_testuser1 + '/_all_docs'), async.apply(couchr.put, db_url_testuser1 + '/some_doc', opt), async.apply(couchr.get, db_url_testuser2 + '/_all_docs'), async.apply(couchr.put, db_url_testuser2 + '/some_doc2', opt), async.apply(couchr.get, db_url + '/_all_docs'), async.apply(couchr.put, db_url + '/some_doc3', opt), db.revokePublicReadAccess, async.apply(couchr.get, db_url_testuser1 + '/_all_docs'), async.apply(couchr.put, db_url_testuser1 + '/some_doc4', opt), async.apply(couchr.get, db_url_testuser2 + '/_all_docs'), async.apply(couchr.put, db_url_testuser2 + '/some_doc5', opt), async.apply(couchr.get, db_url + '/_all_docs'), async.apply(couchr.put, db_url + '/some_doc6', opt) ]; async.series(tasks.map(ignoreErrs), function (err, results) { test.equal(results[4][1].statusCode, 200); // testuser1 read test.equal(results[5][1].statusCode, 201); // testuser1 write test.equal(results[6][1].statusCode, 200); // testuser2 read test.equal(results[7][1].statusCode, 401); // testuser2 write test.equal(results[8][1].statusCode, 200); // anonyous read test.equal(results[9][1].statusCode, 401); // anonymous write // after revoke - testuser1 retains original permisisons test.equal(results[11][1].statusCode, 200); // testuser1 read test.equal(results[12][1].statusCode, 201); // testuser1 write test.equal(results[13][1].statusCode, 401); // testuser2 read test.equal(results[14][1].statusCode, 401); // testuesr2 write test.equal(results[15][1].statusCode, 401); // anonymous read test.equal(results[16][1].statusCode, 401); // anonymous write test.done(); }); }); };
constructor (atomApplication, fileRecoveryService, settings = {}) { super() this.id = nextId++ this.atomApplication = atomApplication this.fileRecoveryService = fileRecoveryService this.isSpec = settings.isSpec this.headless = settings.headless this.safeMode = settings.safeMode this.devMode = settings.devMode this.resourcePath = settings.resourcePath const locationsToOpen = settings.locationsToOpen || [] this.loadedPromise = new Promise(resolve => { this.resolveLoadedPromise = resolve }) this.closedPromise = new Promise(resolve => { this.resolveClosedPromise = resolve }) const options = { show: false, title: 'Atom', tabbingIdentifier: 'atom', webPreferences: { // Prevent specs from throttling when the window is in the background: // this should result in faster CI builds, and an improvement in the // local development experience when running specs through the UI (which // now won't pause when e.g. minimizing the window). backgroundThrottling: !this.isSpec, // Disable the `auxclick` feature so that `click` events are triggered in // response to a middle-click. // (Ref: https://github.com/atom/atom/pull/12696#issuecomment-290496960) disableBlinkFeatures: 'Auxclick' } } // Don't set icon on Windows so the exe's ico will be used as window and // taskbar's icon. See https://github.com/atom/atom/issues/4811 for more. if (process.platform === 'linux') options.icon = ICON_PATH if (this.shouldAddCustomTitleBar()) options.titleBarStyle = 'hidden' if (this.shouldAddCustomInsetTitleBar()) options.titleBarStyle = 'hiddenInset' if (this.shouldHideTitleBar()) options.frame = false this.browserWindow = new BrowserWindow(options) Object.defineProperty(this.browserWindow, 'loadSettingsJSON', { get: () => JSON.stringify(Object.assign({ userSettings: !this.isSpec ? this.atomApplication.configFile.get() : null }, this.loadSettings)) }) this.handleEvents() this.loadSettings = Object.assign({}, settings) this.loadSettings.appVersion = app.getVersion() this.loadSettings.resourcePath = this.resourcePath this.loadSettings.atomHome = process.env.ATOM_HOME if (this.loadSettings.devMode == null) this.loadSettings.devMode = false if (this.loadSettings.safeMode == null) this.loadSettings.safeMode = false if (this.loadSettings.clearWindowState == null) this.loadSettings.clearWindowState = false this.loadSettings.initialPaths = locationsToOpen.map(location => location.pathToOpen).filter(Boolean) this.loadSettings.initialPaths.sort() // Only send to the first non-spec window created if (includeShellLoadTime && !this.isSpec) { includeShellLoadTime = false if (!this.loadSettings.shellLoadTime) { this.loadSettings.shellLoadTime = Date.now() - global.shellStartTime } } this.representedDirectoryPaths = this.loadSettings.initialPaths if (!this.loadSettings.env) this.env = this.loadSettings.env this.browserWindow.on('window:loaded', () => { this.disableZoom() this.emit('window:loaded') this.resolveLoadedPromise() }) this.browserWindow.on('window:locations-opened', () => { this.emit('window:locations-opened') }) this.browserWindow.on('enter-full-screen', () => { this.browserWindow.webContents.send('did-enter-full-screen') }) this.browserWindow.on('leave-full-screen', () => { this.browserWindow.webContents.send('did-leave-full-screen') }) this.browserWindow.loadURL( url.format({ protocol: 'file', pathname: `${this.resourcePath}/static/index.html`, slashes: true }) ) this.browserWindow.showSaveDialog = this.showSaveDialog.bind(this) if (this.isSpec) this.browserWindow.focusOnWebView() const hasPathToOpen = !(locationsToOpen.length === 1 && locationsToOpen[0].pathToOpen == null) if (hasPathToOpen && !this.isSpecWindow()) this.openLocations(locationsToOpen) }