From fd1d01ec1b4676da2a2b4a65a3218254b2446279 Mon Sep 17 00:00:00 2001 From: Adam Pash Date: Wed, 10 Aug 2016 15:03:28 -0400 Subject: [PATCH] Feat: Added CORS to config (#302) --- .../config/environments/development.js | 21 ++++++++++ src/packages/application/initialize.js | 6 ++- src/packages/config/index.js | 5 +++ src/packages/config/interfaces.js | 2 + src/packages/server/index.js | 39 +++++++++++++------ src/packages/server/interfaces.js | 13 ++++++- src/packages/server/utils/set-cors-headers.js | 26 +++++++++++++ 7 files changed, 97 insertions(+), 15 deletions(-) create mode 100644 src/packages/server/utils/set-cors-headers.js diff --git a/examples/social-network/config/environments/development.js b/examples/social-network/config/environments/development.js index 156ce484..6dd3d0d0 100644 --- a/examples/social-network/config/environments/development.js +++ b/examples/social-network/config/environments/development.js @@ -1,4 +1,25 @@ export default { + server: { + cors: { + origin: '*', + enabled: true, + + headers: [ + 'Accept', + 'Content-Type' + ], + + methods: [ + 'GET', + 'POST', + 'PATCH', + 'DELETE', + 'HEAD', + 'OPTIONS' + ] + } + }, + logging: { level: 'DEBUG', format: 'text', diff --git a/src/packages/application/initialize.js b/src/packages/application/initialize.js index 1132ba84..ce892a46 100644 --- a/src/packages/application/initialize.js +++ b/src/packages/application/initialize.js @@ -20,7 +20,8 @@ export default async function initialize(app: T, { path, port, logging, - database + database, + server: serverConfig }: Application$opts) { const routes = loader(path, 'routes'); const models = loader(path, 'models'); @@ -103,7 +104,8 @@ export default async function initialize(app: T, { const server = new Server({ router, - logger + logger, + ...serverConfig }); if (!LUX_CONSOLE) { diff --git a/src/packages/config/index.js b/src/packages/config/index.js index fd2f6bad..f40b77a6 100644 --- a/src/packages/config/index.js +++ b/src/packages/config/index.js @@ -8,6 +8,11 @@ export function createDefaultConfig(): Config { const isProdENV = NODE_ENV === 'production'; return { + server: { + cors: { + enabled: false + } + }, logging: { level: isProdENV ? 'INFO' : 'DEBUG', format: isProdENV ? 'json' : 'text', diff --git a/src/packages/config/interfaces.js b/src/packages/config/interfaces.js index c3ade83d..1133bd1d 100644 --- a/src/packages/config/interfaces.js +++ b/src/packages/config/interfaces.js @@ -1,6 +1,8 @@ // @flow import type { Logger$config } from '../logger'; +import type { Server$config } from '../server'; export type Config = { logging: Logger$config; + server: Server$config; }; diff --git a/src/packages/server/index.js b/src/packages/server/index.js index 28a5c228..be3bf7a9 100644 --- a/src/packages/server/index.js +++ b/src/packages/server/index.js @@ -10,13 +10,14 @@ import { createResponder } from './responder'; import { tryCatchSync } from '../../utils/try-catch'; import validateAccept from './utils/validate-accept'; import validateContentType from './utils/validate-content-type'; +import setCORSHeaders from './utils/set-cors-headers'; import type { Writable } from 'stream'; import type { IncomingMessage, Server as HTTPServer } from 'http'; import type { Request } from './request/interfaces'; import type { Response } from './response/interfaces'; -import type { Server$opts } from './interfaces'; +import type { Server$opts, Server$config } from './interfaces'; /** * @private @@ -26,9 +27,11 @@ class Server { router: Server$opts.router; + cors: Server$config.cors; + instance: HTTPServer; - constructor({ logger, router }: Server$opts) { + constructor({ logger, router, cors }: Server$opts) { Object.defineProperties(this, { router: { value: router, @@ -44,6 +47,13 @@ class Server { configurable: false }, + cors: { + value: cors, + writable: false, + enumerable: false, + configurable: false + }, + instance: { value: createServer(this.receiveRequest), writable: false, @@ -58,19 +68,22 @@ class Server { } initializeRequest(req: IncomingMessage, res: Writable): [Request, Response] { - const { logger, router } = this; + const { logger, router, cors } = this; req.setEncoding('utf8'); - return [ - createRequest(req, { - logger, - router - }), - createResponse(res, { - logger - }) - ]; + const response = createResponse(res, { + logger + }); + + setCORSHeaders(response, cors); + + const request = createRequest(req, { + logger, + router + }); + + return [request, response]; } validateRequest({ method, headers }: Request): true { @@ -122,6 +135,8 @@ export default Server; export { getDomain } from './request'; export { default as createServerError } from './utils/create-server-error'; +export type { Server$config } from './interfaces'; + export type { Request, Request$params, diff --git a/src/packages/server/interfaces.js b/src/packages/server/interfaces.js index cf825ec3..f4afc2af 100644 --- a/src/packages/server/interfaces.js +++ b/src/packages/server/interfaces.js @@ -2,7 +2,18 @@ import type Logger from '../logger'; import type Router from '../router'; -export type Server$opts = { +export type Server$cors = { + enabled: boolean; + origin?: string; + headers?: Array; + methods?: Array; +}; + +export type Server$config = { + cors: Server$cors; +}; + +export type Server$opts = Server$config & { logger: Logger; router: Router; }; diff --git a/src/packages/server/utils/set-cors-headers.js b/src/packages/server/utils/set-cors-headers.js new file mode 100644 index 00000000..120880aa --- /dev/null +++ b/src/packages/server/utils/set-cors-headers.js @@ -0,0 +1,26 @@ +// @flow +import type { Response } from '../index'; +import type { Server$cors } from '../interfaces'; + +export default function setCORSHeaders(res: Response, { + origin, + methods, + headers, + enabled +}: Server$cors) { + if (!enabled) { + return; + } + + if (origin) { + res.setHeader('Access-Control-Allow-Origin', origin); + } + + if (methods) { + res.setHeader('Access-Control-Allow-Methods', methods.join()); + } + + if (headers) { + res.setHeader('Access-Control-Allow-Headers', headers.join()); + } +}