@@ -2,7 +2,7 @@ import { IncomingMessage as Request, ServerResponse as Response } from 'http'
2
2
import { vary } from 'es-vary'
3
3
4
4
export interface AccessControlOptions {
5
- origin ?: string | boolean | ( ( req : Request , res : Response ) => string ) | Array < string > | RegExp
5
+ origin ?: string | boolean | ( ( req : Request , res : Response ) => string ) | Iterable < string > | RegExp
6
6
methods ?: string [ ]
7
7
allowedHeaders ?: string [ ]
8
8
exposedHeaders ?: string [ ]
@@ -12,6 +12,68 @@ export interface AccessControlOptions {
12
12
preflightContinue ?: boolean
13
13
}
14
14
15
+ const isIterable = ( obj : unknown ) : obj is Iterable < unknown > => typeof obj [ Symbol . iterator ] === 'function'
16
+
17
+ const failOriginParam = ( ) => {
18
+ throw new TypeError ( 'No other objects allowed. Allowed types is array of strings or RegExp' )
19
+ }
20
+
21
+ const getOriginHeaderHandler = ( origin : unknown ) : ( ( req : Request , res : Response ) => void ) => {
22
+ if ( typeof origin === 'boolean' ) {
23
+ return origin
24
+ ? ( _ , res ) => {
25
+ res . setHeader ( 'Access-Control-Allow-Origin' , '*' )
26
+ }
27
+ : ( ) => undefined
28
+ }
29
+
30
+ if ( typeof origin === 'string' ) {
31
+ return ( _ , res ) => {
32
+ res . setHeader ( 'Access-Control-Allow-Origin' , origin )
33
+ }
34
+ }
35
+
36
+ if ( typeof origin === 'function' ) {
37
+ return ( req , res ) => {
38
+ vary ( res , 'Origin' )
39
+ res . setHeader ( 'Access-Control-Allow-Origin' , origin ( req , res ) )
40
+ }
41
+ }
42
+
43
+ if ( typeof origin !== 'object' ) failOriginParam ( )
44
+
45
+ if ( isIterable ( origin ) ) {
46
+ const originArray = Array . from ( origin )
47
+ if ( originArray . some ( ( element ) => typeof element !== 'string' ) ) failOriginParam ( )
48
+
49
+ const originSet = new Set ( origin )
50
+
51
+ if ( originSet . has ( '*' ) ) {
52
+ return ( _ , res ) => {
53
+ res . setHeader ( 'Access-Control-Allow-Origin' , '*' )
54
+ }
55
+ }
56
+
57
+ return ( req , res ) => {
58
+ vary ( res , 'Origin' )
59
+ if ( req . headers . origin === undefined ) return
60
+ if ( ! originSet . has ( req . headers . origin ) ) return
61
+ res . setHeader ( 'Access-Control-Allow-Origin' , req . headers . origin )
62
+ }
63
+ }
64
+
65
+ if ( origin instanceof RegExp ) {
66
+ return ( req , res ) => {
67
+ vary ( res , 'Origin' )
68
+ if ( req . headers . origin === undefined ) return
69
+ if ( ! origin . test ( req . headers . origin ) ) return
70
+ res . setHeader ( 'Access-Control-Allow-Origin' , req . headers . origin )
71
+ }
72
+ }
73
+
74
+ failOriginParam ( )
75
+ }
76
+
15
77
/**
16
78
* CORS Middleware
17
79
*/
@@ -26,24 +88,10 @@ export const cors = (opts: AccessControlOptions = {}) => {
26
88
optionsSuccessStatus = 204 ,
27
89
preflightContinue = false
28
90
} = opts
91
+ const originHeaderHandler = getOriginHeaderHandler ( origin )
92
+
29
93
return ( req : Request , res : Response , next ?: ( ) => void ) => {
30
- // Checking the type of the origin property
31
- if ( typeof origin === 'boolean' && origin === true ) {
32
- res . setHeader ( 'Access-Control-Allow-Origin' , '*' )
33
- } else if ( typeof origin === 'string' ) {
34
- res . setHeader ( 'Access-Control-Allow-Origin' , origin )
35
- } else if ( typeof origin === 'function' ) {
36
- res . setHeader ( 'Access-Control-Allow-Origin' , origin ( req , res ) )
37
- } else if ( typeof origin === 'object' ) {
38
- if ( Array . isArray ( origin ) && ( origin . indexOf ( req . headers . origin ) !== - 1 || origin . indexOf ( '*' ) !== - 1 ) ) {
39
- res . setHeader ( 'Access-Control-Allow-Origin' , req . headers . origin )
40
- } else if ( origin instanceof RegExp && origin . test ( req . headers . origin ) ) {
41
- res . setHeader ( 'Access-Control-Allow-Origin' , req . headers . origin )
42
- } else {
43
- throw new TypeError ( 'No other objects allowed. Allowed types is array of strings or RegExp' )
44
- }
45
- }
46
- if ( ( typeof origin === 'string' && origin !== '*' ) || typeof origin === 'function' ) vary ( res , 'Origin' )
94
+ originHeaderHandler ( req , res )
47
95
48
96
// Setting the Access-Control-Allow-Methods header from the methods array
49
97
res . setHeader ( 'Access-Control-Allow-Methods' , methods . join ( ', ' ) . toUpperCase ( ) )
0 commit comments