Initial import from local backup (Documents-Playground/pakerpale)

This commit is contained in:
jeonghwa
2026-07-03 05:27:31 +09:00
commit 3a8de01ba0
1794 changed files with 137027 additions and 0 deletions

5
node_modules/express-http-proxy/.eslintignore generated vendored Normal file
View File

@@ -0,0 +1,5 @@
/coverage
/scripts
/node_modules
/jsdoc
/locales

168
node_modules/express-http-proxy/.eslintrc generated vendored Normal file
View File

@@ -0,0 +1,168 @@
{
"env": {
"browser": true,
"es6": true,
"jquery": true,
"node": true,
"mocha": true,
},
"globals": {},
"parserOptions": { "ecmaVersion": 8 },
"rules": {
"camelcase": [
2,
{
"properties": "always"
}
],
"eqeqeq": 2,
"indent": [
"error",
2,
{
"ArrayExpression": 1,
"CallExpression": {"arguments": 1},
"FunctionDeclaration": {"body": 1, "parameters": 2},
"MemberExpression": 1,
"ObjectExpression": 1,
"SwitchCase": 1
}
],
"no-use-before-define": [
2,
{
"functions": false
}
],
"max-len": [
2,
120
],
"max-depth": [
2,
2
],
"complexity": [
2,
15
],
"new-cap": 2,
"quotes": [
2,
"single",
{
"allowTemplateLiterals": true
}
],
"strict": [
2,
"global"
],
"no-undef": 2,
"no-unused-vars": 2,
"no-eq-null": 2,
"space-before-function-paren": ["error", {
"anonymous": "always",
"named": "never"
}],
"no-empty": [
2,
{
"allowEmptyCatch": true
}
],
"object-curly-spacing": [
2,
"always"
],
"space-in-parens": [
2,
"never"
],
"quote-props": [
2,
"as-needed"
],
"key-spacing": [
2,
{
"beforeColon": false,
"afterColon": true
}
],
"space-unary-ops": [
2,
{
"words": false,
"nonwords": false
}
],
"no-mixed-spaces-and-tabs": 2,
"no-trailing-spaces": 2,
"comma-dangle": 0,
"comma-spacing": [
2,
{
"after": true,
"before": false
}
],
"no-with": 2,
"brace-style": [
2,
"1tbs",
{
"allowSingleLine": true
}
],
"no-multiple-empty-lines": 2,
"no-multi-str": 2,
"one-var": [
2,
"never"
],
"semi-spacing": [
2,
{
"before": false,
"after": true
}
],
"space-before-blocks": [
2,
"always"
],
"wrap-iife": 2,
"comma-style": [
2,
"last"
],
"space-infix-ops": 2,
"eol-last": 2,
"dot-notation": 2,
"curly": [
2,
"all"
],
"keyword-spacing": [
2,
{}
],
"lines-around-comment": [
2,
{ "afterLineComment": true, "allowBlockEnd": true }
],
"semi": [
2,
"always"
],
"consistent-this": [
2,
"self"
],
"linebreak-style": [
2,
"unix"
]
}
}

4
node_modules/express-http-proxy/.travis.yml generated vendored Normal file
View File

@@ -0,0 +1,4 @@
language: node_js
node_js:
- "6"
- "8"

21
node_modules/express-http-proxy/LICENSE-MIT generated vendored Normal file
View File

@@ -0,0 +1,21 @@
Copyright (c) 2013 villadora <jky239@gmail.com>, contributors
http://kael.me/
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.

591
node_modules/express-http-proxy/README.md generated vendored Normal file
View File

