X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=org.simantics.maps.server%2Fnode%2Fnode-v4.8.0-win-x64%2Fnode_modules%2Fnpm%2Fnode_modules%2Fnpm-registry-client%2Flib%2Frequest.js;fp=org.simantics.maps.server%2Fnode%2Fnode-v4.8.0-win-x64%2Fnode_modules%2Fnpm%2Fnode_modules%2Fnpm-registry-client%2Flib%2Frequest.js;h=04be044d6a0e27c792d5371c762904bc4fa27f1d;hb=2529be6d456deeb07c128603ce4971f1dc29b695;hp=0000000000000000000000000000000000000000;hpb=2636fc31c16c23711cf2b06a4ae8537bba9c1d35;p=simantics%2Fdistrict.git diff --git a/org.simantics.maps.server/node/node-v4.8.0-win-x64/node_modules/npm/node_modules/npm-registry-client/lib/request.js b/org.simantics.maps.server/node/node-v4.8.0-win-x64/node_modules/npm/node_modules/npm-registry-client/lib/request.js new file mode 100644 index 00000000..04be044d --- /dev/null +++ b/org.simantics.maps.server/node/node-v4.8.0-win-x64/node_modules/npm/node_modules/npm-registry-client/lib/request.js @@ -0,0 +1,309 @@ +module.exports = regRequest + +// npm: means +// 1. https +// 2. send authorization +// 3. content-type is 'application/json' -- metadata +// +var assert = require('assert') +var url = require('url') +var zlib = require('zlib') +var Stream = require('stream').Stream +var STATUS_CODES = require('http').STATUS_CODES + +var request = require('request') +var once = require('once') + +function regRequest (uri, params, cb_) { + assert(typeof uri === 'string', 'must pass uri to request') + assert(params && typeof params === 'object', 'must pass params to request') + assert(typeof cb_ === 'function', 'must pass callback to request') + + params.method = params.method || 'GET' + this.log.verbose('request', 'uri', uri) + + // Since there are multiple places where an error could occur, + // don't let the cb be called more than once. + var cb = once(cb_) + + if (uri.match(/^\/?favicon.ico/)) { + return cb(new Error("favicon.ico isn't a package, it's a picture.")) + } + + var adduserChange = /\/?-\/user\/org\.couchdb\.user:([^/]+)\/-rev/ + var isUserChange = uri.match(adduserChange) + var adduserNew = /\/?-\/user\/org\.couchdb\.user:([^/?]+)$/ + var isNewUser = uri.match(adduserNew) + var alwaysAuth = params.auth && params.auth.alwaysAuth + var isDelete = params.method === 'DELETE' + var isWrite = params.body || isDelete + + if (isUserChange && !isWrite) { + return cb(new Error('trying to change user document without writing(?!)')) + } + + // new users can *not* use auth, because they don't *have* auth yet + if (isUserChange) { + this.log.verbose('request', 'updating existing user; sending authorization') + params.authed = true + } else if (isNewUser) { + this.log.verbose('request', "new user, so can't send auth") + params.authed = false + } else if (alwaysAuth) { + this.log.verbose('request', 'always-auth set; sending authorization') + params.authed = true + } else if (isWrite) { + this.log.verbose('request', 'sending authorization for write operation') + params.authed = true + } else { + // most of the time we don't want to auth + this.log.verbose('request', 'no auth needed') + params.authed = false + } + + var self = this + this.attempt(function (operation) { + makeRequest.call(self, uri, params, function (er, parsed, raw, response) { + if (response) { + self.log.verbose('headers', response.headers) + if (response.headers['npm-notice']) { + self.log.warn('notice', response.headers['npm-notice']) + } + } + + if (!er || (er.message && er.message.match(/^SSL Error/))) { + if (er) er.code = 'ESSL' + return cb(er, parsed, raw, response) + } + + // Only retry on 408, 5xx or no `response`. + var statusCode = response && response.statusCode + + var timeout = statusCode === 408 + var serverError = statusCode >= 500 + var statusRetry = !statusCode || timeout || serverError + if (er && statusRetry && operation.retry(er)) { + self.log.info('retry', 'will retry, error on last attempt: ' + er) + return undefined + } + cb.apply(null, arguments) + }) + }) +} + +function makeRequest (uri, params, cb_) { + var socket + var cb = once(function (er, parsed, raw, response) { + if (socket) { + // The socket might be returned to a pool for re-use, so don’t keep + // the 'error' listener from here attached. + socket.removeListener('error', cb) + } + + return cb_(er, parsed, raw, response) + }) + + var parsed = url.parse(uri) + var headers = {} + + // metadata should be compressed + headers['accept-encoding'] = 'gzip' + + var er = this.authify(params.authed, parsed, headers, params.auth) + if (er) return cb_(er) + + var opts = this.initialize( + parsed, + params.method, + 'application/json', + headers + ) + + opts.followRedirect = (typeof params.follow === 'boolean' ? params.follow : true) + opts.encoding = null // tell request let body be Buffer instance + + if (params.etag) { + this.log.verbose('etag', params.etag) + headers[params.method === 'GET' ? 'if-none-match' : 'if-match'] = params.etag + } + + if (params.lastModified && params.method === 'GET') { + this.log.verbose('lastModified', params.lastModified) + headers['if-modified-since'] = params.lastModified + } + + // figure out wth body is + if (params.body) { + if (Buffer.isBuffer(params.body)) { + opts.body = params.body + headers['content-type'] = 'application/json' + headers['content-length'] = params.body.length + } else if (typeof params.body === 'string') { + opts.body = params.body + headers['content-type'] = 'application/json' + headers['content-length'] = Buffer.byteLength(params.body) + } else if (params.body instanceof Stream) { + headers['content-type'] = 'application/octet-stream' + if (params.body.size) headers['content-length'] = params.body.size + } else { + delete params.body._etag + delete params.body._lastModified + opts.json = params.body + } + } + + this.log.http('request', params.method, parsed.href || '/') + + var done = requestDone.call(this, params.method, uri, cb) + var req = request(opts, params.streaming ? undefined : decodeResponseBody(done)) + + req.on('error', cb) + + // This should not be necessary, as the HTTP implementation in Node + // passes errors occurring on the socket to the request itself. Being overly + // cautious comes at a low cost, though. + req.on('socket', function (s) { + socket = s + socket.on('error', cb) + }) + + if (params.streaming) { + req.on('response', function (response) { + if (response.statusCode >= 400) { + var parts = [] + response.on('data', function (data) { + parts.push(data) + }) + response.on('end', function () { + decodeResponseBody(done)(null, response, Buffer.concat(parts)) + }) + } else { + response.on('end', function () { + // don't ever re-use connections that had server errors. + // those sockets connect to the Bad Place! + if (response.socket && response.statusCode > 500) { + response.socket.destroy() + } + }) + + return cb(null, response) + } + }) + } + + if (params.body && (params.body instanceof Stream)) { + params.body.pipe(req) + } +} + +function decodeResponseBody (cb) { + return function (er, response, data) { + if (er) return cb(er, response, data) + + // don't ever re-use connections that had server errors. + // those sockets connect to the Bad Place! + if (response.socket && response.statusCode > 500) { + response.socket.destroy() + } + + if (response.headers['content-encoding'] !== 'gzip') { + return cb(er, response, data) + } + + zlib.gunzip(data, function (er, buf) { + if (er) return cb(er, response, data) + + cb(null, response, buf) + }) + } +} + +// cb(er, parsed, raw, response) +function requestDone (method, where, cb) { + return function (er, response, data) { + if (er) return cb(er) + + var urlObj = url.parse(where) + if (urlObj.auth) urlObj.auth = '***' + this.log.http(response.statusCode, url.format(urlObj)) + + if (Buffer.isBuffer(data)) { + data = data.toString() + } + + var parsed + if (data && typeof data === 'string' && response.statusCode !== 304) { + try { + parsed = JSON.parse(data) + } catch (ex) { + ex.message += '\n' + data + this.log.verbose('bad json', data) + this.log.error('registry', 'error parsing json') + return cb(ex, null, data, response) + } + } else if (data) { + parsed = data + data = JSON.stringify(parsed) + } + + // expect data with any error codes + if (!data && response.statusCode >= 400) { + var code = response.statusCode + return cb( + makeError(code + ' ' + STATUS_CODES[code], null, code), + null, + data, + response + ) + } + + er = null + if (parsed && response.headers.etag) { + parsed._etag = response.headers.etag + } + + if (parsed && response.headers['last-modified']) { + parsed._lastModified = response.headers['last-modified'] + } + + // for the search endpoint, the 'error' property can be an object + if (parsed && parsed.error && typeof parsed.error !== 'object' || + response.statusCode >= 400) { + var w = url.parse(where).pathname.substr(1) + var name + if (!w.match(/^-/)) { + w = w.split('/') + name = decodeURIComponent(w[w.indexOf('_rewrite') + 1]) + } + + if (!parsed.error) { + er = makeError( + 'Registry returned ' + response.statusCode + + ' for ' + method + + ' on ' + where, + name, + response.statusCode + ) + } else if (name && parsed.error === 'not_found') { + er = makeError('404 Not Found: ' + name, name, response.statusCode) + } else { + er = makeError( + parsed.error + ' ' + (parsed.reason || '') + ': ' + (name || w), + name, + response.statusCode + ) + } + } + return cb(er, parsed, data, response) + }.bind(this) +} + +function makeError (message, name, code) { + var er = new Error(message) + if (name) er.pkgid = name + if (code) { + er.statusCode = code + er.code = 'E' + code + } + return er +}