Skip to content

feat: remove shorthand usage [BREAKING CHANGE] #716

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 19, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 16 additions & 47 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,12 @@ _All_ `http-proxy` [options](https://github.com/nodejitsu/node-http-proxy#option
- [Install](#install)
- [Core concept](#core-concept)
- [Example](#example)
- [app.use(path, proxy)](#appusepath-proxy)
- [Context matching](#context-matching)
- [Options](#options)
- [http-proxy-middleware options](#http-proxy-middleware-options)
- [http-proxy events](#http-proxy-events)
- [http-proxy options](#http-proxy-options)
- [Shorthand](#shorthand)
- [app.use(path, proxy)](#appusepath-proxy)
- [WebSocket](#websocket)
- [External WebSocket upgrade](#external-websocket-upgrade)
- [Intercept and manipulate requests](#intercept-and-manipulate-requests)
Expand Down Expand Up @@ -104,15 +103,6 @@ const apiProxy = createProxyMiddleware('/api', { target: 'http://www.example.org

(full list of [`http-proxy-middleware` configuration options](#options))

#### createProxyMiddleware(uri [, config])

```javascript
// shorthand syntax for the example above:
const apiProxy = createProxyMiddleware('http://www.example.org/api');
```

More about the [shorthand configuration](#shorthand).

## Example

An example with `express` server.
Expand Down Expand Up @@ -148,6 +138,21 @@ app.use('/api', exampleProxy);
app.listen(3000);
```

### app.use(path, proxy)

If you want to use the server's `app.use` `path` parameter to match requests;
Create and mount the proxy without the http-proxy-middleware `context` parameter:

```javascript
app.use('/api', createProxyMiddleware({ target: 'http://www.example.org', changeOrigin: true }));
```

`app.use` documentation:

- express: http://expressjs.com/en/4x/api.html#app.use
- connect: https://github.com/senchalabs/connect#mount-middleware
- polka: https://github.com/lukeed/polka#usebase-fn

## Context matching

Providing an alternative way to decide which requests should be proxied; In case you are not able to use the server's [`path` parameter](http://expressjs.com/en/4x/api.html#app.use) to mount the proxy or when you need more flexibility.
Expand Down Expand Up @@ -422,47 +427,11 @@ The following options are provided by the underlying [http-proxy](https://github
};
```

## Shorthand

Use the shorthand syntax when verbose configuration is not needed. The `context` and `option.target` will be automatically configured when shorthand is used. Options can still be used if needed.

```javascript
createProxyMiddleware('http://www.example.org:8000/api');
// createProxyMiddleware('/api', {target: 'http://www.example.org:8000'});

createProxyMiddleware('http://www.example.org:8000/api/books/*/**.json');
// createProxyMiddleware('/api/books/*/**.json', {target: 'http://www.example.org:8000'});

createProxyMiddleware('http://www.example.org:8000/api', { changeOrigin: true });
// createProxyMiddleware('/api', {target: 'http://www.example.org:8000', changeOrigin: true});
```

### app.use(path, proxy)

If you want to use the server's `app.use` `path` parameter to match requests;
Create and mount the proxy without the http-proxy-middleware `context` parameter:

```javascript
app.use('/api', createProxyMiddleware({ target: 'http://www.example.org', changeOrigin: true }));
```

`app.use` documentation:

- express: http://expressjs.com/en/4x/api.html#app.use
- connect: https://github.com/senchalabs/connect#mount-middleware
- polka: https://github.com/lukeed/polka#usebase-fn

## WebSocket

```javascript
// verbose api
createProxyMiddleware('/', { target: 'http://echo.websocket.org', ws: true });

// shorthand
createProxyMiddleware('http://echo.websocket.org', { ws: true });

// shorter shorthand
createProxyMiddleware('ws://echo.websocket.org');
```

### External WebSocket upgrade
Expand Down
62 changes: 0 additions & 62 deletions recipes/shorthand.md

This file was deleted.

29 changes: 0 additions & 29 deletions src/config-factory.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import isPlainObj = require('is-plain-obj');
import * as url from 'url';
import { ERRORS } from './errors';
import { getInstance } from './logger';
import { Filter, Options } from './types';
Expand All @@ -22,17 +21,6 @@ export function createConfig(context, opts?: Options): Config {

// app.use('/api', proxy('http://localhost:9000'));
// app.use(proxy('http://localhost:9000/api'));
} else if (isStringShortHand(context)) {
const oUrl = url.parse(context);
const target = [oUrl.protocol, '//', oUrl.host].join('');

config.context = oUrl.pathname || '/';
config.options = Object.assign(config.options, { target }, opts);

if (oUrl.protocol === 'ws:' || oUrl.protocol === 'wss:') {
config.options.ws = true;
}
// app.use('/api', proxy({target:'http://localhost:9000'}));
} else {
config.context = context;
config.options = Object.assign(config.options, opts);
Expand All @@ -47,23 +35,6 @@ export function createConfig(context, opts?: Options): Config {
return config;
}

/**
* Checks if a String only target/config is provided.
* This can be just the host or with the optional path.
*
* @example
* app.use('/api', proxy('http://localhost:9000'));
* app.use(proxy('http://localhost:9000/api'));
*
* @param {String} context [description]
* @return {Boolean} [description]
*/
function isStringShortHand(context: Filter) {
if (typeof context === 'string') {
return !!url.parse(context).host;
}
}

/**
* Checks if a Object only config is provided, without a context.
* In this case the all paths will be proxied.
Expand Down
14 changes: 0 additions & 14 deletions test/e2e/http-proxy-middleware.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -389,20 +389,6 @@ describe('E2E http-proxy-middleware', () => {
});
});

describe('shorthand usage', () => {
beforeEach(() => {
agent = request(
createApp(createProxyMiddleware(`http://localhost:${mockTargetServer.port}/api`))
);
});

it('should have proxy with shorthand configuration', async () => {
await mockTargetServer.get('/api/foo/bar').thenReply(200, 'HELLO /api/foo/bar');
const response = await agent.get(`/api/foo/bar`).expect(200);
expect(response.text).toBe('HELLO /api/foo/bar');
});
});

describe('express with path + proxy', () => {
beforeEach(() => {
agent = request(
Expand Down
26 changes: 0 additions & 26 deletions test/e2e/websocket.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,32 +95,6 @@ describe('E2E WebSocket proxy', () => {
});
});

describe('option.ws with external server "upgrade" and shorthand usage', () => {
beforeEach(() => {
proxyServer = createApp(
createProxyMiddleware(`ws://localhost:${WS_SERVER_PORT}`, {
pathRewrite: { '^/socket': '' },
})
).listen(SERVER_PORT);

proxyServer.on('upgrade', proxyMiddleware.upgrade);
});

beforeEach((done) => {
ws = new WebSocket(`ws://localhost:${SERVER_PORT}/socket`);
ws.on('open', done);
});

it('should proxy to path', (done) => {
ws.on('message', (data, isBinary) => {
const message = isBinary ? data : data.toString();
expect(message).toBe('foobar');
done();
});
ws.send('foobar');
});
});

describe('with router and pathRewrite', () => {
beforeEach(() => {
// override
Expand Down
103 changes: 1 addition & 102 deletions test/unit/config-factory.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,92 +26,7 @@ describe('configFactory', () => {
});
});

describe('shorthand String', () => {
describe('shorthand String config', () => {
beforeEach(() => {
result = createConfig('http://www.example.org:8000/api');
});

it('should return config object', () => {
expect(Object.keys(result)).toEqual(['context', 'options']);
});

it('should return config object with context', () => {
expect(result.context).toBe('/api');
});

it('should return config object with options', () => {
expect(result.options).toEqual({
target: 'http://www.example.org:8000',
});
});
});

describe('shorthand String config for whole domain', () => {
beforeEach(() => {
result = createConfig('http://www.example.org:8000');
});

it('should return config object with context', () => {
expect(result.context).toBe('/');
});
});

describe('shorthand String config for websocket url', () => {
beforeEach(() => {
result = createConfig('ws://www.example.org:8000');
});

it('should return config object with context', () => {
expect(result.context).toBe('/');
});

it('should return options with ws = true', () => {
expect(result.options.ws).toBe(true);
});
});

describe('shorthand String config for secure websocket url', () => {
beforeEach(() => {
result = createConfig('wss://www.example.org:8000');
});

it('should return config object with context', () => {
expect(result.context).toBe('/');
});

it('should return options with ws = true', () => {
expect(result.options.ws).toBe(true);
});
});

describe('shorthand String config with globbing', () => {
beforeEach(() => {
result = createConfig('http://www.example.org:8000/api/*.json');
});

it('should return config object with context', () => {
expect(result.context).toBe('/api/*.json');
});
});

describe('shorthand String config with options', () => {
beforeEach(() => {
result = createConfig('http://www.example.org:8000/api', {
changeOrigin: true,
});
});

it('should return config object with additional options', () => {
expect(result.options).toEqual({
changeOrigin: true,
target: 'http://www.example.org:8000',
});
});
});
});

describe('shorthand Object config', () => {
describe('Object config', () => {
beforeEach(() => {
result = createConfig({ target: 'http://www.example.org:8000' });
});
Expand Down Expand Up @@ -156,21 +71,5 @@ describe('configFactory', () => {
expect(fn).not.toThrowError(Error);
});
});

describe('faulty config. mixing classic with shorthand', () => {
beforeEach(() => {
result = createConfig('http://localhost:3000/api', {
target: 'http://localhost:8000',
});
});

it('should use the target in the configuration as target', () => {
expect(result.options.target).toBe('http://localhost:8000');
});

it('should not use the host from the shorthand as target', () => {
expect(result.options.target).not.toBe('http://localhost:3000');
});
});
});
});