@@ -0,0 +1,591 @@
# express-http-proxy [![NPM version](https://badge.fury.io/js/express-http-proxy.svg)](http://badge.fury.io/js/express-http-proxy) [![Build Status](https://travis-ci.org/villadora/express-http-proxy.svg?branch=master)](https://travis-ci.org/villadora/express-http-proxy) [![Dependency Status](https://gemnasium.com/villadora/express-http-proxy.svg)](https://gemnasium.com/villadora/express-http-proxy)
Express middleware to proxy request to another host and pass response back to original caller.
## Install
```bash
$ npm install express-http-proxy --save
```
## Usage
```js
proxy(host, options);
```
### Example:
To proxy URLS starting with '/proxy' to the host 'www.google.com':
```js
var proxy = require('express-http-proxy');
var app = require('express')();
app.use('/proxy', proxy('www.google.com'));
```
### Streaming
Proxy requests and user responses are piped/streamed/chunked by default.
If you define a response modifier (userResDecorator, userResHeaderDecorator),
or need to inspect the response before continuing (maybeSkipToNext), streaming
is disabled, and the request and response are buffered.
This can cause performance issues with large payloads.
### Promises
Many function hooks support Promises.
If any Promise is rejected, ```next(x)``` is called in the hosting application, where ```x``` is whatever you pass to ```Promise.reject```;
e.g.
```js
app.use(proxy('/reject-promise', {
proxyReqOptDecorator: function() {
return Promise.reject('An arbitrary rejection message.');
}
}));
```
eventually calls
```js
next('An arbitrary rejection messasage');
```
### Host
The first positional argument is for the proxy host; in many cases you will use a static string here, eg.
```js
app.use('/', proxy('http://google.com'))
```
However, this argument can also be a function, and that function can be
memoized or computed on each request, based on the setting of
```memoizeHost```.
```js
function selectProxyHost() {
return (new Date() % 2) ? 'http://google.com' : 'http://altavista.com';
}
app.use('/', proxy(selectProxyHost));
```
### Options
#### proxyReqPathResolver (supports Promises)
Note: In ```express-http-proxy```, the ```path``` is considered the portion of
the url after the host, and including all query params. E.g. for the URL
```http://smoogle.com/search/path?q=123```; the path is
```/search/path?q=123```. Authors using this resolver must also handle the query parameter portion of the path.
Provide a proxyReqPathResolver function if you'd like to
operate on the path before issuing the proxy request. Use a Promise for async
operations.
```js
app.use(proxy('localhost:12345', {
proxyReqPathResolver: function (req) {
var parts = req.url.split('?');
var queryString = parts[1];
var updatedPath = parts[0].replace(/test/, 'tent');
return updatedPath + (queryString ? '?' + queryString : '');
}
}));
```
Promise form
```js
app.use('/proxy', proxy('localhost:12345', {
proxyReqPathResolver: function(req) {
return new Promise(function (resolve, reject) {
setTimeout(function () { // simulate async
var parts = req.url.split('?');
var queryString = parts[1];
var updatedPath = parts[0].replace(/test/, 'tent');
var resolvedPathValue = updatedPath + (queryString ? '?' + queryString : '');
resolve(resolvedPathValue);
}, 200);
});
}
}));
```
#### forwardPath
DEPRECATED. See proxyReqPathResolver
#### forwardPathAsync
DEPRECATED. See proxyReqPathResolver
#### filter (supports Promises)
The ```filter``` option can be used to limit what requests are proxied. Return
```true``` to continue to execute proxy; return false-y to skip proxy for this
request.
For example, if you only want to proxy get request:
```js
app.use('/proxy', proxy('www.google.com', {
filter: function(req, res) {
return req.method == 'GET';
}
}));
```
Promise form:
```js
app.use(proxy('localhost:12346', {
filter: function (req, res) {
return new Promise(function (resolve) {
resolve(req.method === 'GET');
});
}
}));
```
Note that in the previous example, `resolve(false)` will execute the happy path
for filter here (skipping the rest of the proxy, and calling `next()`).
`reject()` will also skip the rest of proxy and call `next()`.
#### userResDecorator (was: intercept) (supports Promise)
You can modify the proxy's response before sending it to the client.
```js
app.use('/proxy', proxy('www.google.com', {
userResDecorator: function(proxyRes, proxyResData, userReq, userRes) {
data = JSON.parse(proxyResData.toString('utf8'));
data.newProperty = 'exciting data';
return JSON.stringify(data);
}
}));
```
```js
app.use(proxy('httpbin.org', {
userResDecorator: function(proxyRes, proxyResData) {
return new Promise(function(resolve) {
proxyResData.funkyMessage = 'oi io oo ii';
setTimeout(function() {
resolve(proxyResData);
}, 200);
});
}
}));
```
##### 304 - Not Modified
When your proxied service returns 304, not modified, this step will be skipped, since there is no body to decorate.
##### exploiting references
The intent is that this be used to modify the proxy response data only.
Note:
The other arguments (proxyRes, userReq, userRes) are passed by reference, so
you *can* currently exploit this to modify either response's headers, for
instance, but this is not a reliable interface. I expect to close this
exploit in a future release, while providing an additional hook for mutating
the userRes before sending.
##### gzip responses
If your proxy response is gzipped, this program will automatically unzip
it before passing to your function, then zip it back up before piping it to the
user response. There is currently no way to short-circuit this behavior.
#### limit
This sets the body size limit (default: `1mb`). If the body size is larger than the specified (or default) limit,
a `413 Request Entity Too Large` error will be returned. See [bytes.js](https://www.npmjs.com/package/bytes) for
a list of supported formats.
```js
app.use('/proxy', proxy('www.google.com', {
limit: '5mb'
}));
```
#### memoizeHost
Defaults to ```true```.
When true, the ```host``` argument will be parsed on first request, and
memoized for subsequent requests.
When ```false```, ```host``` argument will be parsed on each request.
E.g.,
```js
function coinToss() { return Math.random() > .5 }
function getHost() { return coinToss() ? 'http://yahoo.com' : 'http://google.com' }
app.use(proxy(getHost, {
memoizeHost: false
}))
```
In this example, when ```memoizeHost:false```, the coinToss occurs on each
request, and each request could get either value.
Conversely, When ```memoizeHost:true```, the coinToss would occur on the first
request, and all additional requests would return the value resolved on the
first request.
### userResHeaderDecorator
```js
app.use('/proxy', proxy('www.google.com', {
userResHeaderDecorator(headers, userReq, userRes, proxyReq, proxyRes) {
// recieves an Object of headers, returns an Object of headers.
return headers;
}
}));
```
#### decorateRequest
REMOVED: See ```proxyReqOptDecorator``` and ```proxyReqBodyDecorator```.
#### skipToNextHandlerFilter(supports Promise form)
(experimental: this interface may change in upcoming versions)
Allows you to inspect the proxy response, and decide if you want to continue processing (via express-http-proxy) or call ```next()``` to return control to express.
```js
app.use('/proxy', proxy('www.google.com', {
skipToNextHandlerFilter: function(proxyRes) {
return proxyRes.statusCode === 404;
}
}));
```
### proxyErrorHandler
By default, ```express-http-proxy``` will pass any errors except ECONNRESET to
next, so that your application can handle or react to them, or just drop
through to your default error handling. ECONNRESET errors are immediately
returned to the user for historical reasons.
If you would like to modify this behavior, you can provide your own ```proxyErrorHandler```.
```js
// Example of skipping all error handling.
app.use(proxy('localhost:12346', {
proxyErrorHandler: function(err, res, next) {
next(err);
}
}));
// Example of rolling your own
app.use(proxy('localhost:12346', {
proxyErrorHandler: function(err, res, next) {
switch (err && err.code) {
case 'ECONNRESET': { return res.status(405).send('504 became 405'); }
case 'ECONNREFUSED': { return res.status(200).send('gotcher back'); }
default: { next(err); }
}
}}));
```
#### proxyReqOptDecorator (supports Promise form)
You can override most request options before issuing the proxyRequest.
proxyReqOpt represents the options argument passed to the (http|https).request
module.
NOTE: req.path cannot be changed via this method; use ```proxyReqPathResolver``` instead. (see https://github.com/villadora/express-http-proxy/issues/243)
```js
app.use('/proxy', proxy('www.google.com', {
proxyReqOptDecorator: function(proxyReqOpts, srcReq) {
// you can update headers
proxyReqOpts.headers['Content-Type'] = 'text/html';
// you can change the method
proxyReqOpts.method = 'GET';
return proxyReqOpts;
}
}));
```
You can use a Promise for async style.
```js
app.use('/proxy', proxy('www.google.com', {
proxyReqOptDecorator: function(proxyReqOpts, srcReq) {
return new Promise(function(resolve, reject) {
proxyReqOpts.headers['Content-Type'] = 'text/html';
resolve(proxyReqOpts);
})
}
}));
```
#### proxyReqBodyDecorator (supports Promise form)
You can mutate the body content before sending the proxyRequest.
```js
app.use('/proxy', proxy('www.google.com', {
proxyReqBodyDecorator: function(bodyContent, srcReq) {
return bodyContent.split('').reverse().join('');
}
}));
```
You can use a Promise for async style.
```js
app.use('/proxy', proxy('www.google.com', {
proxyReqBodyDecorator: function(proxyReq, srcReq) {
return new Promise(function(resolve, reject) {
http.get('http://dev/null', function (err, res) {
if (err) { reject(err); }
resolve(res);
});
})
}
}));
```
#### https
Normally, your proxy request will be made on the same protocol as the `host`
parameter. If you'd like to force the proxy request to be https, use this
option.
```js
app.use('/proxy', proxy('www.google.com', {
https: true
}));
```
#### preserveHostHdr
You can copy the host HTTP header to the proxied express server using the `preserveHostHdr` option.
```js
app.use('/proxy', proxy('www.google.com', {
preserveHostHdr: true
}));
```
#### parseReqBody
The ```parseReqBody``` option allows you to control parsing the request body.
For example, disabling body parsing is useful for large uploads where it would be inefficient
to hold the data in memory.
##### Note: this setting is required for binary uploads. A future version of this library may handle this for you.
This defaults to true in order to preserve legacy behavior.
When false, no action will be taken on the body and accordingly ```req.body``` will no longer be set.
Note that setting this to false overrides ```reqAsBuffer``` and ```reqBodyEncoding``` below.
```js
app.use('/proxy', proxy('www.google.com', {
parseReqBody: false
}));
```
#### reqAsBuffer
Note: this is an experimental feature. ymmv
The ```reqAsBuffer``` option allows you to ensure the req body is encoded as a Node
```Buffer``` when sending a proxied request. Any value for this is truthy.
This defaults to to false in order to preserve legacy behavior. Note that
the value of ```reqBodyEnconding``` is used as the encoding when coercing strings
(and stringified JSON) to Buffer.
Ignored if ```parseReqBody``` is set to false.
```js
app.use('/proxy', proxy('www.google.com', {
reqAsBuffer: true
}));
```
#### reqBodyEncoding
Encoding used to decode request body. Defaults to ```utf-8```.
Use ```null``` to preserve as Buffer when proxied request body is a Buffer. (e.g image upload)
Accept any values supported by [raw-body](https://www.npmjs.com/package/raw-body#readme).
The same encoding is used in the intercept method.
Ignored if ```parseReqBody``` is set to false.
```js
app.use('/post', proxy('httpbin.org', {
reqBodyEncoding: null
}));
```
#### timeout
By default, node does not express a timeout on connections.
Use timeout option to impose a specific timeout.
Timed-out requests will respond with 504 status code and a X-Timeout-Reason header.
```js
app.use('/', proxy('httpbin.org', {
timeout: 2000 // in milliseconds, two seconds
}));
```
## Trace debugging
The node-debug module is used to provide a trace debugging capability.
```
DEBUG=express-http-proxy npm run YOUR_PROGRAM
DEBUG=express-http-proxy npm run YOUR_PROGRAM | grep 'express-http-proxy' # to filter down to just these messages
```
Will trace the execution of the express-http-proxy module in order to aide debugging.
## Upgrade to 1.0, transition guide and breaking changes
1.
```decorateRequest``` has been REMOVED, and will generate an error when called. See ```proxyReqOptDecorator``` and ```proxyReqBodyDecorator```.
Resolution: Most authors will simply need to change the method name for their
decorateRequest method; if author was decorating reqOpts and reqBody in the
same method, this will need to be split up.
2.
```intercept``` has been REMOVED, and will generate an error when called. See ```userResDecorator```.
Resolution: Most authors will simply need to change the method name from ```intercept``` to ```userResDecorator```, and exit the method by returning the value, rather than passing it to a callback. E.g.:
Before:
```js
app.use('/proxy', proxy('www.google.com', {
intercept: function(proxyRes, proxyResData, userReq, userRes, cb) {
data = JSON.parse(proxyResData.toString('utf8'));
data.newProperty = 'exciting data';
cb(null, JSON.stringify(data));
}
}));
```
Now:
```js
app.use('/proxy', proxy('www.google.com', {
userResDecorator: function(proxyRes, proxyResData, userReq, userRes) {
data = JSON.parse(proxyResData.toString('utf8'));
data.newProperty = 'exciting data';
return JSON.stringify(data);
}
}));
```
3.
```forwardPath``` and ```forwardPathAsync``` have been DEPRECATED and will generate a warning when called. See ```proxyReqPathResolver```.
Resolution: Simple update the name of either ```forwardPath``` or ```forwardPathAsync``` to ```proxyReqPathResolver```.
## When errors occur on your proxy server
When your proxy server responds with an error, express-http-proxy returns a response with the same status code. See ```test/catchingErrors``` for syntax details.
When your proxy server times out, express-http-proxy will continue to wait indefinitely for a response, unless you define a ```timeout``` as described above.
## Questions
### Q: Does it support https proxy?
The library will automatically use https if the provided path has 'https://' or ':443'. You may also set option ```https``` to true to always use https.
You can use ```proxyReqOptDecorator``` to ammend any auth or challenge headers required to succeed https.
### Q: How can I support non-standard certificate chains?
You can use the ability to decorate the proxy request prior to sending. See ```proxyReqOptDecorator``` for more details.
```js
app.use('/', proxy('internalhost.example.com', {
proxyReqOptDecorator: function(proxyReqOpts, originalReq) {
proxyReqOpts.ca = [caCert, intermediaryCert]
return proxyReqOpts;
}
})
```
### Q: How to ignore self-signed certificates ?
You can set the `rejectUnauthorized` value in proxy request options prior to sending. See ```proxyReqOptDecorator``` for more details.
```js
app.use('/', proxy('internalhost.example.com', {
proxyReqOptDecorator: function(proxyReqOpts, originalReq) {
proxyReqOpts.rejectUnauthorized = false
return proxyReqOpts;
}
})
```
## Release Notes
| Release | Notes |
| --- | --- |
| 1.5.1 | Fixes bug in stringifying debug messages. |
| 1.5.0 | Fixes bug in `filter` signature. Fix bug in skipToNextHandler, add expressHttpProxy value to user res when skipped. Add tests for host as ip address. |
| 1.4.0 | DEPRECATED. Critical bug in the `filter` api.|
| 1.3.0 | DEPRECATED. Critical bug in the `filter` api. `filter` now supports Promises. Update linter to eslint. |
| 1.2.0 | Auto-stream when no decorations are made to req/res. Improved docs, fixes issues in maybeSkipToNexthandler, allow authors to manage error handling. |
| 1.1.0 | Add step to allow response headers to be modified.
| 1.0.7 | Update dependencies. Improve docs on promise rejection. Fix promise rejection on body limit. Improve debug output. |
| 1.0.6 | Fixes preserveHostHdr not working, skip userResDecorator on 304, add maybeSkipToNext, test improvements and cleanup. |
| 1.0.5 | Minor documentation and test patches |
| 1.0.4 | Minor documentation, test, and package fixes |
| 1.0.3 | Fixes 'limit option is not taken into account |
| 1.0.2 | Minor docs corrections. |
| 1.0.1 | Minor docs adjustments. |
| 1.0.0 | Major revision. <br > REMOVE decorateRequest, ADD proxyReqOptDecorator and proxyReqBodyDecorator. <br /> REMOVE intercept, ADD userResDecorator <br /> userResDecorator supports a Promise form for async operations. <br /> General cleanup of structure and application of hooks. Documentation improvements. Update all dependencies. Re-organize code as a series of workflow steps, each (potentially) supporting a promise, and creating a reusable pattern for future development. |
| 0.11.0 | Allow author to prevent host from being memoized between requests. General program cleanup. |
| 0.10.1| Fixed issue where 'body encoding' was being incorrectly set to the character encoding. <br /> Dropped explicit support for node 0.10. <br /> Intercept can now deal with gziped responses. <br /> Author can now 'force https', even if the original request is over http. <br /> Do not call next after ECONNRESET catch. |
| 0.10.0 | Fix regression in forwardPath implementation. |
| 0.9.1 | Documentation updates. Set 'Accept-Encoding' header to match bodyEncoding. |
| 0.9.0 | Better handling for request body when body is JSON. |
| 0.8.0 | Features: add forwardPathAsync option <br />Updates: modernize dependencies <br />Fixes: Exceptions parsing proxied response causes error: Can't set headers after they are sent. (#111) <br />If client request aborts, proxied request is aborted too (#107) |
| 0.7.4 | Move jscs to devDependencies to avoid conflict with nsp. |
| 0.7.3 | Adds a timeout option. Code organization and small bug fixes. |
| 0.7.2 | Collecting many minor documentation and test improvements. |
| 0.4.0 | Signature of `intercept` callback changed from `function(data, req, res, callback)` to `function(rsp, data, req, res, callback)` where `rsp` is the original response from the target |
## Licence
MIT
<!-- do not want to make nodeinit to complicated, you can edit this whenever you want. -->

View File

@@ -0,0 +1,25 @@
'use strict';
var debug = require('debug')('express-http-proxy');
var requestOptions = require('../../lib/requestOptions');
function buildProxyReq(Container) {
var req = Container.user.req;
var res = Container.user.res;
var options = Container.options;
var host = Container.proxy.host;
var parseBody = (!options.parseReqBody) ? Promise.resolve(null) : requestOptions.bodyContent(req, res, options);
var createReqOptions = requestOptions.create(req, res, options, host);
return Promise
.all([parseBody, createReqOptions])
.then(function(responseArray) {
Container.proxy.bodyContent = responseArray[0];
Container.proxy.reqBuilder = responseArray[1];
debug('proxy request options:', Container.proxy.reqBuilder);
return Container;
});
}
module.exports = buildProxyReq;

View File

@@ -0,0 +1,22 @@
'use strict';
function copyProxyResHeadersToUserRes(container) {
return new Promise(function(resolve) {
var res = container.user.res;
var rsp = container.proxy.res;
if (!res.headersSent) {
res.status(rsp.statusCode);
Object.keys(rsp.headers)
.filter(function(item) { return item !== 'transfer-encoding'; })
.forEach(function(item) {
res.set(item, rsp.headers[item]);
});
}
resolve(container);
});
}
module.exports = copyProxyResHeadersToUserRes;

View File

@@ -0,0 +1,25 @@
'use strict';
var debug = require('debug')('express-http-proxy');
function defaultDecorator(proxyReqOptBody/*, userReq */) {
return proxyReqOptBody;
}
function decorateProxyReqBody(container) {
var userDecorator = container.options.proxyReqBodyDecorator;
var resolverFn = userDecorator || defaultDecorator;
if (userDecorator) {
debug('using custom proxyReqBodyDecorator');
}
return Promise
.resolve(resolverFn(container.proxy.bodyContent, container.user.req))
.then(function(bodyContent) {
container.proxy.bodyContent = bodyContent;
return Promise.resolve(container);
});
}
module.exports = decorateProxyReqBody;

View File

@@ -0,0 +1,22 @@
'use strict';
var debug = require('debug')('express-http-proxy');
function defaultDecorator(proxyReqOptBuilder /*, userReq */) {
return proxyReqOptBuilder;
}
function decorateProxyReqOpt(container) {
var resolverFn = container.options.proxyReqOptDecorator || defaultDecorator;
return Promise
.resolve(resolverFn(container.proxy.reqBuilder, container.user.req))
.then(function (processedReqOpts) {
delete processedReqOpts.params;
container.proxy.reqBuilder = processedReqOpts;
debug('Request options (after processing): %o', processedReqOpts);
return Promise.resolve(container);
});
}
module.exports = decorateProxyReqOpt;

View File

@@ -0,0 +1,66 @@
'use strict';
var as = require('../../lib/as.js');
var debug = require('debug')('express-http-proxy');
var zlib = require('zlib');
function isResGzipped(res) {
return res.headers['content-encoding'] === 'gzip';
}
function zipOrUnzip(method) {
return function(rspData, res) {
return (isResGzipped(res) && rspData.length) ? zlib[method](rspData) : rspData;
};
}
var maybeUnzipResponse = zipOrUnzip('gunzipSync');
var maybeZipResponse = zipOrUnzip('gzipSync');
function verifyBuffer(rspd, reject) {
if (!Buffer.isBuffer(rspd)) {
return reject(new Error('userResDecorator should return string or buffer as data'));
}
}
function updateHeaders(res, rspdBefore, rspdAfter, reject) {
if (!res.headersSent) {
res.set('content-length', rspdAfter.length);
} else if (rspdAfter.length !== rspdBefore.length) {
var error = '"Content-Length" is already sent,' +
'the length of response data can not be changed';
return reject(new Error(error));
}
}
function decorateProxyResBody(container) {
var resolverFn = container.options.userResDecorator;
if (!resolverFn) {
return Promise.resolve(container);
}
var proxyResData = maybeUnzipResponse(container.proxy.resData, container.proxy.res);
var proxyRes = container.proxy.res;
var req = container.user.req;
var res = container.user.res;
if (res.statusCode === 304) {
debug('Skipping userResDecorator on response 304');
return Promise.resolve(container);
}
return Promise
.resolve(resolverFn(proxyRes, proxyResData, req, res))
.then(function(modifiedResData) {
return new Promise(function(resolve, reject) {
var rspd = as.buffer(modifiedResData, container.options);
verifyBuffer(rspd, reject);
updateHeaders(res, proxyResData, rspd, reject);
container.proxy.resData = maybeZipResponse(rspd, container.proxy.res);
resolve(container);
});
});
}
module.exports = decorateProxyResBody;

View File

@@ -0,0 +1,22 @@
'use strict';
function decorateUserResHeaders(container) {
var resolverFn = container.options.userResHeaderDecorator;
var headers = container.user.res._headers;
if (!resolverFn) {
return Promise.resolve(container);
}
return Promise
.resolve(resolverFn(headers, container.user.req, container.user.res, container.proxy.req, container.proxy.res))
.then(function(headers) {
return new Promise(function(resolve) {
container.user.res.set(headers);
resolve(container);
});
});
}
module.exports = decorateUserResHeaders;

View File

@@ -0,0 +1,24 @@
'use strict';
// No-op version of filter. Allows everything!
function defaultFilter(proxyReqOptBuilder, userReq) { // eslint-disable-line
return true;
}
function filterUserRequest(container) {
var resolverFn = container.options.filter || defaultFilter;
return Promise
.resolve(resolverFn(container.user.req, container.user.res))
.then(function (shouldIContinue) {
if (shouldIContinue) {
return Promise.resolve(container);
} else {
return Promise.reject(); // reject with no args should simply call next()
}
});
}
module.exports = filterUserRequest;

View File

@@ -0,0 +1,21 @@
'use strict';
var debug = require('debug')('express-http-proxy');
function connectionResetHandler(err, res) {
if (err && err.code === 'ECONNRESET') {
debug('Error: Connection reset due to timeout.');
res.setHeader('X-Timeout-Reason', 'express-http-proxy reset the request.');
res.writeHead(504, {'Content-Type': 'text/plain'});
res.end();
}
}
function handleProxyErrors(err, res, next) {
switch (err && err.code) {
case 'ECONNRESET': { return connectionResetHandler(err, res, next); }
default: { next(err); }
}
}
module.exports = handleProxyErrors;

View File

@@ -0,0 +1,22 @@
'use strict';
function defaultSkipFilter(/* res */) {
return false;
}
function maybeSkipToNextHandler(container) {
var resolverFn = container.options.skipToNextHandlerFilter || defaultSkipFilter;
return Promise
.resolve(resolverFn(container.proxy.res))
.then(function (shouldSkipToNext) {
if (shouldSkipToNext) {
container.user.res.expressHttpProxy = container.proxy;
return Promise.reject(container.user.next());
} else {
return Promise.resolve(container);
}
})
}
module.exports = maybeSkipToNextHandler;

View File

@@ -0,0 +1,40 @@
'use strict';
var as = require('../../lib/as');
function getContentLength(body) {
var result;
if (Buffer.isBuffer(body)) { // Buffer
result = body.length;
} else if (typeof body === 'string') {
result = Buffer.byteLength(body);
}
return result;
}
function prepareProxyReq(container) {
return new Promise(function(resolve) {
var bodyContent = container.proxy.bodyContent;
var reqOpt = container.proxy.reqBuilder;
if (bodyContent) {
bodyContent = container.options.reqAsBuffer ?
as.buffer(bodyContent, container.options) :
as.bufferOrString(bodyContent);
reqOpt.headers['content-length'] = getContentLength(bodyContent);
if (container.options.reqBodyEncoding) {
reqOpt.headers['Accept-Charset'] = container.options.reqBodyEncoding;
}
}
container.proxy.bodyContent = bodyContent;
resolve(container);
});
}
module.exports = prepareProxyReq;

View File

@@ -0,0 +1,19 @@
'use strict';
var requestOptions = require('../../lib/requestOptions');
function resolveProxyHost(container) {
var parsedHost;
if (container.options.memoizeHost && container.options.memoizedHost) {
parsedHost = container.options.memoizedHost;
} else {
parsedHost = requestOptions.parseHost(container);
}
container.proxy.reqBuilder.host = parsedHost.host;
container.proxy.reqBuilder.port = container.options.port || parsedHost.port;
container.proxy.requestModule = parsedHost.module;
return Promise.resolve(container);
}
module.exports = resolveProxyHost;

View File

@@ -0,0 +1,22 @@
'use strict';
var url = require('url');
var debug = require('debug')('express-http-proxy');
function defaultProxyReqPathResolver(req) {
return url.parse(req.url).path;
}
function resolveProxyReqPath(container) {
var resolverFn = container.options.proxyReqPathResolver || defaultProxyReqPathResolver;
return Promise
.resolve(resolverFn(container.user.req))
.then(function(resolvedPath) {
container.proxy.reqBuilder.path = resolvedPath;
debug('resolved proxy path:', resolvedPath);
return Promise.resolve(container);
});
}
module.exports = resolveProxyReqPath;

View File

@@ -0,0 +1,78 @@
'use strict';
var chunkLength = require('../../lib/chunkLength');
function sendProxyRequest(Container) {
var req = Container.user.req;
var bodyContent = Container.proxy.bodyContent;
var reqOpt = Container.proxy.reqBuilder;
var options = Container.options;
return new Promise(function(resolve, reject) {
var protocol = Container.proxy.requestModule;
var proxyReq = Container.proxy.req = protocol.request(reqOpt, function(rsp) {
if (options.stream) {
Container.proxy.res = rsp;
return resolve(Container);
}
var chunks = [];
rsp.on('data', function(chunk) { chunks.push(chunk); });
rsp.on('end', function() {
Container.proxy.res = rsp;
Container.proxy.resData = Buffer.concat(chunks, chunkLength(chunks));
resolve(Container);
});
rsp.on('error', reject);
});
proxyReq.on('socket', function(socket) {
if (options.timeout) {
socket.setTimeout(options.timeout, function() {
proxyReq.abort();
});
}
});
proxyReq.on('error', reject);
// this guy should go elsewhere, down the chain
if (options.parseReqBody) {
// We are parsing the body ourselves so we need to write the body content
// and then manually end the request.
//if (bodyContent instanceof Object) {
//throw new Error
//debugger;
//bodyContent = JSON.stringify(bodyContent);
//}
if (bodyContent.length) {
var body = bodyContent;
var contentType = proxyReq.getHeader('Content-Type');
if (contentType === 'x-www-form-urlencoded' || contentType === 'application/x-www-form-urlencoded') {
try {
var params = JSON.parse(body);
body = Object.keys(params).map(function(k) { return k + '=' + params[k]; }).join('&');
} catch (e) {
// bodyContent is not json-format
}
}
proxyReq.setHeader('Content-Length', Buffer.byteLength(body));
proxyReq.write(body);
}
proxyReq.end();
} else {
// Pipe will call end when it has completely read from the request.
req.pipe(proxyReq);
}
req.on('aborted', function() {
// reject?
proxyReq.abort();
});
});
}
module.exports = sendProxyRequest;

View File

@@ -0,0 +1,15 @@
'use strict';
function sendUserRes(Container) {
if (!Container.user.res.headersSent) {
if (Container.options.stream) {
Container.proxy.res.pipe(Container.user.res);
} else {
Container.user.res.send(Container.proxy.resData);
}
}
return Promise.resolve(Container);
}
module.exports = sendUserRes;

61
node_modules/express-http-proxy/index.js generated vendored Normal file
View File

@@ -0,0 +1,61 @@
'use strict';
// * Breaks proxying into a series of discrete steps, many of which can be swapped out by authors.
// * Uses Promises to support async.
// * Uses a quasi-Global called Container to tidy up the argument passing between the major work-flow steps.
var ScopeContainer = require('./lib/scopeContainer');
var assert = require('assert');
var debug = require('debug')('express-http-proxy');
var buildProxyReq = require('./app/steps/buildProxyReq');
var copyProxyResHeadersToUserRes = require('./app/steps/copyProxyResHeadersToUserRes');
var decorateProxyReqBody = require('./app/steps/decorateProxyReqBody');
var decorateProxyReqOpts = require('./app/steps/decorateProxyReqOpts');
var decorateUserRes = require('./app/steps/decorateUserRes');
var decorateUserResHeaders = require('./app/steps/decorateUserResHeaders');
var filterUserRequest = require('./app/steps/filterUserRequest');
var handleProxyErrors = require('./app/steps/handleProxyErrors');
var maybeSkipToNextHandler = require('./app/steps/maybeSkipToNextHandler');
var prepareProxyReq = require('./app/steps/prepareProxyReq');
var resolveProxyHost = require('./app/steps/resolveProxyHost');
var resolveProxyReqPath = require('./app/steps/resolveProxyReqPath');
var sendProxyRequest = require('./app/steps/sendProxyRequest');
var sendUserRes = require('./app/steps/sendUserRes');
module.exports = function proxy(host, userOptions) {
assert(host, 'Host should not be empty');
return function handleProxy(req, res, next) {
debug('[start proxy] ' + req.path);
var container = new ScopeContainer(req, res, next, host, userOptions);
filterUserRequest(container)
.then(buildProxyReq)
.then(resolveProxyHost)
.then(decorateProxyReqOpts)
.then(resolveProxyReqPath)
.then(decorateProxyReqBody)
.then(prepareProxyReq)
.then(sendProxyRequest)
.then(maybeSkipToNextHandler)
.then(copyProxyResHeadersToUserRes)
.then(decorateUserResHeaders)
.then(decorateUserRes)
.then(sendUserRes)
.catch(function (err) {
// I sometimes reject without an error to shortcircuit the remaining
// steps and return control to the host application.
if (err) {
var resolver = (container.options.proxyErrorHandler) ?
container.options.proxyErrorHandler :
handleProxyErrors;
resolver(err, res, next);
} else {
next();
}
});
};
};

36
node_modules/express-http-proxy/lib/as.js generated vendored Normal file
View File

@@ -0,0 +1,36 @@
'use strict';
/*
* Trivial convenience methods for parsing Buffers
*/
function asBuffer(body, options) {
var ret;
if (Buffer.isBuffer(body)) {
ret = body;
} else if (typeof body === 'object') {
ret = new Buffer(JSON.stringify(body), options.reqBodyEncoding);
} else if (typeof body === 'string') {
ret = new Buffer(body, options.reqBodyEncodeing);
}
return ret;
}
function asBufferOrString(body) {
var ret;
if (Buffer.isBuffer(body)) {
ret = body;
} else if (typeof body === 'object') {
ret = JSON.stringify(body);
} else if (typeof body === 'string') {
ret = body;
}
return ret;
}
module.exports = {
buffer: asBuffer,
bufferOrString: asBufferOrString
};

9
node_modules/express-http-proxy/lib/chunkLength.js generated vendored Normal file
View File

@@ -0,0 +1,9 @@
'use strict';
function chunkLength(chunks) {
return chunks.reduce(function (len, buf) {
return len + buf.length;
}, 0);
}
module.exports = chunkLength;

5
node_modules/express-http-proxy/lib/isUnset.js generated vendored Normal file
View File

@@ -0,0 +1,5 @@
'use strict';
module.exports = function (val) {
return (typeof val === 'undefined' || val === '' || val === null);
};

10
node_modules/express-http-proxy/lib/mockHTTP.js generated vendored Normal file
View File

@@ -0,0 +1,10 @@
'use strict';
var app = require('express')();
app.use('/status/:status', function (req, res) {
res.status(Number(req.params.status));
res.send();
});
module.exports = app;

113
node_modules/express-http-proxy/lib/requestOptions.js generated vendored Normal file
View File

@@ -0,0 +1,113 @@
'use strict';
var http = require('http');
var https = require('https');
var url = require('url');
var getRawBody = require('raw-body');
var isUnset = require('./isUnset');
function extend(obj, source, skips) {
if (!source) {
return obj;
}
for (var prop in source) {
if (!skips || skips.indexOf(prop) === -1) {
obj[prop] = source[prop];
}
}
return obj;
}
function parseHost(Container) {
var host = Container.params.host;
var req = Container.user.req;
var options = Container.options;
host = (typeof host === 'function') ? host(req) : host.toString();
if (!host) {
return new Error('Empty host parameter');
}
if (!/http(s)?:\/\//.test(host)) {
host = 'http://' + host;
}
var parsed = url.parse(host);
if (!parsed.hostname) {
return new Error('Unable to parse hostname, possibly missing protocol://?');
}
var ishttps = options.https || parsed.protocol === 'https:';
return {
host: parsed.hostname,
port: parsed.port || (ishttps ? 443 : 80),
module: ishttps ? https : http,
};
}
function reqHeaders(req, options) {
var headers = options.headers || {};
var skipHdrs = [ 'connection', 'content-length' ];
if (!options.preserveHostHdr) {
skipHdrs.push('host');
}
var hds = extend(headers, req.headers, skipHdrs);
hds.connection = 'close';
return hds;
}
function createRequestOptions(req, res, options) {
// prepare proxyRequest
var reqOpt = {
headers: reqHeaders(req, options),
method: req.method,
path: req.path,
params: req.params,
};
if (options.preserveReqSession) {
reqOpt.session = req.session;
}
return Promise.resolve(reqOpt);
}
// extract to bodyContent object
function bodyContent(req, res, options) {
var parseReqBody = isUnset(options.parseReqBody) ? true : options.parseReqBody;
function maybeParseBody(req, limit) {
if (req.body) {
return Promise.resolve(req.body);
} else {
// Returns a promise if no callback specified and global Promise exists.
return getRawBody(req, {
length: req.headers['content-length'],
limit: limit,
});
}
}
if (parseReqBody) {
return maybeParseBody(req, options.limit);
}
}
module.exports = {
create: createRequestOptions,
bodyContent: bodyContent,
parseHost: parseHost
};

79
node_modules/express-http-proxy/lib/resolveOptions.js generated vendored Normal file
View File

@@ -0,0 +1,79 @@
'use strict';
var debug = require('debug')('express-http-proxy');
var isUnset = require('../lib/isUnset');
function resolveBodyEncoding(reqBodyEncoding) {
/* For reqBodyEncoding, these is a meaningful difference between null and
* undefined. null should be passed forward as the value of reqBodyEncoding,
* and undefined should result in utf-8.
*/
return reqBodyEncoding !== undefined ? reqBodyEncoding : 'utf-8';
}
// parse client arguments
function resolveOptions(options) {
options = options || {};
var resolved;
if (options.decorateRequest) {
throw new Error(
'decorateRequest is REMOVED; use proxyReqOptDecorator and' +
'proxyReqBodyDecorator instead. see README.md'
);
}
if (options.forwardPath || options.forwardPathAsync) {
console.warn(
'forwardPath and forwardPathAsync are DEPRECATED' +
'and should be replaced with proxyReqPathResolver'
);
}
if (options.intercept) {
console.warn(
'DEPRECATED: intercept. Use decorateUseRes instead.' +
' Please see README for more information.'
);
}
resolved = {
limit: options.limit || '1mb',
proxyReqPathResolver: options.proxyReqPathResolver
|| options.forwardPathAsync
|| options.forwardPath,
proxyReqOptDecorator: options.proxyReqOptDecorator,
proxyReqBodyDecorator: options.proxyReqBodyDecorator,
userResDecorator: options.userResDecorator || options.intercept,
userResHeaderDecorator: options.userResHeaderDecorator,
proxyErrorHandler: options.proxyErrorHandler,
filter: options.filter,
// For backwards compatability, we default to legacy behavior for newly added settings.
parseReqBody: isUnset(options.parseReqBody) ? true : options.parseReqBody,
preserveHostHdr: options.preserveHostHdr,
memoizeHost: isUnset(options.memoizeHost) ? true : options.memoizeHost,
reqBodyEncoding: resolveBodyEncoding(options.reqBodyEncoding),
skipToNextHandlerFilter: options.skipToNextHandlerFilter,
headers: options.headers,
preserveReqSession: options.preserveReqSession,
https: options.https,
port: options.port,
reqAsBuffer: options.reqAsBuffer,
timeout: options.timeout
};
// automatically opt into stream mode if no response modifiers are specified
resolved.stream = !resolved.skipToNextHandlerFilter &&
!resolved.userResDecorator &&
!resolved.userResHeaderDecorator;
debug(resolved);
return resolved;
}
module.exports = resolveOptions;

35
node_modules/express-http-proxy/lib/scopeContainer.js generated vendored Normal file
View File

@@ -0,0 +1,35 @@
'use strict';
var resolveOptions = require('../lib/resolveOptions');
// The Container object is passed down the chain of Promises, with each one
// of them mutating and returning Container. The goal is that (eventually)
// author using this library // could hook into/override any of these
// workflow steps with a Promise or simple function.
// Container for scoped arguments in a promise chain. Each promise recieves
// this as its argument, and returns it.
//
// Do not expose the details of this to hooks/user functions.
function Container(req, res, next, host, userOptions) {
return {
user: {
req: req,
res: res,
next: next,
},
proxy: {
req: undefined,
res: undefined,
resData: undefined, // from proxy res
bodyContent: undefined, // for proxy req
reqBuilder: {}, // reqOpt, intended as first arg to http(s)?.request
},
options: resolveOptions(userOptions),
params: {
host: host,
userOptions: userOptions
}
};
}
module.exports = Container;

96
node_modules/express-http-proxy/package.json generated vendored Normal file
View File

@@ -0,0 +1,96 @@
{
"_from": "express-http-proxy",
"_id": "express-http-proxy@1.5.1",
"_inBundle": false,
"_integrity": "sha512-k1RdysZWZ8wdPnsLa4iyrrYyUFih/sYKkn6WfkU/q5A8eUdh3l+oXhrRuQmEYEsZmiexVvpiOCkogl03jYfcbg==",
"_location": "/express-http-proxy",
"_phantomChildren": {},
"_requested": {
"type": "tag",
"registry": true,
"raw": "express-http-proxy",
"name": "express-http-proxy",
"escapedName": "express-http-proxy",
"rawSpec": "",
"saveSpec": null,
"fetchSpec": "latest"
},
"_requiredBy": [
"#USER",
"/"
],
"_resolved": "https://registry.npmjs.org/express-http-proxy/-/express-http-proxy-1.5.1.tgz",
"_shasum": "cbf45695c759693c9c5f946117462d25b57e77a8",
"_spec": "express-http-proxy",
"_where": "D:\\dev\\crossmap\\backend-services\\cm-auth",
"author": {
"name": "villadora",
"email": "jky239@gmail.com"
},
"bugs": {
"url": "https://github.com/villadora/express-http-proxy/issues"
},
"bundleDependencies": false,
"contributors": [
{
"name": "Liam Bennett"
},
{
"name": "eldereal",
"url": "https://github.com/eldereal"
},
{
"name": "Saulius Menkevičius",
"url": "https://github.com/razzmatazz"
},
{
"name": "Jérémy Lal",
"email": "kapouer@melix.org"
},
{
"name": "Wei Gao",
"email": "jky239@gmail.com"
},
{
"name": "Nik Krimm",
"url": "https://github.com/monkpow"
}
],
"dependencies": {
"debug": "^3.0.1",
"es6-promise": "^4.1.1",
"raw-body": "^2.3.0"
},
"deprecated": false,
"description": "http proxy middleware for express",
"devDependencies": {
"body-parser": "^1.17.2",
"chai": "^4.1.2",
"cookie-parser": "^1.4.3",
"eslint": "^4.19.1",
"express": "^4.15.4",
"mocha": "^5.2.0",
"supertest": "^3.0.0"
},
"engines": {
"node": ">=6.0.0"
},
"homepage": "https://github.com/villadora/express-http-proxy#readme",
"keywords": [
"express-http-proxy"
],
"license": "MIT",
"main": "index.js",
"name": "express-http-proxy",
"repository": {
"type": "git",
"url": "git://github.com/villadora/express-http-proxy.git"
},
"scripts": {
"lint": "eslint index.js **/*js",
"mocha": "mocha -R spec test --recursive --exit",
"test": "npm -s run mocha && npm run -s lint",
"test:debug": "mocha debug -R spec test --recursive --exit"
},
"version": "1.5.1"
}

160
node_modules/express-http-proxy/test/bodyEncoding.js generated vendored Normal file
View File

@@ -0,0 +1,160 @@
'use strict';
var assert = require('assert');
var express = require('express');
var request = require('supertest');
var fs = require('fs');
var os = require('os');
var proxy = require('../');
var startProxyTarget = require('./support/proxyTarget');
describe('body encoding', function () {
var server;
before(function () {
server = startProxyTarget(8109, 1000);
});
after(function () {
server.close();
});
this.timeout(10000);
var pngHex = '89504e470d0a1a0a0' +
'000000d4948445200' +
'00000100000001080' +
'60000001f15c48900' +
'00000a49444154789' +
'c6300010000050001' +
'0d0a2db4000000004' +
'9454e44ae426082';
var pngData = new Buffer(pngHex, 'hex');
it('allow raw data', function (done) {
var filename = os.tmpdir() + '/express-http-proxy-test-' + (new Date()).getTime() + '-png-transparent.png';
var app = express();
app.use(proxy('localhost:8109', {
reqBodyEncoding: null,
proxyReqBodyDecorator: function (bodyContent) {
assert((new Buffer(bodyContent).toString('hex')).indexOf(pngData.toString('hex')) >= 0,
'body should contain same data');
return bodyContent;
}
}));
fs.writeFile(filename, pngData, function (err) {
if (err) { throw err; }
request(app)
.post('/post')
.attach('image', filename)
.end(function (err) {
fs.unlinkSync(filename);
// This test is both broken and I think unnecessary.
// Its broken because http.bin no longer supports /post, but this test assertion is based on the old
// httpbin behavior.
// The assertion in the decorateRequest above verifies the test title.
//var response = new Buffer(res.body.attachment.data).toString('base64');
//assert(response.indexOf(pngData.toString('base64')) >= 0, 'response should include original raw data');
done(err);
});
});
});
describe('when user sets parseReqBody', function () {
it('should not parse body', function (done) {
var filename = os.tmpdir() + '/express-http-proxy-test-' + (new Date()).getTime() + '-png-transparent.png';
var app = express();
app.use(proxy('localhost:8109', {
parseReqBody: false,
proxyReqBodyDecorator: function (bodyContent) {
assert(!bodyContent, 'body content should not be parsed.');
return bodyContent;
}
}));
fs.writeFile(filename, pngData, function (err) {
if (err) { throw err; }
request(app)
.post('/post')
.attach('image', filename)
.end(function (err) {
fs.unlinkSync(filename);
// This test is both broken and I think unnecessary.
// Its broken because http.bin no longer supports /post, but this test assertion is based on the old
// httpbin behavior.
// The assertion in the decorateRequest above verifies the test title.
// var response = new Buffer(res.body.attachment.data).toString('base64');
// assert(response.indexOf(pngData.toString('base64')) >= 0, 'response should include original raw data');
done(err);
});
});
});
it('should not fail on large limit', function (done) {
var filename = os.tmpdir() + '/express-http-proxy-test-' + (new Date()).getTime() + '-png-transparent.png';
var app = express();
app.use(proxy('localhost:8109', {
parseReqBody: false,
limit: '20gb',
}));
fs.writeFile(filename, pngData, function (err) {
if (err) { throw err; }
request(app)
.post('/post')
.attach('image', filename)
.end(function (err) {
fs.unlinkSync(filename);
assert(err === null);
// This test is both broken and I think unnecessary.
// Its broken because http.bin no longer supports /post, but this test assertion is based on the old
// httpbin behavior.
// The assertion in the decorateRequest above verifies the test title.
//var response = new Buffer(res.body.attachment.data).toString('base64');
//assert(response.indexOf(pngData.toString('base64')) >= 0, 'response should include original raw data');
done(err);
});
});
});
it('should fail with an error when exceeding limit', function (done) {
var app = express();
app.use(proxy('localhost:8109', {
limit: 1,
}));
// silence jshint warning about unused vars - express error handler *needs* 4 args
app.use(function (err, req, res, next) { // eslint-disable-line no-unused-vars
res.json(err);
});
request(app)
.post('/post')
.send({ some: 'json' })
.end(function (err, response) {
assert(response.body.message === 'request entity too large');
done();
});
});
});
describe('when user sets reqBodyEncoding', function () {
it('should set the accepts-charset header', function (done) {
var app = express();
app.use(proxy('localhost:8109', {
reqBodyEncoding: 'utf-16'
}));
request(app)
.get('/headers')
.end(function (err, res) {
if (err) { throw err; }
assert.equal(res.body.headers['accept-charset'], 'utf-16');
done(err);
});
});
});
});

55
node_modules/express-http-proxy/test/catchingErrors.js generated vendored Normal file
View File

@@ -0,0 +1,55 @@
'use strict';
var assert = require('assert');
var express = require('express');
var request = require('supertest');
var proxy = require('../');
describe('when server responds with an error', function () {
this.timeout(10000);
var app;
var slowTarget;
var serverReference;
beforeEach(function () {
app = express();
});
afterEach(function () {
serverReference.close();
});
var STATUS_CODES = [
{ code: 403, text: 'Forbidden', toString: 'Error: cannot GET /proxy (403)' },
{ code: 404, text: 'Not Found', toString: 'Error: cannot GET /proxy (404)' },
{ code: 500, text: 'Internal Server Error', toString: 'Error: cannot GET /proxy (500)' }
];
STATUS_CODES.forEach(function (statusCode) {
it('express-http-proxy responds with ' + statusCode.text +
'when proxy server responds ' + statusCode.code, function (done) {
slowTarget = express();
slowTarget.use(function (req, res) { res.sendStatus(statusCode.code); });
serverReference = slowTarget.listen(12345);
app.use('/proxy', proxy('http://127.0.0.1:12345', {
reqAsBuffer: true,
reqBodyEncoding: null,
parseReqBody: false
}));
request(app)
.get('/proxy')
.expect(statusCode.code)
.end(function (err, res) {
assert(err === null);
assert(res.error);
assert(res.error.text === statusCode.text);
assert(res.error.toString() === statusCode.toString);
done();
});
});
});
});

48
node_modules/express-http-proxy/test/cookies.js generated vendored Normal file
View File

@@ -0,0 +1,48 @@
'use strict';
var assert = require('assert');
var express = require('express');
var request = require('supertest');
var proxy = require('../');
var proxyTarget = require('../test/support/proxyTarget');
var proxyRouteFn = [{
method: 'get',
path: '/cookieTest',
fn: function (req, res) {
Object.keys(req.cookies).forEach(function (key) {
res.cookie(key, req.cookies[key]);
});
res.sendStatus(200);
}
}];
describe('proxies cookie', function () {
this.timeout(10000);
var app;
var proxyServer;
beforeEach(function () {
proxyServer = proxyTarget(12346, 100, proxyRouteFn);
app = express();
app.use(proxy('localhost:12346'));
});
afterEach(function () {
proxyServer.close();
});
it('set cookie', function (done) {
request(app)
.get('/cookieTest')
.set('Cookie', 'myApp-token=12345667')
.end(function (err, res) {
var cookiesMatch = res.headers['set-cookie'].filter(function (item) {
return item.match(/myApp-token=12345667/);
});
assert(cookiesMatch);
done(err);
});
});
});

View File

@@ -0,0 +1,50 @@
'use strict';
var assert = require('assert');
var express = require('express');
var request = require('supertest');
var proxy = require('../');
describe('when userResHeaderDecorator is defined', function () {
this.timeout(10000);
var app;
var serverReference;
afterEach(function () {
serverReference.close();
});
beforeEach(function () {
app = express();
var pTarget = express();
pTarget.use(function (req, res) { res.json(req.headers); });
serverReference = pTarget.listen(12345);
});
afterEach(function () {
serverReference.close();
});
it('provides an interface for updating headers', function (done) {
app.use('/proxy', proxy('http://127.0.0.1:12345', {
userResHeaderDecorator: function (headers /*, userReq, userRes, proxyReq, proxyRes */) {
headers.boltedonheader = 'franky';
return headers;
}
}));
app.use(function (req, res) {
res.sendStatus(200);
});
request(app)
.get('/proxy')
.expect(function (res) {
assert(res.headers.boltedonheader === 'franky');
})
.end(done);
});
});

113
node_modules/express-http-proxy/test/filter.js generated vendored Normal file
View File

@@ -0,0 +1,113 @@
'use strict';
var express = require('express');
var request = require('supertest');
var proxy = require('../');
var proxyTarget = require('../test/support/proxyTarget');
var proxyRouteFn = [{
method: 'get',
path: '/',
fn: function (req, res) {
return res.status(209).send('Proxy Server');
}
}];
function nextMethod(req, res, next) {
res.status(201).send('Client Application');
next();
}
describe('filter', function () {
var app = express();
var proxyServer;
beforeEach(function () {
proxyServer = proxyTarget(12346, 100, proxyRouteFn);
app = express();
});
afterEach(function () {
proxyServer.close();
});
describe('when filter function returns true', function () {
it('continues route processing', function (done) {
// should capture every possible path
app.use(proxy('localhost:12346', {
filter: function () { return true; }
}));
// because prior line should *always* fire and return, we should never get here.
app.use(nextMethod);
request(app)
.get('/')
.expect(209)
.end(done);
});
});
describe('when filter function returns false', function () {
it('hanldes route processing', function (done) {
// should capture every possible path
app.use(proxy('localhost:12346', {
filter: function () { return false; }
}));
// because prior line should *always* fire skip, we should get here.
app.use(nextMethod);
request(app)
.get('/')
.expect(201)
.end(done);
});
});
describe('promise form', function () {
describe('when filter function returns true', function () {
it('continues route processing', function (done) {
// should capture every possible path
app.use(proxy('localhost:12346', {
filter: function () { return new Promise(function (resolve) { resolve(true); }); }
}));
// because prior line should *always* fire and return, we should never get here.
app.use(nextMethod);
request(app)
.get('/')
.expect(209)
.end(done);
});
});
describe('when filter function returns false', function () {
it('hanldes route processing', function (done) {
// should capture every possible path
app.use(proxy('localhost:12346', {
filter: function () { return new Promise(function (resolve) { resolve(false); }); }
}));
// because prior line should *always* fire skip, we should get here.
app.use(nextMethod);
request(app)
.get('/')
.expect(201)
.end(done);
});
});
});
});

View File

@@ -0,0 +1,136 @@
'use strict';
var assert = require('assert');
var express = require('express');
var request = require('supertest');
var proxy = require('../');
var proxyTarget = require('../test/support/proxyTarget');
var proxyRouteFn = [{
method: 'get',
path: '/:errorCode',
fn: function (req, res) {
var errorCode = req.params.errorCode;
if (errorCode === 'timeout') {
return res.status(504).send('mock timeout');
}
return res.status(parseInt(errorCode)).send('test case error');
}
}];
describe('error handling can be over-ridden by user', function () {
var app = express();
var proxyServer;
beforeEach(function () {
proxyServer = proxyTarget(12346, 100, proxyRouteFn);
app = express();
});
afterEach(function () {
proxyServer.close();
});
describe('when user provides a null function', function () {
describe('when author sets a timeout that fires', function () {
it('passes 504 directly to client', function (done) {
app.use(proxy('localhost:12346', {
timeout: 1,
}));
request(app)
.get('/200')
.expect(504)
.expect('X-Timeout-Reason', 'express-http-proxy reset the request.')
.end(done);
});
});
it('passes status code (e.g. 504) directly to the client', function (done) {
app.use(proxy('localhost:12346'));
request(app)
.get('/504')
.expect(504)
.expect(function (res) {
assert(res.text === 'test case error');
return res;
})
.end(done);
});
it('passes status code (e.g. 500) back to the client', function (done) {
app.use(proxy('localhost:12346'));
request(app)
.get('/500')
.expect(500)
.end(function (err, res) {
assert(res.text === 'test case error');
done();
});
});
});
describe('when user provides a handler function', function () {
var intentionallyWeirdStatusCode = 399;
var intentionallyQuirkyStatusMessage = 'monkey skunky';
describe('when author sets a timeout that fires', function () {
it('allows author to skip handling and handle in application step', function (done) {
app.use(proxy('localhost:12346', {
timeout: 1,
proxyErrorHandler: function (err, res, next) {
next(err);
}
}));
app.use(function (err, req, res, next) { // eslint-disable-line no-unused-vars
if (err.code === 'ECONNRESET') {
res.status(intentionallyWeirdStatusCode).send(intentionallyQuirkyStatusMessage);
}
});
request(app)
.get('/200')
.expect(function (res) {
assert(res.text === intentionallyQuirkyStatusMessage);
return res;
})
.expect(intentionallyWeirdStatusCode)
.end(done);
});
});
it('allows authors to sub in their own handling', function (done) {
app.use(proxy('localhost:12346', {
timeout: 1,
proxyErrorHandler: function (err, res, next) {
switch (err && err.code) {
case 'ECONNRESET': { return res.status(405).send('504 became 405'); }
case 'ECONNREFUSED': { return res.status(200).send('gotcher back'); }
default: { next(err); }
}
} }));
request(app)
.get('/timeout')
.expect(405)
.expect(function (res) {
assert(res.text === '504 became 405');
return res;
})
.end(done);
});
it('passes status code (e.g. 500) back to the client', function (done) {
app.use(proxy('localhost:12346'));
request(app)
.get('/500')
.expect(500)
.end(function (err, res) {
assert(res.text === 'test case error');
done();
});
});
});
});

45
node_modules/express-http-proxy/test/headers.js generated vendored Normal file
View File

@@ -0,0 +1,45 @@
'use strict';
var assert = require('assert');
var express = require('express');
var request = require('supertest');
var proxy = require('../');
describe('proxies headers', function () {
this.timeout(10000);
var http;
beforeEach(function () {
http = express();
http.use(proxy('http://httpbin.org', {
headers: {
'X-Current-president': 'taft'
}
}));
});
it('passed as options', function (done) {
request(http)
.get('/headers')
.expect(200)
.end(function (err, res) {
if (err) { return done(err); }
assert(res.body.headers['X-Current-President'] === 'taft');
done();
});
});
it('passed as on request', function (done) {
request(http)
.get('/headers')
.set('X-Powerererer', 'XTYORG')
.expect(200)
.end(function (err, res) {
if (err) { return done(err); }
assert(res.body.headers['X-Powerererer']);
done();
});
});
});

70
node_modules/express-http-proxy/test/host.js generated vendored Normal file
View File

@@ -0,0 +1,70 @@
'use strict';
var express = require('express');
var request = require('supertest');
var proxy = require('../');
describe('host can be a dynamic function', function () {
this.timeout(10000);
var app = express();
describe('and memoization can be disabled', function () {
var firstProxyApp = express();
var secondProxyApp = express();
// TODO: This seems like a bug factory. We will have intermittent port conflicts, yeah?
function randomNumberInPortRange() {
return Math.floor(Math.random() * 48000) + 1024;
}
var firstPort = randomNumberInPortRange();
var secondPort = randomNumberInPortRange();
var hostFn = function (req) {
return 'localhost:' + req.params.port;
};
app.use('/proxy/:port', proxy(hostFn, { memoizeHost: false }));
firstProxyApp
.get('/', function (req, res) { res.sendStatus(204); })
.listen(firstPort);
secondProxyApp
.get('/', function (req, res) { res.sendStatus(200); })
.listen(secondPort);
it('when not memoized, host resolves to a second value on the seecond call', function (done) {
request(app)
.get('/proxy/' + firstPort)
.expect(204)
.end(function (err) {
if (err) {
return done(err);
}
request(app)
.get('/proxy/' + secondPort)
.expect(200, done);
});
});
});
});
describe('host can be an ip address', function () {
it('with a port', function (done) {
var app = express();
app.use('/proxy/', proxy('127.0.0.1:3020'));
var targetApp = express();
targetApp
.get('/', function (req, res) { res.sendStatus(211); })
.listen(3020);
request(app)
.get('/proxy/')
.expect(211)
.end(done);
});
});

59
node_modules/express-http-proxy/test/https.js generated vendored Normal file
View File

@@ -0,0 +1,59 @@
'use strict';
var assert = require('assert');
var express = require('express');
var request = require('supertest');
var proxy = require('../');
describe('proxies https', function () {
this.timeout(10000);
var app;
beforeEach(function () {
app = express();
});
function assertSecureRequest(app, done) {
request(app)
.get('/get?show_env=1')
.end(function (err, res) {
if (err) { return done(err); }
assert(res.body.headers['X-Forwarded-Port'] === '443', 'Expects forwarded 443 Port');
assert(res.body.headers['X-Forwarded-Proto'] === 'https', 'Expects forwarded protocol to be https');
done();
});
}
describe('when host is a String', function () {
describe('and includes "https" as protocol', function () {
it('proxys via https', function (done) {
app.use(proxy('https://httpbin.org'));
assertSecureRequest(app, done);
});
});
describe('option https is set to "true"', function () {
it('proxys via https', function (done) {
app.use(proxy('http://httpbin.org', { https: true }));
assertSecureRequest(app, done);
});
});
});
describe('when host is a Function', function () {
describe('returned value includes "https" as protocol', function () {
it('proxys via https', function (done) {
app.use(proxy(function () { return 'https://httpbin.org'; }));
assertSecureRequest(app, done);
});
});
describe('option https is set to "true"', function () {
it('proxys via https', function (done) {
app.use(proxy(function () { return 'http://httpbin.org'; }, { https: true }));
assertSecureRequest(app, done);
});
});
});
});

View File

@@ -0,0 +1,57 @@
'use strict';
var express = require('express');
var request = require('supertest');
var proxy = require('../');
var http = require('http');
var assert = require('assert');
describe('when skipToNextHandlerFilter is defined', function () {
this.timeout(10000);
var app;
var slowTarget;
var serverReference;
beforeEach(function () {
app = express();
slowTarget = express();
slowTarget.use(function (req, res) { res.sendStatus(404); });
serverReference = slowTarget.listen(12345);
});
afterEach(function () {
serverReference.close();
});
var OUTCOMES = [
{ shouldSkip: true, expectedStatus: 200 },
{ shouldSkip: false, expectedStatus: 404 }
];
OUTCOMES.forEach(function (outcome) {
describe('and returns ' + outcome.shouldSkip, function () {
it('express-http-proxy' + (outcome.shouldSkip ? ' skips ' : ' doesnt skip ') + 'to next()', function (done) {
app.use('/proxy', proxy('http://127.0.0.1:12345', {
skipToNextHandlerFilter: function (/*res*/) {
return outcome.shouldSkip;
}
}));
app.use(function (req, res) {
assert(res.expressHttpProxy instanceof Object);
assert(res.expressHttpProxy.res instanceof http.IncomingMessage);
assert(res.expressHttpProxy.req instanceof Object);
res.sendStatus(200);
});
request(app)
.get('/proxy')
.expect(outcome.expectedStatus)
.end(done);
});
});
});
});

View File

@@ -0,0 +1,110 @@
'use strict';
var assert = require('assert');
var express = require('express');
var request = require('supertest');
var bodyParser = require('body-parser');
var proxy = require('../');
var proxyTarget = require('../test/support/proxyTarget');
var proxyRouteFn = [{
method: 'post',
path: '/poster',
fn: function (req, res) {
res.send(req.body);
}
}];
describe('middleware compatibility', function () {
var proxyServer;
beforeEach(function () {
proxyServer = proxyTarget(12346, 100, proxyRouteFn);
});
afterEach(function () {
proxyServer.close();
});
it('should use req.body if defined', function (done) {
var app = express();
// Simulate another middleware that puts req stream into the body
app.use(function (req, res, next) {
var received = [];
req.on('data', function onData(chunk) {
if (!chunk) { return; }
received.push(chunk);
});
req.on('end', function onEnd() {
received = Buffer.concat(received).toString('utf8');
req.body = JSON.parse(received);
req.body.foo = 1;
next();
});
});
app.use(proxy('localhost:12346', {
intercept: function (rsp, data, req) {
assert(req.body);
assert.equal(req.body.foo, 1);
assert.equal(req.body.mypost, 'hello');
return data;
}
}));
request(app)
.post('/poster')
.send({ mypost: 'hello' })
.expect(function (res) {
assert.equal(res.body.foo, 1);
assert.equal(res.body.mypost, 'hello');
})
.end(done);
});
it('should stringify req.body when it is a json body so it is written to proxy request', function (done) {
var app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: false
}));
app.use(proxy('localhost:12346'));
request(app)
.post('/poster')
.send({
mypost: 'hello',
doorknob: 'wrect'
})
.expect(function (res) {
assert.equal(res.body.doorknob, 'wrect');
assert.equal(res.body.mypost, 'hello');
})
.end(done);
});
it('should convert req.body to a Buffer when reqAsBuffer is set', function (done) {
var app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: false
}));
app.use(proxy('localhost:12346', {
reqAsBuffer: true
}));
request(app)
.post('/poster')
.send({
mypost: 'hello',
doorknob: 'wrect'
})
.expect(function (res) {
assert.equal(res.body.doorknob, 'wrect');
assert.equal(res.body.mypost, 'hello');
})
.end(done);
});
});

