Skip to content

Commit ba32508

Browse files
committed
feat: add cors middleware
1 parent 7fdf9c7 commit ba32508

File tree

8 files changed

+228
-4
lines changed

8 files changed

+228
-4
lines changed

README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@ npm i @qiwi/mware
88
```
99

1010
### Middlewares
11-
* [mware-mdc](../mware-mdc/README.md)
12-
* [mware-logger](../mware-logger/README.md)
13-
* [mware-crumbs](../mware-crumbs/README.md)
11+
* [mware-mdc](./packages/mware-mdc/README.md)
12+
* [mware-logger](./packages/mware-logger/README.md)
13+
* [mware-crumbs](./packages/mware-crumbs/README.md)
14+
* [mware-cors](./packages/mware-cors/README.md)
1415

1516
### Usage
1617
```javascript

packages/mware-cors/.babelrc

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
{
2+
"comments": false,
3+
"ignore": [
4+
"interface.js"
5+
],
6+
"presets": [
7+
"@babel/preset-flow"
8+
],
9+
"env": {
10+
"production": {
11+
"presets": [
12+
"@babel/preset-flow",
13+
["@babel/preset-env", {
14+
"modules": false
15+
}]
16+
],
17+
"plugins": [
18+
"@babel/plugin-transform-modules-commonjs",
19+
"@babel/plugin-proposal-class-properties",
20+
"@babel/plugin-proposal-object-rest-spread"
21+
]
22+
},
23+
"test": {
24+
"presets": [
25+
"@babel/preset-flow",
26+
"@babel/preset-env"
27+
],
28+
"plugins": [
29+
"@babel/plugin-transform-modules-commonjs",
30+
"@babel/plugin-proposal-class-properties",
31+
"@babel/plugin-proposal-object-rest-spread"
32+
]
33+
}
34+
}
35+
}

packages/mware-cors/README.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# @qiwi/mware-cors
2+
CORS middleware
3+
4+
### Install
5+
```bash
6+
yarn add @qiwi/mware-cors
7+
npm i @qiwi/mware-cors
8+
```
9+
10+
### Usage
11+
12+
```javascript
13+
import cors from '@qiwi/mware-cors'
14+
import express from 'express'
15+
16+
const app = express()
17+
app.use(cors())
18+
19+
app.get('/foo/bar', (req, res) => {
20+
res.send('foo')
21+
})
22+
23+
/*
24+
RES {
25+
headers: {
26+
'Access-Control-Allow-Origin': '*',
27+
'Access-Control-Allow-Methods': 'GET, HEAD, PATCH, PUT, POST, DELETE, OPTIONS'
28+
...
29+
},
30+
...
31+
}
32+
*/
33+
34+
app.listen(...)
35+
```

packages/mware-cors/package.json

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
{
2+
"name": "@qiwi/mware-cors",
3+
"version": "1.1.0",
4+
"private": false,
5+
"description": "CORS middleware",
6+
"main": "dist/es5/index.js",
7+
"files": [
8+
"README.md",
9+
"CHANGELOG.md",
10+
"dist/"
11+
],
12+
"scripts": {
13+
"build_es6": "flow-remove-types src/ --out-dir dist/es6/",
14+
"build_es5": "BABEL_ENV=production babel src --out-dir dist/es5/",
15+
"build": "rm -rf dist && npm run build_es6 && npm run build_es5"
16+
},
17+
"repository": {
18+
"type": "git",
19+
"url": "https://github.com/qiwi/mware.git"
20+
},
21+
"keywords": [
22+
"common middlewares"
23+
],
24+
"author": "Anton Golub <a.golub@qiwi.com>",
25+
"license": "MIT",
26+
"bugs": {
27+
"url": "https://github.com/qiwi/mware/issues"
28+
},
29+
"homepage": "https://github.com/qiwi/mware#readme",
30+
"dependencies": {},
31+
"devDependencies": {
32+
"lodash": "^4.17.11",
33+
"reqresnext": "^1.5.1"
34+
}
35+
}

