Added logging, changed some directory structure

This commit is contained in:
2018-01-13 21:33:40 -05:00
parent f079a5f067
commit 8e72ffb917
73656 changed files with 35284 additions and 53718 deletions

View File

@@ -0,0 +1,97 @@
# Changelog
## [v0.17.4](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.17.4)
- fix(ntlm authentication): fixed bug preventing proxying with ntlm authentication. ([#132](https://github.com/chimurai/http-proxy-middleware/pull/149)) (Thanks: [EladBezalel](https://github.com/EladBezalel), [oshri551](https://github.com/oshri551))
## [v0.17.3](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.17.3)
- fix(onError): improve default proxy error handling. http status codes (504, 502 and 500). ([#132](https://github.com/chimurai/http-proxy-middleware/pull/132)) ([graingert](https://github.com/graingert))
## [v0.17.2](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.17.2)
- feat(logging): improve error message & add link to Node errors page. ([#106](https://github.com/chimurai/http-proxy-middleware/pull/106)) ([cloudmu](https://github.com/cloudmu))
- feat(pathRewrite): path can be empty string. ([#110](https://github.com/chimurai/http-proxy-middleware/pull/110)) ([sunnylqm](https://github.com/sunnylqm))
- bug(websocket): memory leak when option 'ws:true' is used. ([#114](https://github.com/chimurai/http-proxy-middleware/pull/114)) ([julbra](https://github.com/julbra))
- chore(package.json): reduce package size. ([#109](https://github.com/chimurai/http-proxy-middleware/pull/109))
## [v0.17.1](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.17.1)
- fix(Express sub Router): 404 on non-proxy routes ([#94](https://github.com/chimurai/http-proxy-middleware/issues/94))
## [v0.17.0](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.17.0)
- fix(context matching): Use [RFC 3986 path](https://tools.ietf.org/html/rfc3986#section-3.3) in context matching. (excludes query parameters)
## [v0.16.0](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.16.0)
- deprecated(proxyTable): renamed `proxyTable` to `router`.
- feat(router): support for custom `router` function.
## [v0.15.2](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.15.2)
- fix(websocket): fixes websocket upgrade.
## [v0.15.1](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.15.1)
- feat(pathRewrite): expose `req` object to pathRewrite function.
- fix(websocket): fixes websocket upgrade when both config.ws and external .upgrade() are used.
## [v0.15.0](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.15.0)
- feat(pathRewrite): support for custom pathRewrite function.
## [v0.14.0](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.14.0)
- feat(proxy): support proxy creation without context.
- fix(connect mounting): use connect's `path` configuration to mount proxy.
## [v0.13.0](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.13.0)
- feat(context): custom context matcher; when simple `path` matching is not sufficient.
## [v0.12.0](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.12.0)
- add option `onProxyReqWs` (subscribe to http-proxy `proxyReqWs` event)
- add option `onOpen` (subscribe to http-proxy `open` event)
- add option `onClose` (subscribe to http-proxy `close` event)
## [v0.11.0](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.11.0)
- improved logging
## [v0.10.0](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.10.0)
- feat(proxyTable) - added proxyTable support for WebSockets.
- fixed(proxyTable) - ensure original path (not rewritten path) is being used when `proxyTable` is used in conjunction with `pathRewrite`.
## [v0.9.1](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.9.1)
- fix server crash when socket error not handled correctly.
## [v0.9.0](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.9.0)
- support subscribing to http-proxy `proxyReq` event ([trbngr](https://github.com/trbngr))
- add `logLevel` and `logProvider` support
## [v0.8.2](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.8.2)
- fix proxyError handler ([mTazelaar](https://github.com/mTazelaar))
## [v0.8.1](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.8.1)
- fix pathRewrite when `agent` is configured
## [v0.8.0](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.8.0)
- support external websocket upgrade
- fix websocket shorthand
## [v0.7.0](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.7.0)
- support shorthand syntax
- fix express/connect mounting
## [v0.6.0](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.6.0)
- support proxyTable
## [v0.5.0](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.5.0)
- support subscribing to http-proxy `error` event
- support subscribing to http-proxy `proxyRes` event
## [v0.4.0](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.4.0)
- support websocket
## [v0.3.0](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.3.0)
- support wildcard / glob
## [v0.2.0](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.2.0)
- support multiple paths
## [v0.1.0](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.1.0)
- support path rewrite
- deprecate proxyHost option
## [v0.0.5](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.0.5)
- initial release

View File

@@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright (c) 2015 Steven Chim
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,447 @@
# http-proxy-middleware
[![Build Status](https://img.shields.io/travis/chimurai/http-proxy-middleware/master.svg?style=flat-square)](https://travis-ci.org/chimurai/http-proxy-middleware)
[![Coveralls](https://img.shields.io/coveralls/chimurai/http-proxy-middleware.svg?style=flat-square)](https://coveralls.io/r/chimurai/http-proxy-middleware)
[![dependency Status](https://img.shields.io/david/chimurai/http-proxy-middleware.svg?style=flat-square)](https://david-dm.org/chimurai/http-proxy-middleware#info=dependencies)
[![dependency Status](https://snyk.io/test/npm/http-proxy-middleware/badge.svg)](https://snyk.io/test/npm/http-proxy-middleware)
Node.js proxying made simple. Configure proxy middleware with ease for [connect](https://github.com/senchalabs/connect), [express](https://github.com/strongloop/express), [browser-sync](https://github.com/BrowserSync/browser-sync) and [many more](#compatible-servers).
Powered by the popular Nodejitsu [`http-proxy`](https://github.com/nodejitsu/node-http-proxy). [![GitHub stars](https://img.shields.io/github/stars/nodejitsu/node-http-proxy.svg?style=social&label=Star)](https://github.com/nodejitsu/node-http-proxy)
## TL;DR
Proxy `/api` requests to `http://www.example.org`
```javascript
var express = require('express');
var proxy = require('http-proxy-middleware');
var app = express();
app.use('/api', proxy({target: 'http://www.example.org', changeOrigin: true}));
app.listen(3000);
// http://localhost:3000/api/foo/bar -> http://www.example.org/api/foo/bar
```
_All_ `http-proxy` [options](https://github.com/nodejitsu/node-http-proxy#options) can be used, along with some extra `http-proxy-middleware` [options](#options).
:bulb: **Tip:** Set the option `changeOrigin` to `true` for [name-based virtual hosted sites](http://en.wikipedia.org/wiki/Virtual_hosting#Name-based).
## Table of Contents
<!-- MarkdownTOC autolink=true bracket=round depth=2 -->
- [Install](#install)
- [Core concept](#core-concept)
- [Example](#example)
- [Context matching](#context-matching)
- [Options](#options)
- [http-proxy-middleware options](#http-proxy-middleware-options)
- [http-proxy events](#http-proxy-events)
- [http-proxy options](#http-proxy-options)
- [Shorthand](#shorthand)
- [app.use\(path, proxy\)](#appusepath-proxy)
- [WebSocket](#websocket)
- [External WebSocket upgrade](#external-websocket-upgrade)
- [Working examples](#working-examples)
- [Recipes](#recipes)
- [Compatible servers](#compatible-servers)
- [Tests](#tests)
- [Changelog](#changelog)
- [License](#license)
<!-- /MarkdownTOC -->
## Install
```javascript
$ npm install --save-dev http-proxy-middleware
```
## Core concept
Proxy middleware configuration.
#### proxy([context,] config)
```javascript
var proxy = require('http-proxy-middleware');
var apiProxy = proxy('/api', {target: 'http://www.example.org'});
// \____/ \_____________________________/
// | |
// context options
// 'apiProxy' is now ready to be used as middleware in a server.
```
* **context**: Determine which requests should be proxied to the target host.
(more on [context matching](#context-matching))
* **options.target**: target host to proxy to. _(protocol + host)_
(full list of [`http-proxy-middleware` configuration options](#options))
#### proxy(uri [, config])
``` javascript
// shorthand syntax for the example above:
var apiProxy = proxy('http://www.example.org/api');
```
More about the [shorthand configuration](#shorthand).
## Example
An example with `express` server.
```javascript
// include dependencies
var express = require('express');
var proxy = require('http-proxy-middleware');
// proxy middleware options
var options = {
target: 'http://www.example.org', // target host
changeOrigin: true, // needed for virtual hosted sites
ws: true, // proxy websockets
pathRewrite: {
'^/api/old-path' : '/api/new-path', // rewrite path
'^/api/remove/path' : '/path' // remove base path
},
router: {
// when request.headers.host == 'dev.localhost:3000',
// override target 'http://www.example.org' to 'http://localhost:8000'
'dev.localhost:3000' : 'http://localhost:8000'
}
};
// create the proxy (without context)
var exampleProxy = proxy(options);
// mount `exampleProxy` in web server
var app = express();
app.use('/api', exampleProxy);
app.listen(3000);
```
## Context matching
Providing an alternative way to decide which requests should be proxied; In case you are not able to use the server's [`path` parameter](http://expressjs.com/en/4x/api.html#app.use) to mount the proxy or when you need more flexibility.
The [RFC 3986 `path`](https://tools.ietf.org/html/rfc3986#section-3.3) is be used for context matching.
```
foo://example.com:8042/over/there?name=ferret#nose
\_/ \______________/\_________/ \_________/ \__/
| | | | |
scheme authority path query fragment
```
* **path matching**
- `proxy({...})` - matches any path, all requests will be proxied.
- `proxy('/', {...})` - matches any path, all requests will be proxied.
- `proxy('/api', {...})` - matches paths starting with `/api`
* **multiple path matching**
- `proxy(['/api', '/ajax', '/someotherpath'], {...})`
* **wildcard path matching**
For fine-grained control you can use wildcard matching. Glob pattern matching is done by _micromatch_. Visit [micromatch](https://www.npmjs.com/package/micromatch) or [glob](https://www.npmjs.com/package/glob) for more globbing examples.
- `proxy('**', {...})` matches any path, all requests will be proxied.
- `proxy('**/*.html', {...})` matches any path which ends with `.html`
- `proxy('/*.html', {...})` matches paths directly under path-absolute
- `proxy('/api/**/*.html', {...})` matches requests ending with `.html` in the path of `/api`
- `proxy(['/api/**', '/ajax/**'], {...})` combine multiple patterns
- `proxy(['/api/**', '!**/bad.json'], {...})` exclusion
* **custom matching**
For full control you can provide a custom function to determine which requests should be proxied or not.
```javascript
/**
* @return {Boolean}
*/
var filter = function (pathname, req) {
return (pathname.match('^/api') && req.method === 'GET');
};
var apiProxy = proxy(filter, {target: 'http://www.example.org'})
```
## Options
### http-proxy-middleware options
* **option.pathRewrite**: object/function, rewrite target's url path. Object-keys will be used as _RegExp_ to match paths.
```javascript
// rewrite path
pathRewrite: {'^/old/api' : '/new/api'}
// remove path
pathRewrite: {'^/remove/api' : ''}
// add base path
pathRewrite: {'^/' : '/basepath/'}
// custom rewriting
pathRewrite: function (path, req) { return path.replace('/api', '/base/api') }
```
* **option.router**: object/function, re-target `option.target` for specific requests.
```javascript
// Use `host` and/or `path` to match requests. First match will be used.
// The order of the configuration matters.
router: {
'integration.localhost:3000' : 'http://localhost:8001', // host only
'staging.localhost:3000' : 'http://localhost:8002', // host only
'localhost:3000/api' : 'http://localhost:8003', // host + path
'/rest' : 'http://localhost:8004' // path only
}
// Custom router function
router: function(req) {
return 'http://localhost:8004';
}
```
* **option.logLevel**: string, ['debug', 'info', 'warn', 'error', 'silent']. Default: `'info'`
* **option.logProvider**: function, modify or replace log provider. Default: `console`.
```javascript
// simple replace
function logProvider(provider) {
// replace the default console log provider.
return require('winston');
}
```
```javascript
// verbose replacement
function logProvider(provider) {
var logger = new (require('winston').Logger)();
var myCustomProvider = {
log: logger.log,
debug: logger.debug,
info: logger.info,
warn: logger.warn,
error: logger.error
}
return myCustomProvider;
}
```
* (DEPRECATED) **option.proxyHost**: Use `option.changeOrigin = true` instead.
* (DEPRECATED) **option.proxyTable**: Use `option.router` instead.
### http-proxy events
Subscribe to [http-proxy events](https://github.com/nodejitsu/node-http-proxy#listening-for-proxy-events):
* **option.onError**: function, subscribe to http-proxy's `error` event for custom error handling.
```javascript
function onError(err, req, res) {
res.writeHead(500, {
'Content-Type': 'text/plain'
});
res.end('Something went wrong. And we are reporting a custom error message.');
}
```
* **option.onProxyRes**: function, subscribe to http-proxy's `proxyRes` event.
```javascript
function onProxyRes(proxyRes, req, res) {
proxyRes.headers['x-added'] = 'foobar'; // add new header to response
delete proxyRes.headers['x-removed']; // remove header from response
}
```
* **option.onProxyReq**: function, subscribe to http-proxy's `proxyReq` event.
```javascript
function onProxyReq(proxyReq, req, res) {
// add custom header to request
proxyReq.setHeader('x-added', 'foobar');
// or log the req
}
```
* **option.onProxyReqWs**: function, subscribe to http-proxy's `proxyReqWs` event.
```javascript
function onProxyReqWs(proxyReq, req, socket, options, head) {
// add custom header
proxyReq.setHeader('X-Special-Proxy-Header', 'foobar');
}
```
* **option.onOpen**: function, subscribe to http-proxy's `open` event.
```javascript
function onOpen(proxySocket) {
// listen for messages coming FROM the target here
proxySocket.on('data', hybiParseAndLogMessage);
}
```
* **option.onClose**: function, subscribe to http-proxy's `close` event.
```javascript
function onClose(res, socket, head) {
// view disconnected websocket connections
console.log('Client disconnected');
}
```
### http-proxy options
The following options are provided by the underlying [http-proxy](https://github.com/nodejitsu/node-http-proxy#options) library.
* **option.target**: url string to be parsed with the url module
* **option.forward**: url string to be parsed with the url module
* **option.agent**: object to be passed to http(s).request (see Node's [https agent](http://nodejs.org/api/https.html#https_class_https_agent) and [http agent](http://nodejs.org/api/http.html#http_class_http_agent) objects)
* **option.ssl**: object to be passed to https.createServer()
* **option.ws**: true/false: if you want to proxy websockets
* **option.xfwd**: true/false, adds x-forward headers
* **option.secure**: true/false, if you want to verify the SSL Certs
* **option.toProxy**: true/false, passes the absolute URL as the `path` (useful for proxying to proxies)
* **option.prependPath**: true/false, Default: true - specify whether you want to prepend the target's path to the proxy path
* **option.ignorePath**: true/false, Default: false - specify whether you want to ignore the proxy path of the incoming request (note: you will have to append / manually if required).
* **option.localAddress** : Local interface string to bind for outgoing connections
* **option.changeOrigin**: true/false, Default: false - changes the origin of the host header to the target URL
* **option.auth** : Basic authentication i.e. 'user:password' to compute an Authorization header.
* **option.hostRewrite**: rewrites the location hostname on (301/302/307/308) redirects.
* **option.autoRewrite**: rewrites the location host/port on (301/302/307/308) redirects based on requested host/port. Default: false.
* **option.protocolRewrite**: rewrites the location protocol on (301/302/307/308) redirects to 'http' or 'https'. Default: null.
* **option.cookieDomainRewrite**: rewrites domain of `set-cookie` headers. Possible values:
* `false` (default): disable cookie rewriting
* String: new domain, for example `cookieDomainRewrite: "new.domain"`. To remove the domain, use `cookieDomainRewrite: ""`.
* Object: mapping of domains to new domains, use `"*"` to match all domains.
For example keep one domain unchanged, rewrite one domain and remove other domains:
```
cookieDomainRewrite: {
"unchanged.domain": "unchanged.domain",
"old.domain": "new.domain",
"*": ""
}
```
* **option.headers**: object, adds [request headers](https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#Request_fields). (Example: `{host:'www.example.org'}`)
* **option.proxyTimeout**: timeout (in millis) when proxy receives no response from target
## Shorthand
Use the shorthand syntax when verbose configuration is not needed. The `context` and `option.target` will be automatically configured when shorthand is used. Options can still be used if needed.
```javascript
proxy('http://www.example.org:8000/api');
// proxy('/api', {target: 'http://www.example.org:8000'});
proxy('http://www.example.org:8000/api/books/*/**.json');
// proxy('/api/books/*/**.json', {target: 'http://www.example.org:8000'});
proxy('http://www.example.org:8000/api', {changeOrigin:true});
// proxy('/api', {target: 'http://www.example.org:8000', changeOrigin: true});
```
### app.use(path, proxy)
If you want to use the server's `app.use` `path` parameter to match requests;
Create and mount the proxy without the http-proxy-middleware `context` parameter:
```javascript
app.use('/api', proxy({target:'http://www.example.org', changeOrigin:true}));
```
`app.use` documentation:
* express: http://expressjs.com/en/4x/api.html#app.use
* connect: https://github.com/senchalabs/connect#mount-middleware
## WebSocket
```javascript
// verbose api
proxy('/', {target:'http://echo.websocket.org', ws:true});
// shorthand
proxy('http://echo.websocket.org', {ws:true});
// shorter shorthand
proxy('ws://echo.websocket.org');
```
### External WebSocket upgrade
In the previous WebSocket examples, http-proxy-middleware relies on a initial http request in order to listen to the http `upgrade` event. If you need to proxy WebSockets without the initial http request, you can subscribe to the server's http `upgrade` event manually.
```javascript
var wsProxy = proxy('ws://echo.websocket.org', {changeOrigin:true});
var app = express();
app.use(wsProxy);
var server = app.listen(3000);
server.on('upgrade', wsProxy.upgrade); // <-- subscribe to http 'upgrade'
```
## Working examples
View and play around with [working examples](https://github.com/chimurai/http-proxy-middleware/tree/master/examples).
* Browser-Sync ([example source](https://github.com/chimurai/http-proxy-middleware/tree/master/examples/browser-sync/index.js))
* express ([example source](https://github.com/chimurai/http-proxy-middleware/tree/master/examples/express/index.js))
* connect ([example source](https://github.com/chimurai/http-proxy-middleware/tree/master/examples/connect/index.js))
* WebSocket ([example source](https://github.com/chimurai/http-proxy-middleware/tree/master/examples/websocket/index.js))
## Recipes
View the [recipes](https://github.com/chimurai/http-proxy-middleware/tree/master/recipes) for common use cases.
## Compatible servers
`http-proxy-middleware` is compatible with the following servers:
* [connect](https://www.npmjs.com/package/connect)
* [express](https://www.npmjs.com/package/express)
* [browser-sync](https://www.npmjs.com/package/browser-sync)
* [lite-server](https://www.npmjs.com/package/lite-server)
* [grunt-contrib-connect](https://www.npmjs.com/package/grunt-contrib-connect)
* [grunt-browser-sync](https://www.npmjs.com/package/grunt-browser-sync)
* [gulp-connect](https://www.npmjs.com/package/gulp-connect)
* [gulp-webserver](https://www.npmjs.com/package/gulp-webserver)
Sample implementations can be found in the [server recipes](https://github.com/chimurai/http-proxy-middleware/tree/master/recipes/servers.md).
## Tests
Run the test suite:
```bash
# install dependencies
$ npm install
```
unit testing
```bash
# unit tests
$ npm test
```
coverage
```bash
# code coverage
$ npm run cover
```
## Changelog
- [View changelog](https://github.com/chimurai/http-proxy-middleware/blob/master/CHANGELOG.md)
## License
The MIT License (MIT)
Copyright (c) 2015-2017 Steven Chim

View File

@@ -0,0 +1,5 @@
var HPM = require('./lib');
module.exports = function(context, opts) {
return new HPM(context, opts);
};

View File

@@ -0,0 +1,126 @@
var _ = require('lodash');
var url = require('url');
var logger = require('./logger').getInstance();
module.exports = {
createConfig: createConfig
};
function createConfig(context, opts) {
// structure of config object to be returned
var config = {
context: undefined,
options: {}
};
// app.use('/api', proxy({target:'http://localhost:9000'}));
if (isContextless(context, opts)) {
config.context = '/';
config.options = _.assign(config.options, context);
}
// app.use('/api', proxy('http://localhost:9000'));
// app.use(proxy('http://localhost:9000/api'));
else if (isStringShortHand(context)) {
var oUrl = url.parse(context);
var target = [oUrl.protocol, '//', oUrl.host].join('');
config.context = oUrl.pathname || '/';
config.options = _.assign(config.options, {target: target}, opts);
if (oUrl.protocol === 'ws:' || oUrl.protocol === 'wss:') {
config.options.ws = true;
}
// app.use('/api', proxy({target:'http://localhost:9000'}));
} else {
config.context = context;
config.options = _.assign(config.options, opts);
}
configureLogger(config.options);
if (!config.options.target) {
throw new Error('[HPM] Missing "target" option. Example: {target: "http://www.example.org"}');
}
// Legacy option.proxyHost
config.options = mapLegacyProxyHostOption(config.options);
// Legacy option.proxyTable > option.router
config.options = mapLegacyProxyTableOption(config.options);
return config;
}
/**
* Checks if a String only target/config is provided.
* This can be just the host or with the optional path.
*
* @example
* app.use('/api', proxy('http://localhost:9000'));
app.use(proxy('http://localhost:9000/api'));
*
* @param {String} context [description]
* @return {Boolean} [description]
*/
function isStringShortHand(context) {
if (_.isString(context)) {
return (url.parse(context).host) ? true : false;
}
}
/**
* Checks if a Object only config is provided, without a context.
* In this case the all paths will be proxied.
*
* @example
* app.use('/api', proxy({target:'http://localhost:9000'}));
*
* @param {Object} context [description]
* @param {*} opts [description]
* @return {Boolean} [description]
*/
function isContextless(context, opts) {
return (_.isPlainObject(context) && _.isEmpty(opts));
}
function mapLegacyProxyHostOption(options) {
// set options.headers.host when option.proxyHost is provided
if (options.proxyHost) {
logger.warn('*************************************');
logger.warn('[HPM] Deprecated "option.proxyHost"');
logger.warn(' Use "option.changeOrigin" or "option.headers.host" instead');
logger.warn(' "option.proxyHost" will be removed in future release.');
logger.warn('*************************************');
options.headers = options.headers || {};
options.headers.host = options.proxyHost;
}
return options;
}
// Warn deprecated proxyTable api usage
function mapLegacyProxyTableOption(options) {
if (options.proxyTable) {
logger.warn('*************************************');
logger.warn('[HPM] Deprecated "option.proxyTable"');
logger.warn(' Use "option.router" instead');
logger.warn(' "option.proxyTable" will be removed in future release.');
logger.warn('*************************************');
options.router = _.clone(options.proxyTable);
_.omit(options, 'proxyTable');
}
return options;
}
function configureLogger(options) {
if (options.logLevel) {
logger.setLevel(options.logLevel);
}
if (options.logProvider) {
logger.setProvider(options.logProvider);
}
}

View File

@@ -0,0 +1,94 @@
var _ = require('lodash');
var url = require('url');
var isGlob = require('is-glob');
var micromatch = require('micromatch');
module.exports = {
match: matchContext
};
function matchContext(context, uri, req) {
// single path
if (isStringPath(context)) {
return matchSingleStringPath(context, uri);
}
// single glob path
if (isGlobPath(context)) {
return matchSingleGlobPath(context, uri);
}
// multi path
if (Array.isArray(context)) {
if (context.every(isStringPath)) {
return matchMultiPath(context, uri);
}
if (context.every(isGlobPath)) {
return matchMultiGlobPath(context, uri);
}
throw new Error('[HPM] Invalid context. Expecting something like: ["/api", "/ajax"] or ["/api/**", "!**.html"]');
}
// custom matching
if (_.isFunction(context)) {
var pathname = getUrlPathName(uri);
return context(pathname, req);
}
throw new Error('[HPM] Invalid context. Expecting something like: "/api" or ["/api", "/ajax"]');
}
/**
* @param {String} context '/api'
* @param {String} uri 'http://example.org/api/b/c/d.html'
* @return {Boolean}
*/
function matchSingleStringPath(context, uri) {
var pathname = getUrlPathName(uri);
return pathname.indexOf(context) === 0;
}
function matchSingleGlobPath(pattern, uri) {
var pathname = getUrlPathName(uri);
var matches = micromatch(pathname, pattern);
return matches && (matches.length > 0);
}
function matchMultiGlobPath(patternList, uri) {
return matchSingleGlobPath(patternList, uri);
}
/**
* @param {String} context ['/api', '/ajax']
* @param {String} uri 'http://example.org/api/b/c/d.html'
* @return {Boolean}
*/
function matchMultiPath(contextList, uri) {
for (var i = 0; i < contextList.length; i++) {
var context = contextList[i];
if (matchSingleStringPath(context, uri)) {
return true;
}
}
return false;
}
/**
* Parses URI and returns RFC 3986 path
*
* @param {String} uri from req.url
* @return {String} RFC 3986 path
*/
function getUrlPathName(uri) {
return uri && url.parse(uri).pathname;
}
function isStringPath(context) {
return _.isString(context) && !isGlob(context);
}
function isGlobPath(context) {
return isGlob(context);
}

View File

@@ -0,0 +1,74 @@
var _ = require('lodash');
var logger = require('./logger').getInstance();
module.exports = {
init: init,
getHandlers: getProxyEventHandlers
};
function init(proxy, opts) {
var handlers = getProxyEventHandlers(opts);
_.forIn(handlers, function(handler, eventName) {
proxy.on(eventName, handlers[eventName]);
});
logger.debug('[HPM] Subscribed to http-proxy events: ', _.keys(handlers));
}
function getProxyEventHandlers(opts) {
// https://github.com/nodejitsu/node-http-proxy#listening-for-proxy-events
var proxyEvents = ['error', 'proxyReq', 'proxyReqWs', 'proxyRes', 'open', 'close'];
var handlers = {};
_.forEach(proxyEvents, function(event) {
// all handlers for the http-proxy events are prefixed with 'on'.
// loop through options and try to find these handlers
// and add them to the handlers object for subscription in init().
var eventName = _.camelCase('on ' + event);
var fnHandler = _.get(opts, eventName);
if (_.isFunction(fnHandler)) {
handlers[event] = fnHandler;
}
});
// add default error handler in absence of error handler
if (!_.isFunction(handlers.error)) {
handlers.error = defaultErrorHandler;
}
// add default close handler in absence of close handler
if (!_.isFunction(handlers.close)) {
handlers.close = logClose;
}
return handlers;
};
function defaultErrorHandler(err, req, res) {
var host = (req.headers && req.headers.host);
var code = err.code;
if (res.writeHead && !res.headersSent) {
if (/HPE_INVALID/.test(code)) {
res.writeHead(502);
} else {
switch(code) {
case 'ECONNRESET':
case 'ENOTFOUND':
case 'ECONNREFUSED':
res.writeHead(504);
break;
default: res.writeHead(500);
}
}
}
res.end('Error occured while trying to proxy to: ' + host + req.url);
}
function logClose(req, socket, head) {
// view disconnected websocket connections
logger.info('[HPM] Client disconnected');
}

View File

@@ -0,0 +1,147 @@
var _ = require('lodash');
var httpProxy = require('http-proxy');
var configFactory = require('./config-factory');
var handlers = require('./handlers');
var contextMatcher = require('./context-matcher');
var PathRewriter = require('./path-rewriter');
var Router = require('./router');
var logger = require('./logger').getInstance();
var getArrow = require('./logger').getArrow;
module.exports = HttpProxyMiddleware;
function HttpProxyMiddleware(context, opts) {
// https://github.com/chimurai/http-proxy-middleware/issues/57
var wsUpgradeDebounced = _.debounce(handleUpgrade);
var wsInitialized = false;
var config = configFactory.createConfig(context, opts);
var proxyOptions = config.options;
// create proxy
var proxy = httpProxy.createProxyServer({});
logger.info('[HPM] Proxy created:', config.context, ' -> ', proxyOptions.target);
var pathRewriter = PathRewriter.create(proxyOptions.pathRewrite); // returns undefined when "pathRewrite" is not provided
// attach handler to http-proxy events
handlers.init(proxy, proxyOptions);
// log errors for debug purpose
proxy.on('error', logError);
// https://github.com/chimurai/http-proxy-middleware/issues/19
// expose function to upgrade externally
middleware.upgrade = wsUpgradeDebounced;
return middleware;
function middleware(req, res, next) {
if (shouldProxy(config.context, req)) {
var activeProxyOptions = prepareProxyRequest(req);
proxy.web(req, res, activeProxyOptions);
} else {
next();
}
if (proxyOptions.ws === true) {
// use initial request to access the server object to subscribe to http upgrade event
catchUpgradeRequest(req.connection.server);
}
}
function catchUpgradeRequest(server) {
// subscribe once; don't subscribe on every request...
// https://github.com/chimurai/http-proxy-middleware/issues/113
if (!wsInitialized) {
server.on('upgrade', wsUpgradeDebounced);
wsInitialized = true;
}
}
function handleUpgrade(req, socket, head) {
// set to initialized when used externally
wsInitialized = true;
if (shouldProxy(config.context, req)) {
var activeProxyOptions = prepareProxyRequest(req);
proxy.ws(req, socket, head, activeProxyOptions);
logger.info('[HPM] Upgrading to WebSocket');
}
}
/**
* Determine whether request should be proxied.
*
* @private
* @return {Boolean}
*/
function shouldProxy(context, req) {
var path = (req.originalUrl || req.url);
return contextMatcher.match(context, path, req);
}
/**
* Apply option.router and option.pathRewrite
* Order matters:
Router uses original path for routing;
NOT the modified path, after it has been rewritten by pathRewrite
*/
function prepareProxyRequest(req) {
// https://github.com/chimurai/http-proxy-middleware/issues/17
// https://github.com/chimurai/http-proxy-middleware/issues/94
req.url = (req.originalUrl || req.url);
// store uri before it gets rewritten for logging
var originalPath = req.url;
var newProxyOptions = _.assign({}, proxyOptions);
// Apply in order:
// 1. option.router
// 2. option.pathRewrite
__applyRouter(req, newProxyOptions);
__applyPathRewrite(req, pathRewriter);
// debug logging for both http(s) and websockets
if (proxyOptions.logLevel === 'debug') {
var arrow = getArrow(originalPath, req.url, proxyOptions.target, newProxyOptions.target);
logger.debug('[HPM] %s %s %s %s', req.method, originalPath, arrow, newProxyOptions.target);
}
return newProxyOptions;
}
// Modify option.target when router present.
function __applyRouter(req, options) {
var newTarget;
if (options.router) {
newTarget = Router.getTarget(req, options);
if (newTarget) {
logger.debug('[HPM] Router new target: %s -> "%s"', options.target, newTarget);
options.target = newTarget;
}
}
}
// rewrite path
function __applyPathRewrite(req, pathRewriter) {
if (pathRewriter) {
var path = pathRewriter(req.url, req);
if (typeof path === 'string') {
req.url = path;
} else {
logger.info('[HPM] pathRewrite: No rewritten path found. (%s)', req.url);
}
}
}
function logError(err, req, res) {
var hostname = (req.headers && req.headers.host) || (req.hostname || req.host); // (websocket) || (node0.10 || node 4/5)
var target = proxyOptions.target.host || proxyOptions.target;
var errReference = 'https://nodejs.org/api/errors.html#errors_common_system_errors'; // link to Node Common Systems Errors page
logger.error('[HPM] Error occurred while trying to proxy request %s from %s to %s (%s) (%s)', req.url, hostname, target, err.code, errReference);
}
};

View File

@@ -0,0 +1,158 @@
var util = require('util');
var _ = require('lodash');
var loggerInstance;
var defaultProvider = {
log: console.log,
debug: console.log, // use .log(); since console does not have .debug()
info: console.info,
warn: console.warn,
error: console.error
};
// log level 'weight'
var LEVELS = {
debug: 10,
info: 20,
warn: 30,
error: 50,
silent: 80
};
module.exports = {
// singleton
getInstance: function() {
if (!loggerInstance) {
loggerInstance = new Logger();
}
return loggerInstance;
},
getArrow: getArrow
};
function Logger() {
var logLevel;
var provider;
var api = {
log: log,
debug: debug,
info: info,
warn: warn,
error: error,
setLevel: function(v) {
if (isValidLevel(v)) {
logLevel = v;
}
},
setProvider: function(fn) {
if (fn && isValidProvider(fn)) {
provider = fn(defaultProvider);
}
}
};
init();
return api;
function init() {
api.setLevel('info');
api.setProvider(function() {
return defaultProvider;
});
}
// log will log messages, regardless of logLevels
function log() {
provider.log(_interpolate.apply(null, arguments));
}
function debug() {
if (_showLevel('debug')) {
provider.debug(_interpolate.apply(null, arguments));
}
}
function info() {
if (_showLevel('info')) {
provider.info(_interpolate.apply(null, arguments));
}
}
function warn() {
if (_showLevel('warn')) {
provider.warn(_interpolate.apply(null, arguments));
}
}
function error() {
if (_showLevel('error')) {
provider.error(_interpolate.apply(null, arguments));
}
}
/**
* Decide to log or not to log, based on the log levels 'weight'
* @param {String} showLevel [debug, info, warn, error, silent]
* @return {Boolean}
*/
function _showLevel(showLevel) {
var result = false;
var currentLogLevel = LEVELS[logLevel];
if (currentLogLevel && (currentLogLevel <= LEVELS[showLevel])) {
result = true;
}
return result;
}
// make sure logged messages and its data are return interpolated
// make it possible for additional log data, such date/time or custom prefix.
function _interpolate() {
var fn = _.spread(util.format);
var result = fn(_.slice(arguments));
return result;
}
function isValidProvider(fnProvider) {
var result = true;
if (fnProvider && !_.isFunction(fnProvider)) {
throw new Error('[HPM] Log provider config error. Expecting a function.');
}
return result;
}
function isValidLevel(levelName) {
var validLevels = _.keys(LEVELS);
var isValid = _.includes(validLevels, levelName);
if (!isValid) {
throw new Error('[HPM] Log level error. Invalid logLevel.');
}
return isValid;
}
}
/**
* -> normal proxy
* => router
* ~> pathRewrite
* ≈> router + pathRewrite
*/
function getArrow(originalPath, newPath, originalTarget, newTarget) {
var arrow = ['>'];
var isNewTarget = (originalTarget !== newTarget); // router
var isNewPath = (originalPath !== newPath); // pathRewrite
if (isNewPath && !isNewTarget) {arrow.unshift('~');} else if (!isNewPath && isNewTarget) {arrow.unshift('=');} else if (isNewPath && isNewTarget) {arrow.unshift('≈');} else {arrow.unshift('-');}
return arrow.join('');
}

View File

@@ -0,0 +1,72 @@
var _ = require('lodash');
var logger = require('./logger').getInstance();
module.exports = {
create: createPathRewriter
};
/**
* Create rewrite function, to cache parsed rewrite rules.
*
* @returns {function} Function to rewrite paths; This function should accept `path` (request.url) as parameter
*/
function createPathRewriter(rewriteConfig) {
var rulesCache;
if (!isValidRewriteConfig(rewriteConfig)) {
return;
}
if (_.isFunction(rewriteConfig)) {
var customRewriteFn = rewriteConfig;
return customRewriteFn;
} else {
rulesCache = parsePathRewriteRules(rewriteConfig);
return rewritePath;
}
function rewritePath(path) {
var result = path;
_.forEach(rulesCache, function(rule) {
if (rule.regex.test(path)) {
result = result.replace(rule.regex, rule.value);
logger.debug('[HPM] Rewriting path from "%s" to "%s"', path, result);
return false;
}
});
return result;
}
}
function isValidRewriteConfig(rewriteConfig) {
if (_.isFunction(rewriteConfig)) {
return true;
} else if (!_.isEmpty(rewriteConfig) && _.isPlainObject(rewriteConfig)) {
return true;
} else if (_.isUndefined(rewriteConfig) ||
_.isNull(rewriteConfig) ||
_.isEqual(rewriteConfig, {})) {
return false;
} else {
throw new Error('[HPM] Invalid pathRewrite config. Expecting object with pathRewrite config or a rewrite function');
}
}
function parsePathRewriteRules(rewriteConfig) {
var rules = [];
if (_.isPlainObject(rewriteConfig)) {
_.forIn(rewriteConfig, function(value, key) {
rules.push({
regex: new RegExp(key),
value: rewriteConfig[key]
});
logger.info('[HPM] Proxy rewrite rule created: "%s" ~> "%s"', key, rewriteConfig[key]);
});
}
return rules;
}

View File

@@ -0,0 +1,53 @@
var _ = require('lodash');
var logger = require('./logger.js').getInstance();
module.exports = {
getTarget: getTarget
};
function getTarget(req, config) {
var newTarget;
var router = config.router;
if (_.isPlainObject(router)) {
newTarget = getTargetFromProxyTable(req, router);
} else if (_.isFunction(router)) {
newTarget = router(req);
}
return newTarget;
}
function getTargetFromProxyTable(req, table) {
var result;
var host = req.headers.host;
var path = req.url;
var hostAndPath = host + path;
_.forIn(table, function(value, key) {
if (containsPath(key)) {
if (hostAndPath.indexOf(key) > -1) { // match 'localhost:3000/api'
result = table[key];
logger.debug('[HPM] Router table match: "%s"', key);
return false;
}
} else {
if (key === host) { // match 'localhost:3000'
result = table[key];
logger.debug('[HPM] Router table match: "%s"', host);
return false;
}
}
});
return result;
}
function containsPath(v) {
return v.indexOf('/') > -1;
}

View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2014-2016, Jon Schlinkert
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -0,0 +1,107 @@
# is-extglob [![NPM version](https://img.shields.io/npm/v/is-extglob.svg?style=flat)](https://www.npmjs.com/package/is-extglob) [![NPM downloads](https://img.shields.io/npm/dm/is-extglob.svg?style=flat)](https://npmjs.org/package/is-extglob) [![Build Status](https://img.shields.io/travis/jonschlinkert/is-extglob.svg?style=flat)](https://travis-ci.org/jonschlinkert/is-extglob)
> Returns true if a string has an extglob.
## Install
Install with [npm](https://www.npmjs.com/):
```sh
$ npm install --save is-extglob
```
## Usage
```js
var isExtglob = require('is-extglob');
```
**True**
```js
isExtglob('?(abc)');
isExtglob('@(abc)');
isExtglob('!(abc)');
isExtglob('*(abc)');
isExtglob('+(abc)');
```
**False**
Escaped extglobs:
```js
isExtglob('\\?(abc)');
isExtglob('\\@(abc)');
isExtglob('\\!(abc)');
isExtglob('\\*(abc)');
isExtglob('\\+(abc)');
```
Everything else...
```js
isExtglob('foo.js');
isExtglob('!foo.js');
isExtglob('*.js');
isExtglob('**/abc.js');
isExtglob('abc/*.js');
isExtglob('abc/(aaa|bbb).js');
isExtglob('abc/[a-z].js');
isExtglob('abc/{a,b}.js');
isExtglob('abc/?.js');
isExtglob('abc.js');
isExtglob('abc/def/ghi.js');
```
## History
**v2.0**
Adds support for escaping. Escaped exglobs no longer return true.
## About
### Related projects
* [has-glob](https://www.npmjs.com/package/has-glob): Returns `true` if an array has a glob pattern. | [homepage](https://github.com/jonschlinkert/has-glob "Returns `true` if an array has a glob pattern.")
* [is-glob](https://www.npmjs.com/package/is-glob): Returns `true` if the given string looks like a glob pattern or an extglob pattern… [more](https://github.com/jonschlinkert/is-glob) | [homepage](https://github.com/jonschlinkert/is-glob "Returns `true` if the given string looks like a glob pattern or an extglob pattern. This makes it easy to create code that only uses external modules like node-glob when necessary, resulting in much faster code execution and initialization time, and a bet")
* [micromatch](https://www.npmjs.com/package/micromatch): Glob matching for javascript/node.js. A drop-in replacement and faster alternative to minimatch and multimatch. | [homepage](https://github.com/jonschlinkert/micromatch "Glob matching for javascript/node.js. A drop-in replacement and faster alternative to minimatch and multimatch.")
### Contributing
Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
### Building docs
_(This document was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme) (a [verb](https://github.com/verbose/verb) generator), please don't edit the readme directly. Any changes to the readme must be made in [.verb.md](.verb.md).)_
To generate the readme and API documentation with [verb](https://github.com/verbose/verb):
```sh
$ npm install -g verb verb-generate-readme && verb
```
### Running tests
Install dev dependencies:
```sh
$ npm install -d && npm test
```
### Author
**Jon Schlinkert**
* [github/jonschlinkert](https://github.com/jonschlinkert)
* [twitter/jonschlinkert](http://twitter.com/jonschlinkert)
### License
Copyright © 2016, [Jon Schlinkert](https://github.com/jonschlinkert).
Released under the [MIT license](https://github.com/jonschlinkert/is-extglob/blob/master/LICENSE).
***
_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.1.31, on October 12, 2016._

View File

@@ -0,0 +1,20 @@
/*!
* is-extglob <https://github.com/jonschlinkert/is-extglob>
*
* Copyright (c) 2014-2016, Jon Schlinkert.
* Licensed under the MIT License.
*/
module.exports = function isExtglob(str) {
if (typeof str !== 'string' || str === '') {
return false;
}
var match;
while ((match = /(\\).|([@?!+*]\(.*\))/g.exec(str))) {
if (match[2]) return true;
str = str.slice(match.index + match[0].length);
}
return false;
};

View File

@@ -0,0 +1,103 @@
{
"_args": [
[
"is-extglob@2.1.1",
"C:\\Users\\deranjer\\go\\src\\github.com\\deranjer\\goTorrent\\torrent-project"
]
],
"_from": "is-extglob@2.1.1",
"_id": "is-extglob@2.1.1",
"_inBundle": false,
"_integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
"_location": "/react-scripts/http-proxy-middleware/is-extglob",
"_phantomChildren": {},
"_requested": {
"type": "version",
"registry": true,
"raw": "is-extglob@2.1.1",
"name": "is-extglob",
"escapedName": "is-extglob",
"rawSpec": "2.1.1",
"saveSpec": null,
"fetchSpec": "2.1.1"
},
"_requiredBy": [
"/react-scripts/http-proxy-middleware/is-glob"
],
"_resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"_spec": "2.1.1",
"_where": "C:\\Users\\deranjer\\go\\src\\github.com\\deranjer\\goTorrent\\torrent-project",
"author": {
"name": "Jon Schlinkert",
"url": "https://github.com/jonschlinkert"
},
"bugs": {
"url": "https://github.com/jonschlinkert/is-extglob/issues"
},
"description": "Returns true if a string has an extglob.",
"devDependencies": {
"gulp-format-md": "^0.1.10",
"mocha": "^3.0.2"
},
"engines": {
"node": ">=0.10.0"
},
"files": [
"index.js"
],
"homepage": "https://github.com/jonschlinkert/is-extglob",
"keywords": [
"bash",
"braces",
"check",
"exec",
"expression",
"extglob",
"glob",
"globbing",
"globstar",
"is",
"match",
"matches",
"pattern",
"regex",
"regular",
"string",
"test"
],
"license": "MIT",
"main": "index.js",
"name": "is-extglob",
"repository": {
"type": "git",
"url": "git+https://github.com/jonschlinkert/is-extglob.git"
},
"scripts": {
"test": "mocha"
},
"verb": {
"toc": false,
"layout": "default",
"tasks": [
"readme"
],
"plugins": [
"gulp-format-md"
],
"related": {
"list": [
"has-glob",
"is-glob",
"micromatch"
]
},
"reflinks": [
"verb",
"verb-generate-readme"
],
"lint": {
"reflinks": true
}
},
"version": "2.1.1"
}

View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2014-2016, Jon Schlinkert.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -0,0 +1,142 @@
# is-glob [![NPM version](https://img.shields.io/npm/v/is-glob.svg?style=flat)](https://www.npmjs.com/package/is-glob) [![NPM downloads](https://img.shields.io/npm/dm/is-glob.svg?style=flat)](https://npmjs.org/package/is-glob) [![Build Status](https://img.shields.io/travis/jonschlinkert/is-glob.svg?style=flat)](https://travis-ci.org/jonschlinkert/is-glob)
> Returns `true` if the given string looks like a glob pattern or an extglob pattern. This makes it easy to create code that only uses external modules like node-glob when necessary, resulting in much faster code execution and initialization time, and a better user experience.
## Install
Install with [npm](https://www.npmjs.com/):
```sh
$ npm install --save is-glob
```
You might also be interested in [is-valid-glob](https://github.com/jonschlinkert/is-valid-glob) and [has-glob](https://github.com/jonschlinkert/has-glob).
## Usage
```js
var isGlob = require('is-glob');
```
**True**
Patterns that have glob characters or regex patterns will return `true`:
```js
isGlob('!foo.js');
isGlob('*.js');
isGlob('**/abc.js');
isGlob('abc/*.js');
isGlob('abc/(aaa|bbb).js');
isGlob('abc/[a-z].js');
isGlob('abc/{a,b}.js');
isGlob('abc/?.js');
//=> true
```
Extglobs
```js
isGlob('abc/@(a).js');
isGlob('abc/!(a).js');
isGlob('abc/+(a).js');
isGlob('abc/*(a).js');
isGlob('abc/?(a).js');
//=> true
```
**False**
Escaped globs or extglobs return `false`:
```js
isGlob('abc/\\@(a).js');
isGlob('abc/\\!(a).js');
isGlob('abc/\\+(a).js');
isGlob('abc/\\*(a).js');
isGlob('abc/\\?(a).js');
isGlob('\\!foo.js');
isGlob('\\*.js');
isGlob('\\*\\*/abc.js');
isGlob('abc/\\*.js');
isGlob('abc/\\(aaa|bbb).js');
isGlob('abc/\\[a-z].js');
isGlob('abc/\\{a,b}.js');
isGlob('abc/\\?.js');
//=> false
```
Patterns that do not have glob patterns return `false`:
```js
isGlob('abc.js');
isGlob('abc/def/ghi.js');
isGlob('foo.js');
isGlob('abc/@.js');
isGlob('abc/+.js');
isGlob();
isGlob(null);
//=> false
```
Arrays are also `false` (If you want to check if an array has a glob pattern, use [has-glob](https://github.com/jonschlinkert/has-glob)):
```js
isGlob(['**/*.js']);
isGlob(['foo.js']);
//=> false
```
## About
### Related projects
* [assemble](https://www.npmjs.com/package/assemble): Get the rocks out of your socks! Assemble makes you fast at creating web projects… [more](https://github.com/assemble/assemble) | [homepage](https://github.com/assemble/assemble "Get the rocks out of your socks! Assemble makes you fast at creating web projects. Assemble is used by thousands of projects for rapid prototyping, creating themes, scaffolds, boilerplates, e-books, UI components, API documentation, blogs, building websit")
* [base](https://www.npmjs.com/package/base): base is the foundation for creating modular, unit testable and highly pluggable node.js applications, starting… [more](https://github.com/node-base/base) | [homepage](https://github.com/node-base/base "base is the foundation for creating modular, unit testable and highly pluggable node.js applications, starting with a handful of common methods, like `set`, `get`, `del` and `use`.")
* [update](https://www.npmjs.com/package/update): Be scalable! Update is a new, open source developer framework and CLI for automating updates… [more](https://github.com/update/update) | [homepage](https://github.com/update/update "Be scalable! Update is a new, open source developer framework and CLI for automating updates of any kind in code projects.")
* [verb](https://www.npmjs.com/package/verb): Documentation generator for GitHub projects. Verb is extremely powerful, easy to use, and is used… [more](https://github.com/verbose/verb) | [homepage](https://github.com/verbose/verb "Documentation generator for GitHub projects. Verb is extremely powerful, easy to use, and is used on hundreds of projects of all sizes to generate everything from API docs to readmes.")
### Contributing
Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
### Contributors
| **Commits** | **Contributor**<br/> |
| --- | --- |
| 40 | [jonschlinkert](https://github.com/jonschlinkert) |
| 1 | [tuvistavie](https://github.com/tuvistavie) |
### Building docs
_(This document was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme) (a [verb](https://github.com/verbose/verb) generator), please don't edit the readme directly. Any changes to the readme must be made in [.verb.md](.verb.md).)_
To generate the readme and API documentation with [verb](https://github.com/verbose/verb):
```sh
$ npm install -g verb verb-generate-readme && verb
```
### Running tests
Install dev dependencies:
```sh
$ npm install -d && npm test
```
### Author
**Jon Schlinkert**
* [github/jonschlinkert](https://github.com/jonschlinkert)
* [twitter/jonschlinkert](http://twitter.com/jonschlinkert)
### License
Copyright © 2016, [Jon Schlinkert](https://github.com/jonschlinkert).
Released under the [MIT license](https://github.com/jonschlinkert/is-glob/blob/master/LICENSE).
***
_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.1.31, on October 12, 2016._

View File

@@ -0,0 +1,25 @@
/*!
* is-glob <https://github.com/jonschlinkert/is-glob>
*
* Copyright (c) 2014-2016, Jon Schlinkert.
* Licensed under the MIT License.
*/
var isExtglob = require('is-extglob');
module.exports = function isGlob(str) {
if (typeof str !== 'string' || str === '') {
return false;
}
if (isExtglob(str)) return true;
var regex = /(\\).|([*?]|\[.*\]|\{.*\}|\(.*\|.*\)|^!)/;
var match;
while ((match = regex.exec(str))) {
if (match[2]) return true;
str = str.slice(match.index + match[0].length);
}
return false;
};

View File

@@ -0,0 +1,122 @@
{
"_args": [
[
"is-glob@3.1.0",
"C:\\Users\\deranjer\\go\\src\\github.com\\deranjer\\goTorrent\\torrent-project"
]
],
"_from": "is-glob@3.1.0",
"_id": "is-glob@3.1.0",
"_inBundle": false,
"_integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
"_location": "/react-scripts/http-proxy-middleware/is-glob",
"_phantomChildren": {},
"_requested": {
"type": "version",
"registry": true,
"raw": "is-glob@3.1.0",
"name": "is-glob",
"escapedName": "is-glob",
"rawSpec": "3.1.0",
"saveSpec": null,
"fetchSpec": "3.1.0"
},
"_requiredBy": [
"/react-scripts/http-proxy-middleware"
],
"_resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
"_spec": "3.1.0",
"_where": "C:\\Users\\deranjer\\go\\src\\github.com\\deranjer\\goTorrent\\torrent-project",
"author": {
"name": "Jon Schlinkert",
"url": "https://github.com/jonschlinkert"
},
"bugs": {
"url": "https://github.com/jonschlinkert/is-glob/issues"
},
"contributors": [
{
"name": "Daniel Perez",
"email": "daniel@claudetech.com",
"url": "http://tuvistavie.com"
},
{
"name": "Jon Schlinkert",
"email": "jon.schlinkert@sellside.com",
"url": "http://twitter.com/jonschlinkert"
}
],
"dependencies": {
"is-extglob": "^2.1.0"
},
"description": "Returns `true` if the given string looks like a glob pattern or an extglob pattern. This makes it easy to create code that only uses external modules like node-glob when necessary, resulting in much faster code execution and initialization time, and a better user experience.",
"devDependencies": {
"gulp-format-md": "^0.1.10",
"mocha": "^3.0.2"
},
"engines": {
"node": ">=0.10.0"
},
"files": [
"index.js"
],
"homepage": "https://github.com/jonschlinkert/is-glob",
"keywords": [
"bash",
"braces",
"check",
"exec",
"expression",
"extglob",
"glob",
"globbing",
"globstar",
"is",
"match",
"matches",
"pattern",
"regex",
"regular",
"string",
"test"
],
"license": "MIT",
"main": "index.js",
"name": "is-glob",
"repository": {
"type": "git",
"url": "git+https://github.com/jonschlinkert/is-glob.git"
},
"scripts": {
"test": "mocha"
},
"verb": {
"layout": "default",
"plugins": [
"gulp-format-md"
],
"related": {
"list": [
"assemble",
"base",
"update",
"verb"
]
},
"reflinks": [
"assemble",
"bach",
"base",
"composer",
"gulp",
"has-glob",
"is-valid-glob",
"micromatch",
"npm",
"scaffold",
"verb",
"vinyl"
]
},
"version": "3.1.0"
}

View File

@@ -0,0 +1,90 @@
{
"_args": [
[
"http-proxy-middleware@0.17.4",
"C:\\Users\\deranjer\\go\\src\\github.com\\deranjer\\goTorrent\\torrent-project"
]
],
"_from": "http-proxy-middleware@0.17.4",
"_id": "http-proxy-middleware@0.17.4",
"_inBundle": false,
"_integrity": "sha1-ZC6ISIUdZvCdTxJJEoRtuutBuDM=",
"_location": "/react-scripts/http-proxy-middleware",
"_phantomChildren": {},
"_requested": {
"type": "version",
"registry": true,
"raw": "http-proxy-middleware@0.17.4",
"name": "http-proxy-middleware",
"escapedName": "http-proxy-middleware",
"rawSpec": "0.17.4",
"saveSpec": null,
"fetchSpec": "0.17.4"
},
"_requiredBy": [
"/react-scripts/webpack-dev-server"
],
"_resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.17.4.tgz",
"_spec": "0.17.4",
"_where": "C:\\Users\\deranjer\\go\\src\\github.com\\deranjer\\goTorrent\\torrent-project",
"author": {
"name": "Steven Chim"
},
"bugs": {
"url": "https://github.com/chimurai/http-proxy-middleware/issues"
},
"dependencies": {
"http-proxy": "^1.16.2",
"is-glob": "^3.1.0",
"lodash": "^4.17.2",
"micromatch": "^2.3.11"
},
"description": "The one-liner node.js proxy middleware for connect, express and browser-sync",
"devDependencies": {
"browser-sync": "^2.18.2",
"chai": "^3.5.0",
"connect": "^3.5.0",
"coveralls": "^2.11.15",
"express": "^4.14.0",
"istanbul": "^0.4.5",
"istanbul-coveralls": "^1.0.3",
"mocha": "^3.2.0",
"mocha-lcov-reporter": "1.2.0",
"opn": "^4.0.2",
"ws": "^1.1.1"
},
"files": [
"index.js",
"lib"
],
"homepage": "https://github.com/chimurai/http-proxy-middleware",
"keywords": [
"reverse",
"proxy",
"middleware",
"http",
"https",
"connect",
"express",
"browser-sync",
"gulp",
"grunt-contrib-connect",
"websocket",
"ws",
"cors"
],
"license": "MIT",
"main": "index.js",
"name": "http-proxy-middleware",
"repository": {
"type": "git",
"url": "git+https://github.com/chimurai/http-proxy-middleware.git"
},
"scripts": {
"clean": "rm -rf coverage",
"cover": "npm run clean && istanbul cover ./node_modules/mocha/bin/_mocha -- --recursive",
"coveralls": "istanbul cover ./node_modules/mocha/bin/_mocha --report lcovonly -- --recursive --reporter spec && istanbul-coveralls && npm run clean",
"test": "mocha --recursive --colors --reporter spec"
},
"version": "0.17.4"
}