41
node_modules/express-http-proxy/test/params.js generated vendored Normal file
View File

@@ -0,0 +1,41 @@
'use strict';
var assert = require('assert');
var express = require('express');
var request = require('supertest');
var proxy = require('../');
var proxyTarget = require('../test/support/proxyTarget');
var proxyRouteFn = [{
method: 'get',
path: '/test',
fn: function (req, res) {
res.send(req.url);
}
}];
describe('proxies query parameters', function () {
this.timeout(10000);
var app;
var proxyServer;
beforeEach(function () {
proxyServer = proxyTarget(12346, 100, proxyRouteFn);
app = express();
app.use(proxy('localhost:12346'));
});
afterEach(function () {
proxyServer.close();
});
it('repeats query params to proxy server', function (done) {
request(app)
.get('/test?a=1&b=2&c=3')
.end(function (err, res) {
assert.equal(res.text, '/test?a=1&b=2&c=3');
done(err);
});
});
});

95
node_modules/express-http-proxy/test/path.js generated vendored Normal file
View File

@@ -0,0 +1,95 @@
'use strict';
var express = require('express');
var request = require('supertest');
var proxy = require('../');
var startProxyTarget = require('./support/proxyTarget');
var expect = require('chai').expect;
describe('uses remote path', function () {
this.timeout(10000);
var app = express();
var proxyRoutes = ['/somePath/', '/somePath/longer/path', '/somePath/long/path/with/many/tokens'];
var proxyKeyPath = '/somePath';
var server;
afterEach(function () {
server.close();
});
proxyRoutes.forEach(function (path) {
it('uses path component from inbound request', function (done) {
var modifiedPath = path.replace(new RegExp(proxyKeyPath), '');
var proxyRouteFn = {
method: 'get',
path: modifiedPath,
fn: function (req, res) {
res.json({ path: path, modifiedPath: modifiedPath });
}
};
server = startProxyTarget(8309, 1000, [proxyRouteFn]);
app.use('/somePath/', proxy('http://localhost:8309'));
request(app)
.get(path)
.expect(200)
.end(function (err, response) {
if (err) {
return done(err);
}
expect(response.path === path);
expect(response.modifiedPath === path);
done();
});
});
});
});
describe('host can be a dynamic function', function () {
this.timeout(10000);
var app = express();
var firstProxyApp = express();
var secondProxyApp = express();
var firstPort = 10031;
var secondPort = 10032;
app.use('/proxy/:port', proxy(function (req) {
return 'localhost:' + req.params.port;
}, {
memoizeHost: false
}));
firstProxyApp.use('/', function (req, res) {
res.sendStatus(204);
});
firstProxyApp.listen(firstPort);
secondProxyApp.use('/', function (req, res) {
res.sendStatus(200);
});
secondProxyApp.listen(secondPort);
it('can proxy with session value', function (done) {
request(app)
.get('/proxy/' + firstPort)
.expect(204)
.end(function (err) {
if (err) {
return done(err);
}
request(app)
.get('/proxy/' + secondPort)
.expect(200, done);
});
});
});

