-
-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
8b23926
commit 703f45a
Showing
7 changed files
with
185 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,8 +23,8 @@ __test__ | |
# production | ||
dist | ||
es | ||
lib | ||
logs | ||
|
||
# misc | ||
# add other ignore file below | ||
lib |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -35,7 +35,6 @@ __snapshots__ | |
# production | ||
dist | ||
es | ||
lib | ||
logs | ||
|
||
# umi | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
/** | ||
* Multi purpose CORS lib. | ||
* Note: Based on the `cors` package in npm but using only | ||
* web APIs. Feel free to use it in your own projects. | ||
*/ | ||
|
||
type StaticOrigin = boolean | string | RegExp | (boolean | string | RegExp)[]; | ||
|
||
type OriginFn = (origin: string | undefined, req: Request) => StaticOrigin | Promise<StaticOrigin>; | ||
|
||
interface CorsOptions { | ||
origin?: StaticOrigin | OriginFn; | ||
methods?: string | string[]; | ||
allowedHeaders?: string | string[]; | ||
exposedHeaders?: string | string[]; | ||
credentials?: boolean; | ||
maxAge?: number; | ||
preflightContinue?: boolean; | ||
optionsSuccessStatus?: number; | ||
} | ||
|
||
const defaultOptions: CorsOptions = { | ||
origin: '*', | ||
methods: 'GET,HEAD,PUT,PATCH,POST,DELETE', | ||
preflightContinue: false, | ||
optionsSuccessStatus: 204, | ||
}; | ||
|
||
function isOriginAllowed(origin: string, allowed: StaticOrigin): boolean { | ||
return Array.isArray(allowed) | ||
? allowed.some((o) => isOriginAllowed(origin, o)) | ||
: typeof allowed === 'string' | ||
? origin === allowed | ||
: allowed instanceof RegExp | ||
? allowed.test(origin) | ||
: !!allowed; | ||
} | ||
|
||
function getOriginHeaders(reqOrigin: string | undefined, origin: StaticOrigin) { | ||
const headers = new Headers(); | ||
|
||
if (origin === '*') { | ||
// Allow any origin | ||
headers.set('Access-Control-Allow-Origin', '*'); | ||
} else if (typeof origin === 'string') { | ||
// Fixed origin | ||
headers.set('Access-Control-Allow-Origin', origin); | ||
headers.append('Vary', 'Origin'); | ||
} else { | ||
const allowed = isOriginAllowed(reqOrigin ?? '', origin); | ||
|
||
if (allowed && reqOrigin) { | ||
headers.set('Access-Control-Allow-Origin', reqOrigin); | ||
} | ||
headers.append('Vary', 'Origin'); | ||
} | ||
|
||
return headers; | ||
} | ||
|
||
// originHeadersFromReq | ||
|
||
async function originHeadersFromReq(req: Request, origin: StaticOrigin | OriginFn) { | ||
const reqOrigin = req.headers.get('Origin') || undefined; | ||
const value = typeof origin === 'function' ? await origin(reqOrigin, req) : origin; | ||
|
||
if (!value) return; | ||
return getOriginHeaders(reqOrigin, value); | ||
} | ||
|
||
function getAllowedHeaders(req: Request, allowed?: string | string[]) { | ||
const headers = new Headers(); | ||
|
||
if (!allowed) { | ||
allowed = req.headers.get('Access-Control-Request-Headers')!; | ||
headers.append('Vary', 'Access-Control-Request-Headers'); | ||
} else if (Array.isArray(allowed)) { | ||
// If the allowed headers is an array, turn it into a string | ||
allowed = allowed.join(','); | ||
} | ||
if (allowed) { | ||
headers.set('Access-Control-Allow-Headers', allowed); | ||
} | ||
|
||
return headers; | ||
} | ||
|
||
export default async function cors(req: Request, res: Response, options?: CorsOptions) { | ||
const opts = { ...defaultOptions, ...options }; | ||
const { headers } = res; | ||
const originHeaders = await originHeadersFromReq(req, opts.origin ?? false); | ||
const mergeHeaders = (v: string, k: string) => { | ||
if (k === 'Vary') headers.append(k, v); | ||
else headers.set(k, v); | ||
}; | ||
|
||
// If there's no origin we won't touch the response | ||
if (!originHeaders) return res; | ||
|
||
originHeaders.forEach(mergeHeaders); | ||
|
||
if (opts.credentials) { | ||
headers.set('Access-Control-Allow-Credentials', 'true'); | ||
} | ||
|
||
const exposed = Array.isArray(opts.exposedHeaders) | ||
? opts.exposedHeaders.join(',') | ||
: opts.exposedHeaders; | ||
|
||
if (exposed) { | ||
headers.set('Access-Control-Expose-Headers', exposed); | ||
} | ||
|
||
// Handle the preflight request | ||
if (req.method === 'OPTIONS') { | ||
if (opts.methods) { | ||
const methods = Array.isArray(opts.methods) ? opts.methods.join(',') : opts.methods; | ||
|
||
headers.set('Access-Control-Allow-Methods', methods); | ||
} | ||
|
||
getAllowedHeaders(req, opts.allowedHeaders).forEach(mergeHeaders); | ||
|
||
if (typeof opts.maxAge === 'number') { | ||
headers.set('Access-Control-Max-Age', String(opts.maxAge)); | ||
} | ||
|
||
if (opts.preflightContinue) return res; | ||
|
||
headers.set('Content-Length', '0'); | ||
return new Response(null, { status: opts.optionsSuccessStatus, headers }); | ||
} | ||
|
||
// If we got here, it's a normal request | ||
return res; | ||
} | ||
|
||
export function initCors(options?: CorsOptions) { | ||
return (req: Request, res: Response) => cors(req, res, options); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,8 +10,6 @@ export default () => { | |
{ | ||
avatarSize: 64, | ||
id: 'lobehub', | ||
padding: 0, | ||
width: 800, | ||
}, | ||
{ store }, | ||
); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters