0
Fork 0
mirror of https://github.com/verdaccio/verdaccio.git synced 2025-01-06 22:40:26 -05:00

chore(flow): update flow definitions for proxy

This commit is contained in:
Juan Picado @jotadeveloper 2018-02-04 02:24:38 +01:00
parent 7e06ccc8ac
commit f7414e9bb2
No known key found for this signature in database
GPG key ID: 18AC54485952D158
6 changed files with 82 additions and 40 deletions

View file

@ -51,7 +51,7 @@
"@commitlint/cli": "^6.1.0",
"@commitlint/config-conventional": "^6.1.0",
"@commitlint/travis-cli": "^6.1.0",
"@verdaccio/types": "0.3.0",
"@verdaccio/types": "0.3.1",
"axios": "0.17.1",
"babel-cli": "6.26.0",
"babel-core": "6.26.0",

View file

@ -570,7 +570,8 @@ class Storage implements IStorageHandler {
}
if (err || !upLinkResponse) {
return cb(null, [err || Error(500, 'no data')]);
// $FlowFixMe
return cb(null, [err || Error('no data')]);
}
try {
@ -597,6 +598,7 @@ class Storage implements IStorageHandler {
try {
Storage._mergeVersions(packageInfo, upLinkResponse, self.config);
} catch(err) {
self.logger.error({
sub: 'out',

View file

@ -1,3 +1,5 @@
// @flow
import zlib from 'zlib';
import JSONStream from 'JSONStream';
import createError from 'http-errors';
@ -8,7 +10,17 @@ import URL from 'url';
import {parseInterval, is_object, ErrorCode} from './utils';
import {ReadTarball} from '@verdaccio/streams';
const Logger = require('./logger');
import type {
IProxy,
Config,
Callback,
Logger,
} from '@verdaccio/types';
import type {IUploadTarball} from '@verdaccio/streams';
const LoggerApi = require('./logger');
const encode = function(thing) {
return encodeURIComponent(thing).replace(/^%40/, '@');
@ -33,23 +45,37 @@ const setConfig = (config, key, def) => {
* Implements Storage interface
* (same for storage.js, local-storage.js, up-storage.js)
*/
class ProxyStorage {
class ProxyStorage implements IProxy {
config: Config;
failed_requests: number;
userAgent: string;
ca: string | void;
logger: Logger;
server_id: string;
url: any;
maxage: string;
timeout: string;
max_fails: number;
fail_timeout: number;
upname: string;
proxy: string;
last_request_time: number;
/**
* Constructor
* @param {*} config
* @param {*} mainConfig
*/
constructor(config, mainConfig) {
constructor(config: UpLinkConf, mainConfig: Config) {
this.config = config;
this.failed_requests = 0;
this.userAgent = mainConfig.user_agent;
this.ca = config.ca;
this.logger = Logger.logger.child({sub: 'out'});
this.logger = LoggerApi.logger.child({sub: 'out'});
this.server_id = mainConfig.server_id;
this.url = URL.parse(this.config.url);
// $FlowFixMe
this._setupProxy(this.url.hostname, config, mainConfig, this.url.protocol === 'https:');
this.config.url = this.config.url.replace(/\/$/, '');
@ -74,7 +100,7 @@ class ProxyStorage {
* @param {*} cb
* @return {Request}
*/
request(options, cb) {
request(options: any, cb: Callback) {
let json;
if (this._statusCheck() === false) {
@ -84,9 +110,10 @@ class ProxyStorage {
if (_.isFunction(cb)) {
cb(ErrorCode.get500('uplink is offline'));
}
// $FlowFixMe
streamRead.emit('error', createError('uplink is offline'));
});
// $FlowFixMe
streamRead._read = function() {};
// preventing 'Uncaught, unspecified "error" event'
streamRead.on('error', function() {});
@ -116,7 +143,7 @@ class ProxyStorage {
let requestCallback = cb ? (function(err, res, body) {
let error;
const responseLength = err ? 0 : body.length;
// $FlowFixMe
processBody(err, body);
logActivity();
cb(err, res, body);
@ -132,6 +159,7 @@ class ProxyStorage {
if (options.json && res.statusCode < 300) {
try {
// $FlowFixMe
body = JSON.parse(body.toString('utf8'));
} catch(_err) {
body = {};
@ -216,7 +244,7 @@ class ProxyStorage {
* @return {Object}
* @private
*/
_setHeaders(options) {
_setHeaders(options: any) {
const headers = options.headers || {};
const accept = 'Accept';
const acceptEncoding = 'Accept-Encoding';
@ -236,7 +264,7 @@ class ProxyStorage {
* @return {Object}
* @private
*/
_setAuth(headers) {
_setAuth(headers: any) {
if (_.isNil(this.config.auth) || headers['authorization']) {
return headers;
@ -248,7 +276,7 @@ class ProxyStorage {
// get NPM_TOKEN http://blog.npmjs.org/post/118393368555/deploying-with-npm-private-modules
// or get other variable export in env
let token = process.env.NPM_TOKEN;
let token: any = process.env.NPM_TOKEN;
if (this.config.auth.token) {
token = this.config.auth.token;
} else if (this.config.auth.token_env) {
@ -270,7 +298,7 @@ class ProxyStorage {
* @throws {Error}
* @private
*/
_throwErrorAuth(message) {
_throwErrorAuth(message: string) {
this.logger.error(message);
throw new Error(message);
}
@ -282,7 +310,7 @@ class ProxyStorage {
* @param {string} token
* @private
*/
_setHeaderAuthorization(headers, type, token) {
_setHeaderAuthorization(headers: any, type: string, token: string) {
if (type !== 'bearer' && type !== 'basic') {
this._throwErrorAuth(`Auth type '${type}' not allowed`);
}
@ -310,7 +338,7 @@ class ProxyStorage {
* @param {Object} headers
* @private
*/
_overrideWithUplinkConfigHeaders(headers) {
_overrideWithUplinkConfigHeaders(headers: any) {
// add/override headers specified in the config
for (let key in this.config.headers) {
if (Object.prototype.hasOwnProperty.call(this.config.headers, key)) {
@ -320,13 +348,15 @@ class ProxyStorage {
}
/**
* Determine whether can fetch from the provided URL.
* Determine whether can fetch from the provided URL
* @param {*} url
* @return {Boolean}
*/
isUplinkValid(url) {
url = URL.parse(url);
return url.protocol === this.url.protocol && url.host === this.url.host && url.path.indexOf(this.url.path) === 0;
isUplinkValid(url: string) {
// $FlowFixMe
url = URL.parse(url);
// $FlowFixMe
return url.protocol === this.url.protocol && url.host === this.url.host && url.path.indexOf(this.url.path) === 0;
}
/**
@ -335,7 +365,7 @@ class ProxyStorage {
* @param {*} options request options, eg: eTag.
* @param {*} callback
*/
getRemoteMetadata(name, options, callback) {
getRemoteMetadata(name: string, options: any, callback: Callback) {
const headers = {};
if (_.isNil(options.etag) === false) {
headers['If-None-Match'] = options.etag;
@ -355,7 +385,9 @@ class ProxyStorage {
return callback( ErrorCode.get404('package doesn\'t exist on uplink'));
}
if (!(res.statusCode >= 200 && res.statusCode < 300)) {
// $FlowFixMe
const error = createError(`bad status code: ${res.statusCode}`);
// $FlowFixMe
error.remoteStatus = res.statusCode;
return callback(error);
}
@ -368,7 +400,7 @@ class ProxyStorage {
* @param {String} url
* @return {Stream}
*/
fetchTarball(url) {
fetchTarball(url: string) {
const stream = new ReadTarball({});
let current_length = 0;
let expected_length;
@ -382,11 +414,12 @@ class ProxyStorage {
},
});
readStream.on('response', function(res) {
readStream.on('response', function(res: any) {
if (res.statusCode === 404) {
return stream.emit('error', ErrorCode.get404('file doesn\'t exist on uplink'));
}
if (!(res.statusCode >= 200 && res.statusCode < 300)) {
// $FlowFixMe
return stream.emit('error', createError('bad uplink status code: ' + res.statusCode));
}
if (res.headers['content-length']) {
@ -408,6 +441,7 @@ class ProxyStorage {
current_length += data.length;
}
if (expected_length && current_length != expected_length) {
// $FlowFixMe
stream.emit('error', createError('content length mismatch'));
}
});
@ -419,9 +453,9 @@ class ProxyStorage {
* @param {*} options request options
* @return {Stream}
*/
search(options) {
const transformStream = new Stream.PassThrough({objectMode: true});
const requestStream = this.request({
search(options: any) {
const transformStream: IUploadTarball = new Stream.PassThrough({objectMode: true});
const requestStream: IUploadTarball = this.request({
uri: options.req.url,
req: options.req,
headers: {
@ -437,6 +471,7 @@ class ProxyStorage {
requestStream.on('response', (res) => {
if (!String(res.statusCode).match(/^2\d\d$/)) {
// $FlowFixMe
return transformStream.emit('error', createError(`bad status code ${res.statusCode} from uplink`));
}
@ -471,7 +506,7 @@ class ProxyStorage {
* @param {*} req the http request
* @param {*} headers the request headers
*/
_addProxyHeaders(req, headers) {
_addProxyHeaders(req: any, headers: any) {
if (req) {
// Only submit X-Forwarded-For field if we don't have a proxy selected
// in the config file.
@ -502,7 +537,7 @@ class ProxyStorage {
* @param {*} alive
* @return {Boolean}
*/
_statusCheck(alive) {
_statusCheck(alive?: boolean) {
if (arguments.length === 0) {
return this._ifRequestFailure() === false;
} else {
@ -541,9 +576,9 @@ class ProxyStorage {
* @param {*} mainconfig
* @param {*} isHTTPS
*/
_setupProxy(hostname, config, mainconfig, isHTTPS) {
_setupProxy(hostname: string, config: UpLinkConf, mainconfig: Config, isHTTPS: boolean) {
let noProxyList;
let proxy_key = isHTTPS ? 'https_proxy' : 'http_proxy';
let proxy_key: string = isHTTPS ? 'https_proxy' : 'http_proxy';
// get http_proxy and no_proxy configs
if (proxy_key in config) {
@ -552,6 +587,7 @@ class ProxyStorage {
this.proxy = mainconfig[proxy_key];
}
if ('no_proxy' in config) {
// $FlowFixMe
noProxyList = config.no_proxy;
} else if ('no_proxy' in mainconfig) {
noProxyList = mainconfig.no_proxy;
@ -561,17 +597,22 @@ class ProxyStorage {
if (hostname[0] !== '.') {
hostname = '.' + hostname;
}
// $FlowFixMe
if (_.isString(noProxyList) && noProxyList.length) {
// $FlowFixMe
noProxyList = noProxyList.split(',');
}
if (_.isArray(noProxyList)) {
// $FlowFixMe
for (let i = 0; i < noProxyList.length; i++) {
// $FlowFixMe
let noProxyItem = noProxyList[i];
if (noProxyItem[0] !== '.') noProxyItem = '.' + noProxyItem;
if (hostname.lastIndexOf(noProxyItem) === hostname.length - noProxyItem.length) {
if (this.proxy) {
this.logger.debug({url: this.url.href, rule: noProxyItem},
'not using proxy for @{url}, excluded by @{rule} rule');
// $FlowFixMe
this.proxy = false;
}
break;

View file

@ -1,9 +1,7 @@
import assert from 'assert';
export default function(server, express) {
describe('test for unexpected client hangs', () => {
let on_tarball;
let handleResponseTarball;
beforeAll(function() {
express.get('/testexp-racycrash', function(request, response) {
@ -23,16 +21,17 @@ export default function(server, express) {
});
express.get('/testexp-racycrash/-/test.tar.gz', function(request, response) {
on_tarball(response);
handleResponseTarball(response);
});
});
test('should not crash on error if client disconnects', callback => {
on_tarball = function(res) {
handleResponseTarball = function(res) {
res.header('content-length', 1e6);
res.write('test test test\n');
res.write('test test test');
setTimeout(function() {
res.write('test test test\n');
res.write('-');
// destroy the connection
res.socket.destroy();
cb();
}, 200);
@ -40,7 +39,7 @@ export default function(server, express) {
server.request({uri: '/testexp-racycrash/-/test.tar.gz'})
.then(function(body) {
assert.equal(body, 'test test test\n');
expect(body).toEqual('test test test');
});
function cb() {
@ -54,7 +53,7 @@ export default function(server, express) {
});
test('should not store tarball', () => {
on_tarball = function(res) {
handleResponseTarball = function(res) {
res.socket.destroy();
};

View file

@ -13,7 +13,7 @@ describe('UpStorge', () => {
const uplinkDefault = {
url: 'https://registry.npmjs.org/'
};
let generateProxy = (config = uplinkDefault) => {
let generateProxy = (config: UpLinkConf = uplinkDefault) => {
const appConfig: Config = new AppConfig(configExample);
return new ProxyStorage(config, appConfig);

BIN
yarn.lock

Binary file not shown.