84
node_modules/express-http-proxy/test/port.js generated vendored Normal file
View File

@@ -0,0 +1,84 @@
'use strict';
var assert = require('assert');
var express = require('express');
var request = require('supertest');
var proxy = require('../');
function proxyTarget(port) {
var other = express();
other.get('/', function (req, res) {
res.send('Success');
});
return other.listen(port);
}
describe('proxies to requested port', function () {
var other;
var http;
beforeEach(function () {
http = express();
other = proxyTarget(56001);
});
afterEach(function () {
other.close();
});
function assertSuccess(server, done) {
request(http)
.get('/')
.expect(200)
.end(function (err, res) {
if (err) { return done(err); }
assert(res.text === 'Success');
done();
});
}
describe('when host is a String', function () {
it('when passed as an option', function (done) {
http.use(proxy('http://localhost', {
port: 56001
}));
assertSuccess(http, done);
});
it('when passed on the host string', function (done) {
http.use(proxy('http://localhost:56001'));
assertSuccess(http, done);
});
});
describe('when host is a function', function () {
it('and port is on the String returned', function (done) {
http.use(proxy(
function () { return 'http://localhost:56001'; }
));
assertSuccess(http, done);
});
it('and port passed as an option', function (done) {
http.use(proxy(
function () { return 'http://localhost'; },
{ port: 56001 }
));
assertSuccess(http, done);
});
});
});