packages/mware-cors/src/index.js

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// @flow
2+
3+
import type {
4+
IAny,
5+
IMiddlewareFactory,
6+
IRegularMiddleware,
7+
IRequest,
8+
IResponse,
9+
INext,
10+
ILogger
11+
} from '../../mware-core/src/interface'
12+
13+
export const ALLOW_ORIGIN = 'Access-Control-Allow-Origin'
14+
export const ALLOW_HEADERS = 'Access-Control-Allow-Headers'
15+
export const EXPOSE_HEADERS = 'Access-Control-Expose-Headers'
16+
export const ALLOW_METHODS = 'Access-Control-Allow-Methods'
17+
export const ALLOW_CREDENTIALS = 'Access-Control-Allow-Credentials'
18+
19+
export const DEFAULT_HEADERS = {
20+
[ALLOW_ORIGIN]: '*',
21+
[ALLOW_HEADERS]: 'set-cookie, Authorization, Origin, X-Requested-With, Content-Type, Accept, Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers',
22+
[EXPOSE_HEADERS]: 'Cookie, Set-Cookie, Location',
23+
[ALLOW_METHODS]: 'GET, HEAD, PATCH, PUT, POST, DELETE, OPTIONS',
24+
[ALLOW_CREDENTIALS]: 'true'
25+
}
26+
27+
export const formatOriginHeader = (policy: IAny, origin: IAny): string => {
28+
switch (policy) {
29+
case 'echo':
30+
return origin
31+
32+
case undefined:
33+
case null:
34+
return '*'
35+
36+
default:
37+
return '' + policy
38+
}
39+
}
40+
export type headers = typeof ALLOW_ORIGIN | typeof ALLOW_HEADERS | typeof EXPOSE_HEADERS | typeof ALLOW_METHODS | typeof ALLOW_CREDENTIALS
41+
export type IOpts = {
42+
logger?: ILogger,
43+
[headers]: ?string
44+
}
45+
46+
export default ((opts: ?IOpts) => {
47+
return ((req: IRequest, res: IResponse, next: INext) => {
48+
const allowOrigin = formatOriginHeader(opts && opts[ALLOW_ORIGIN], req.get('origin'))
49+
const corsHeaders = {
50+
...DEFAULT_HEADERS,
51+
...opts,
52+
[ALLOW_ORIGIN]: allowOrigin
53+
}
54+
55+
res.header(corsHeaders)
56+
57+
next()
58+
}: IRegularMiddleware)
59+
}: IMiddlewareFactory)

packages/mware-cors/test/index.js

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import factory, {ALLOW_ORIGIN, ALLOW_METHODS } from '../src'
2+
import reqresnext from 'reqresnext'
3+
4+
describe('mware-crumbs', () => {
5+
6+
beforeEach(() => {
7+
jest.resetAllMocks()
8+
})
9+
10+
it('factory returns a middleware', () => {
11+
expect(factory()).toEqual(expect.any(Function))
12+
})
13+
14+
describe('sets CORS headers', () => {
15+
it('default', () => {
16+
const mware = factory({})
17+
const { req, res, next } = reqresnext(null, null, jest.fn())
18+
19+
mware(req, res, next)
20+
21+
expect(next).toHaveBeenCalled()
22+
expect(res.get(ALLOW_ORIGIN)).toBe('*')
23+
})
24+
25+
it('optional methods', () => {
26+
const mware = factory({
27+
[ALLOW_ORIGIN]: 'example.com',
28+
[ALLOW_METHODS]: 'GET, PUT'
29+
})
30+
const { req, res, next } = reqresnext(null, null, jest.fn())
31+
32+
mware(req, res, next)
33+
34+
expect(next).toHaveBeenCalled()
35+
expect(res.get(ALLOW_ORIGIN)).toBe('example.com')
36+
expect(res.get(ALLOW_METHODS)).toBe('GET, PUT')
37+
})
38+
39+
it('origin echo', () => {
40+
const mware = factory({ [ALLOW_ORIGIN]: 'echo' })
41+
const { req, res, next } = reqresnext({
42+
headers: {
43+
origin: 'www.example.com'
44+
}
45+
}, null, jest.fn())
46+
47+
mware(req, res, next)
48+
49+
expect(next).toHaveBeenCalled()
50+
expect(res.get(ALLOW_ORIGIN)).toBe('www.example.com')
51+
})
52+
})
53+
})

packages/mware/src/index.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
import mdc from '@qiwi/mware-mdc'
22
import logger from '@qiwi/mware-logger'
3+
import crumbs from '@qiwi/mware-crumbs'
4+
import cors from '@qiwi/mware-cors'
35
import { util } from '@qiwi/mware-core'
46

57
export {
68
mdc,
79
logger,
10+
cors,
11+
crumbs,
812
util
913
}
1014

packages/mware/test/index.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1-
import {mdc, logger, util} from '../src'
1+
import {mdc, logger, util, cors, crumbs} from '../src'
22

33
describe('mware', () => {
44
it('exposes middlewares collection', () => {
55
expect(mdc).toEqual(expect.any(Function))
66
expect(logger).toEqual(expect.any(Function))
7+
expect(cors).toEqual(expect.any(Function))
8+
expect(crumbs).toEqual(expect.any(Function))
79
expect(util).not.toBeUndefined()
810
})
911
})

0 commit comments

Comments
 (0)