65
node_modules/express-http-proxy/test/postBody.js generated vendored Normal file
View File

@@ -0,0 +1,65 @@
'use strict';
var assert = require('assert');
var express = require('express');
var request = require('supertest');
var proxy = require('../');
var bodyParser = require('body-parser');
function createLocalApplicationServer() {
var app = express();
return app;
}
function createProxyApplicationServer() {
var pTarget = express();
pTarget.use(bodyParser.json());
pTarget.use(bodyParser.urlencoded({ extended: true }));
pTarget.use(function (req, res) {
assert(req.body.name === 'tobi'); //, 'Assert that the value posted to the local server is passed to the proxy');
res.json(req.body);
});
return pTarget.listen(12345);
}
describe('when proxy request is a POST', function () {
this.timeout(10000);
var localServer;
var proxyServer;
beforeEach(function () {
localServer = createLocalApplicationServer();
proxyServer = createProxyApplicationServer();
});
afterEach(function () {
proxyServer.close();
});
var testCases = [
{ name: 'form encoded', encoding: 'application/x-www-form-urlencoded' },
{ name: 'JSON encoded', encoding: 'application/json' }
];
testCases.forEach(function (test) {
it('should deliver the post body when ' + test.name, function (done) {
localServer.use('/proxy', proxy('http://127.0.0.1:12345'));
localServer.use(function (req, res) { res.sendStatus(200); });
localServer.use(function (err, req, res, next) { throw new Error(err, req, res, next); });
request(localServer)
.post('/proxy')
.send({ name: 'tobi' })
.set('Content-Type', test.encoding)
.expect(function (res) {
assert(res.body.name === 'tobi');
})
.end(done);
});
});
});

View File

@@ -0,0 +1,70 @@
'use strict';
var assert = require('assert');
var express = require('express');
var request = require('supertest');
var proxy = require('../');
var proxyTarget = require('../test/support/proxyTarget');
var proxyRouteFn = [{
method: 'get',
path: '/hostHdrTest',
fn: function (req, res) {
res.send(req.headers.host);
}
}];
describe('preserves host header only when requested', function () {
this.timeout(10000);
var app;
var proxyServer;
describe('when preserveHostHdr is true', function () {
before(function () {
proxyServer = proxyTarget(12346, 100, proxyRouteFn);
app = express();
app.use(proxy('localhost:12346', {
preserveHostHdr: true
}));
});
after(function () {
proxyServer.close();
});
it('host is passed forward', function (done) {
request(app)
.get('/hostHdrTest')
.set('host', 'hamburger-helper')
.end(function (err, res) {
assert(res.text === 'hamburger-helper');
done();
});
});
});
describe('when preserveHostHdr is absent or false', function () {
before(function () {
proxyServer = proxyTarget(12346, 100, proxyRouteFn);
app = express();
app.use(proxy('localhost:12346'));
});
after(function () {
proxyServer.close();
});
it('host is not passed forward', function (done) {
request(app)
.get('/hostHdrTest')
.set('host', 'hamburger-helper')
.end(function (err, res) {
assert(res.text !== 'hamburger-helper');
done();
});
});
});
});

View File

@@ -0,0 +1,150 @@
'use strict';
var assert = require('assert');
var express = require('express');
var http = require('http');
var request = require('supertest');
var proxy = require('../');
var proxyTarget = require('../test/support/proxyTarget');
describe('proxyReqOptDecorator', function () {
var server;
this.timeout(10000);
before(function () {
var handlers = [{
method: 'get',
path: '/working',
fn: function (req, res) {
res.send({ headers: req.headers });
}
}];
server = proxyTarget(12345, 100, handlers);
});
after(function () {
server.close();
});
this.timeout(10000);
var app;
beforeEach(function () {
app = express();
app.use(proxy('localhost:12345'));
});
describe('allows authors to modify a number of request parameters', function () {
it('modify headers', function (done) {
app = express();
app.use(proxy('localhost:12345', {
proxyReqOptDecorator: function (reqOpt) {
reqOpt.headers['user-agent'] = 'test user agent';
reqOpt.headers.mmmmmmmmmm = 'misty mountain hop';
return reqOpt;
}
}));
request(app)
.get('/working')
.end(function (err, res) {
if (err) { return done(err); }
assert.equal(res.body.headers['user-agent'], 'test user agent');
assert.equal(res.body.headers.mmmmmmmmmm, 'misty mountain hop');
done();
});
});
describe('when proxyReqOptDecorator is a simple function (non Promise)', function () {
it('can modify headers', function (done) {
var app = express();
app.use(proxy('localhost:12345', {
proxyReqOptDecorator: function (reqOpt, req) {
reqOpt.headers['user-agent'] = 'test user agent';
assert(req instanceof http.IncomingMessage);
return reqOpt;
}
}));
request(app)
.get('/working')
.end(function (err, res) {
if (err) { return done(err); }
assert.equal(res.body.headers['user-agent'], 'test user agent');
done();
});
});
});
describe('when proxyReqOptDecorator is a Promise', function () {
it('should mutate the proxied request', function (done) {
var app = express();
app.use(proxy('localhost:12345', {
proxyReqOptDecorator: function (reqOpt, req) {
assert(req instanceof http.IncomingMessage);
return new Promise(function (resolve) {
reqOpt.headers['user-agent'] = 'test user agent';
resolve(reqOpt);
});
}
}));
request(app)
.get('/working')
.end(function (err, res) {
if (err) { return done(err); }
assert.equal(res.body.headers['user-agent'], 'test user agent');
done();
});
});
describe('when the Promise is rejected', function () {
it('returns err to host application for processing', function (done) {
var app = express();
app.use(proxy('/reject-promise', {
proxyReqOptDecorator: function () {
return Promise.reject('An arbitrary rejection message.');
}
}));
/* jshint ignore:start */
app.use(function (err, req, res, next) { // eslint-disable-line no-unused-vars
assert(err === 'An arbitrary rejection message.');
res.status(221).send(err);
});
/* jshint ignore:end */
request(app)
.get('/reject-promise')
.expect(221, done); // ensures we've entered the handler with assert above
});
});
});
});
describe('proxyReqOptDecorator has access to the source request\'s data', function () {
it('should have access to ip', function (done) {
var app = express();
app.use(proxy('localhost:12345', {
proxyReqOptDecorator: function (reqOpts, req) {
assert(req instanceof http.IncomingMessage);
assert(req.ip);
return reqOpts;
}
}));
request(app)
.get('/working')
.end(function (err) {
if (err) { return done(err); }
done();
});
});
});
});

View File

@@ -0,0 +1,64 @@
'use strict';
var assert = require('assert');
var express = require('express');
var http = require('http');
var request = require('supertest');
var proxy = require('../');
var proxyTarget = require('../test/support/proxyTarget');
var aliases = ['forwardPath', 'forwardPathAsync', 'proxyReqPathResolver'];
describe('resolveProxyReqPath', function () {
var server;
this.timeout(10000);
before(function () {
var handlers = [{
method: 'get',
path: '/working',
fn: function (req, res) {
res.sendStatus(200);
}
}];
server = proxyTarget(12345, 100, handlers);
});
after(function () {
server.close();
});
aliases.forEach(function (alias) {
describe('when author uses option ' + alias, function () {
it('the proxy request path is the result of the function', function (done) {
var app = express();
var opts = {};
opts[alias] = function () { return '/working'; };
app.use(proxy('localhost:12345', opts));
request(app)
.get('/failing')
.expect(200)
.end(done);
});
it('the ' + alias + ' method has access to request object', function (done) {
var app = express();
app.use(proxy('localhost:12345', {
forwardPath: function (req) {
assert.ok(req instanceof http.IncomingMessage);
return '/working';
}
}));
request(app)
.get('/foobar')
.expect(200)
.end(done);
});
});
});
});

View File

@@ -0,0 +1,116 @@
'use strict';
var assert = require('assert');
var ScopeContainer = require('../lib/scopeContainer');
var resolveProxyReqPath = require('../app/steps/resolveProxyReqPath');
var expect = require('chai').expect;
var express = require('express');
var request = require('supertest');
var proxy = require('../');
describe('resolveProxyReqPath', function () {
var container;
beforeEach(function () {
container = new ScopeContainer();
});
var tests = [
{
resolverType: 'undefined',
resolverFn: undefined,
data: [
{ url: 'http://localhost:12345', parsed: '/' },
{ url: 'http://g.com/123?45=67', parsed: '/123?45=67' }
]
},
{
resolverType: 'a syncronous function',
resolverFn: function () { return 'the craziest thing'; },
data: [
{ url: 'http://localhost:12345', parsed: 'the craziest thing' },
{ url: 'http://g.com/123?45=67', parsed: 'the craziest thing' }
]
},
{
resolverType: 'a Promise',
resolverFn: function () {
return new Promise(function (resolve) {
resolve('the craziest think');
});
},
data: [
{ url: 'http://localhost:12345', parsed: 'the craziest think' },
{ url: 'http://g.com/123?45=67', parsed: 'the craziest think' }
]
}
];
describe('when proxyReqPathResolver', function () {
tests.forEach(function (test) {
describe('is ' + test.resolverType, function () {
describe('it returns a promise which resolves a container with expected url', function () {
test.data.forEach(function (data) {
it(data.url, function (done) {
container.user.req = { url: data.url };
container.options.proxyReqPathResolver = test.resolverFn;
var r = resolveProxyReqPath(container);
assert(r instanceof Promise, 'Expect resolver to return a thennable');
r.then(function (container) {
var response;
try {
response = container.proxy.reqBuilder.path;
if (!response) {
throw new Error('reqBuilder.url is undefined');
}
} catch (e) {
done(e);
}
expect(response).to.equal(data.parsed);
done();
});
});
});
});
});
});
});
describe('testing example code in docs', function () {
it('works as advertised', function (done) {
var proxyTarget = require('../test/support/proxyTarget');
var proxyRouteFn = [{
method: 'get',
path: '/tent',
fn: function (req, res) {
res.send(req.url);
}
}];
var proxyServer = proxyTarget(12345, 100, proxyRouteFn);
var app = express();
app.use(proxy('localhost:12345', {
proxyReqPathResolver: function (req) {
var parts = req.url.split('?');
var queryString = parts[1];
var updatedPath = parts[0].replace(/test/, 'tent');
return updatedPath + (queryString ? '?' + queryString : '');
}
}));
request(app)
.get('/test?a=1&b=2&c=3')
.end(function (err, res) {
assert.equal(res.text, '/tent?a=1&b=2&c=3');
proxyServer.close();
done(err);
});
});
});
});

40
node_modules/express-http-proxy/test/session.js generated vendored Normal file
View File

@@ -0,0 +1,40 @@
'use strict';
var assert = require('assert');
var express = require('express');
var request = require('supertest');
var proxy = require('../');
describe('preserveReqSession', function () {
this.timeout(10000);
var app;
beforeEach(function () {
app = express();
app.use(proxy('httpbin.org'));
});
it('preserveReqSession', function (done) {
var app = express();
app.use(function (req, res, next) {
req.session = 'hola';
next();
});
app.use(proxy('httpbin.org', {
preserveReqSession: true,
proxyReqOptDecorator: function (reqOpts) {
assert(reqOpts.session, 'hola');
return reqOpts;
}
}));
request(app)
.get('/user-agent')
.end(function (err) {
if (err) { return done(err); }
done();
});
});
});

31
node_modules/express-http-proxy/test/status.js generated vendored Normal file
View File

@@ -0,0 +1,31 @@
'use strict';
var express = require('express');
var request = require('supertest');
var proxy = require('../');
var mockEndpoint = require('../lib/mockHTTP.js');
describe('proxies status code', function () {
var proxyServer = express();
var port = 21239;
var proxiedEndpoint = 'http://localhost:' + port;
var server;
proxyServer.use(proxy(proxiedEndpoint));
beforeEach(function () {
server = mockEndpoint.listen(21239);
});
afterEach(function () {
server.close();
});
[304, 404, 200, 401, 500].forEach(function (status) {
it('on ' + status, function (done) {
request(proxyServer)
.get('/status/' + status)
.expect(status, done);
});
});
});

121
node_modules/express-http-proxy/test/streaming.js generated vendored Normal file
View File

@@ -0,0 +1,121 @@
'use strict';
var assert = require('assert');
var express = require('express');
var http = require('http');
var startProxyTarget = require('./support/proxyTarget');
var proxy = require('../');
function chunkingProxyServer() {
var proxyRouteFn = [{
method: 'get',
path: '/stream',
fn: function (req, res) {
res.write('0');
setTimeout(function () { res.write('1'); }, 100);
setTimeout(function () { res.write('2'); }, 200);
setTimeout(function () { res.write('3'); }, 300);
setTimeout(function () { res.end(); }, 500);
}
}];
return startProxyTarget(8309, 1000, proxyRouteFn);
}
function simulateUserRequest() {
return new Promise(function (resolve, reject) {
var req = http.request({ hostname: 'localhost', port: 8308, path: '/stream' }, function (res) {
var chunks = [];
res.on('data', function (chunk) { chunks.push(chunk.toString()); });
res.on('end', function () { resolve(chunks); });
});
req.on('error', function (e) {
reject('problem with request:', e.message);
});
req.end();
});
}
function startLocalServer(proxyOptions) {
var app = express();
app.get('/stream', proxy('http://localhost:8309', proxyOptions));
return app.listen(8308);
}
describe('streams / piped requests', function () {
this.timeout(3000);
var server;
var targetServer;
beforeEach(function () {
targetServer = chunkingProxyServer();
});
afterEach(function () {
server.close();
targetServer.close();
});
describe('when streaming options are truthy', function () {
var TEST_CASES = [{
name: 'vanilla, no options defined',
options: {}
}, {
name: 'proxyReqOptDecorator is defined',
options: { proxyReqOptDecorator: function (reqBuilder) { return reqBuilder; } }
}, {
//// Keep around this case for manually testing that this for sure fails for a few cycles. 2018 NMK
//name: 'proxyReqOptDecorator never returns',
//options: { proxyReqOptDecorator: function () { return new Promise(function () {}); } }
//}, {
name: 'proxyReqOptDecorator is a Promise',
options: { proxyReqOptDecorator: function (reqBuilder) { return Promise.resolve(reqBuilder); } }
}];
TEST_CASES.forEach(function (testCase) {
describe(testCase.name, function () {
it('chunks are received without any buffering, e.g. before request end', function (done) {
server = startLocalServer(testCase.options);
simulateUserRequest()
.then(function (res) {
// Assume that if I'm getting a chunked response, it will be an array of length > 1;
assert(res instanceof Array, 'res is an Array');
assert.equal(res.length, 4);
done();
})
.catch(done);
});
});
});
});
describe('when streaming options are falsey', function () {
var TEST_CASES = [{
name: 'skipToNextHandler is defined',
options: { skipToNextHandlerFilter: function () { return false; } }
}];
TEST_CASES.forEach(function (testCase) {
describe(testCase.name, function () {
it('response arrives in one large chunk', function (done) {
server = startLocalServer(testCase.options);
simulateUserRequest()
.then(function (res) {
// Assume that if I'm getting a un-chunked response, it will be an array of length = 1;
assert(res instanceof Array);
assert.equal(res.length, 1);
done();
})
.catch(done);
});
});
});
});
});

View File

@@ -0,0 +1,55 @@
'use strict';
var express = require('express');
var bodyParser = require('body-parser');
var cookieParser = require('cookie-parser');
function proxyTarget(port, timeout, handlers) {
var target = express();
timeout = timeout || 100;
// parse application/x-www-form-urlencoded
target.use(bodyParser.urlencoded({ extended: false }));
// parse application/json
target.use(bodyParser.json());
target.use(cookieParser());
target.use(function(req, res, next) {
setTimeout(function() {
next();
},timeout);
});
if (handlers) {
handlers.forEach(function(handler) {
target[handler.method](handler.path, handler.fn);
});
}
target.get('/get', function (req, res) {
res.send('OK');
});
target.post('/post', function(req, res) {
req.pipe(res);
});
target.use('/headers', function(req, res) {
res.json({ headers: req.headers });
});
target.use(function(err, req, res, next) {
res.send(err);
next();
});
target.use(function(req, res) {
res.sendStatus(404);
});
return target.listen(port);
}
module.exports = proxyTarget;

63
node_modules/express-http-proxy/test/timeout.js generated vendored Normal file
View File

@@ -0,0 +1,63 @@
'use strict';
var express = require('express');
var request = require('supertest');
var proxy = require('../');
var proxyTarget = require('./support/proxyTarget');
describe('honors timeout option', function () {
var other;
var http;
beforeEach(function () {
http = express();
other = proxyTarget(56001, 1000, [{
method: 'get',
path: '/',
fn: function (req, res) { res.sendStatus(200); }
}]);
});
afterEach(function () {
other.close();
});
function assertSuccess(server, done) {
request(http)
.get('/')
.expect(200)
.end(done);
}
function assertConnectionTimeout(server, done) {
request(http)
.get('/')
.expect(504)
.expect('X-Timeout-Reason', 'express-http-proxy reset the request.')
.end(done);
}
describe('when timeout option is set lower than server response time', function () {
it('should fail with CONNECTION TIMEOUT', function (done) {
http.use(proxy('http://localhost:56001', {
timeout: 100,
}));
assertConnectionTimeout(http, done);
});
});
describe('when timeout option is set higher than server response time', function () {
it('should succeed', function (done) {
http.use(proxy('http://localhost:56001', {
timeout: 1200,
}));
assertSuccess(http, done);
});
});
});

41
node_modules/express-http-proxy/test/traceDebugging.js generated vendored Normal file
View File

@@ -0,0 +1,41 @@
'use strict';
var debug = require('debug');
var express = require('express');
var request = require('supertest');
var proxy = require('../');
var proxyTarget = require('../test/support/proxyTarget');
/* This test is specifically written because of critical errors thrown while debug logging. */
describe.only('trace debugging does not cause the application to fail', function () {
var proxyServer;
beforeEach(function () { debug.enable('express-http-proxy'); proxyServer = proxyTarget(3000); });
afterEach(function () { debug.disable('express-http-proxy'); proxyServer.close(); });
it('happy path', function (done) {
var app = express();
app.use(proxy('localhost:3000'));
request(app)
.get('/get')
.expect(200)
.end(done);
});
it('when agent is a deeply nested object', function (done) {
var app = express();
var HttpAgent = require('http').Agent;
var httpAgent = new HttpAgent({ keepAlive: true, keepAliveMsecs: 60e3 });
app.use(proxy('localhost:3000', {
proxyReqOptDecorator: function (proxyReqOpts) {
proxyReqOpts.agent = httpAgent;
return proxyReqOpts;
}
}));
request(app)
.get('/get')
.expect(200)
.end(done);
});
});

37
node_modules/express-http-proxy/test/urlParsing.js generated vendored Normal file
View File

@@ -0,0 +1,37 @@
'use strict';
var assert = require('assert');
var express = require('express');
var request = require('supertest');
var proxy = require('../');
describe('url parsing', function () {
this.timeout(10000);
it('can parse a url with a port', function (done) {
var app = express();
app.use(proxy('http://httpbin.org:80'));
request(app)
.get('/')
.end(function (err) {
if (err) { return done(err); }
assert(true);
done();
});
});
it('does not throw `Uncaught RangeError` if you have both a port and a trailing slash', function (done) {
var app = express();
app.use(proxy('http://httpbin.org:80/'));
request(app)
.get('/')
.end(function (err) {
if (err) { return done(err); }
assert(true);
done();
});
});
});

View File

@@ -0,0 +1,213 @@
'use strict';
var assert = require('assert');
var express = require('express');
var request = require('supertest');
var proxy = require('../');
describe('userResDecorator', function () {
describe('when handling a 304', function () {
this.timeout(10000);
var app;
var slowTarget;
var serverReference;
beforeEach(function () {
app = express();
slowTarget = express();
slowTarget.use(function (req, res) { res.sendStatus(304); });
serverReference = slowTarget.listen(12345);
});
afterEach(function () {
serverReference.close();
});
it('skips any handling', function (done) {
app.use('/proxy', proxy('http://127.0.0.1:12345', {
userResDecorator: function (/*res*/) {
throw new Error('expected to never get here because this step should be skipped for 304');
}
}));
request(app)
.get('/proxy')
.expect(304)
.end(done);
});
});
it('has access to original response', function (done) {
var app = express();
app.use(proxy('httpbin.org', {
userResDecorator: function (proxyRes, proxyResData) {
assert(proxyRes.connection);
assert(proxyRes.socket);
assert(proxyRes.headers);
assert(proxyRes.headers['content-type']);
return proxyResData;
}
}));
request(app).get('/').end(done);
});
it('works with promises', function (done) {
var app = express();
app.use(proxy('httpbin.org', {
userResDecorator: function (proxyRes, proxyResData) {
return new Promise(function (resolve) {
proxyResData.funkyMessage = 'oi io oo ii';
setTimeout(function () {
resolve(proxyResData);
}, 200);
});
}
}));
request(app)
.get('/ip')
.end(function (err, res) {
if (err) { return done(err); }
assert(res.body.funkyMessage = 'oi io oo ii');
done();
});
});
it('can modify the response data', function (done) {
var app = express();
app.use(proxy('httpbin.org', {
userResDecorator: function (proxyRes, proxyResData) {
proxyResData = JSON.parse(proxyResData.toString('utf8'));
proxyResData.intercepted = true;
return JSON.stringify(proxyResData);
}
}));
request(app)
.get('/ip')
.end(function (err, res) {
if (err) { return done(err); }
assert(res.body.intercepted);
done();
});
});
it('can modify the response headers, [deviant case, supported by pass-by-reference atm]', function (done) {
var app = express();
app.use(proxy('httpbin.org', {
userResDecorator: function (rsp, data, req, res) {
res.set('x-wombat-alliance', 'mammels');
res.set('content-type', 'wiki/wiki');
return data;
}
}));
request(app)
.get('/ip')
.end(function (err, res) {
if (err) { return done(err); }
assert(res.headers['content-type'] === 'wiki/wiki');
assert(res.headers['x-wombat-alliance'] === 'mammels');
done();
});
});
it('can mutuate an html response', function (done) {
var app = express();
app.use(proxy('httpbin.org', {
userResDecorator: function (rsp, data) {
data = data.toString().replace('Oh', '<strong>Hey</strong>');
assert(data !== '');
return data;
}
}));
request(app)
.get('/html')
.end(function (err, res) {
if (err) { return done(err); }
assert(res.text.indexOf('<strong>Hey</strong>') > -1);
done();
});
});
it('can change the location of a redirect', function (done) {
function redirectingServer(port, origin) {
var app = express();
app.get('/', function (req, res) {
res.status(302);
res.location(origin + '/proxied/redirect/url');
res.send();
});
return app.listen(port);
}
var redirectingServerPort = 8012;
var redirectingServerOrigin = ['http://localhost', redirectingServerPort].join(':');
var server = redirectingServer(redirectingServerPort, redirectingServerOrigin);
var proxyApp = express();
var preferredPort = 3000;
proxyApp.use(proxy(redirectingServerOrigin, {
userResDecorator: function (rsp, data, req, res) {
var proxyReturnedLocation = res._headers.location;
res.location(proxyReturnedLocation.replace(redirectingServerPort, preferredPort));
return data;
}
}));
request(proxyApp)
.get('/')
.expect(function (res) {
res.headers.location.match(/localhost:3000/);
})
.end(function () {
server.close();
done();
});
});
});
describe('test userResDecorator on html response from github', function () {
/*
Github provided a unique situation where the encoding was different than
utf-8 when we didn't explicitly ask for utf-8. This test helped sort out
the issue, and even though its a little too on the nose for a specific
case, it seems worth keeping around to ensure we don't regress on this
issue.
*/
it('is able to read and manipulate the response', function (done) {
this.timeout(15000); // give it some extra time to get response
var app = express();
app.use(proxy('https://github.com/villadora/express-http-proxy', {
userResDecorator: function (targetResponse, data) {
data = data.toString().replace('DOCTYPE', 'WINNING');
assert(data !== '');
return data;
}
}));
request(app)
.get('/html')
.end(function (err, res) {
if (err) { return done(err); }
assert(res.text.indexOf('WINNING') > -1);
done();
});
});
});

90
node_modules/express-http-proxy/test/verbs.js generated vendored Normal file
View File

@@ -0,0 +1,90 @@
'use strict';
var assert = require('assert');
var express = require('express');
var bodyParser = require('body-parser');
var request = require('supertest');
var proxy = require('../');
describe('http verbs', function () {
this.timeout(10000);
var app;
beforeEach(function () {
app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(proxy('httpbin.org'));
});
it('test proxy get', function (done) {
request(app)
.get('/get')
.end(function (err, res) {
if (err) { return done(err); }
assert(/node-superagent/.test(res.body.headers['User-Agent']));
assert.equal(res.body.url, 'http://httpbin.org/get');
done(err);
});
});
it('test proxy post', function (done) {
request(app)
.post('/post')
.send({
mypost: 'hello'
})
.end(function (err, res) {
assert.equal(res.body.data, '{"mypost":"hello"}');
done(err);
});
});
it('test proxy post by x-www-form-urlencoded', function (done) {
request(app)
.post('/post')
.set('Content-Type', 'application/x-www-form-urlencoded')
.send('mypost=hello')
.end(function (err, res) {
assert.equal(JSON.stringify(res.body.form), '{"mypost":"hello"}');
done(err);
});
});
it('test proxy put', function (done) {
request(app)
.put('/put')
.send({
mypost: 'hello'
})
.end(function (err, res) {
assert.equal(res.body.data, '{"mypost":"hello"}');
done(err);
});
});
it('test proxy patch', function (done) {
request(app)
.patch('/patch')
.send({
mypost: 'hello'
})
.end(function (err, res) {
assert.equal(res.body.data, '{"mypost":"hello"}');
done(err);
});
});
it('test proxy delete', function (done) {
request(app)
.del('/delete')
.send({
mypost: 'hello'
})
.end(function (err, res) {
assert.equal(res.body.data, '{"mypost":"hello"}');
done(err);
});
});
});