From 26c3df0862ec407408807ec24f3487e93d0d6f2a Mon Sep 17 00:00:00 2001 From: Amir Najafi Date: Fri, 13 May 2022 22:17:29 +0430 Subject: [PATCH 1/5] fea(micro-server): add core helpers --- packages/core/micro-server/src/micro-server.ts | 11 +++++++++-- .../src/middleware/core-helpers.ts | 17 +++++++++++++++++ packages/core/micro-server/src/type.ts | 10 ++++++++++ .../starter/microservice/src/route/home.ts | 18 ++++++++++-------- 4 files changed, 46 insertions(+), 10 deletions(-) create mode 100644 packages/core/micro-server/src/middleware/core-helpers.ts diff --git a/packages/core/micro-server/src/micro-server.ts b/packages/core/micro-server/src/micro-server.ts index 15f8db323..ed2e34426 100644 --- a/packages/core/micro-server/src/micro-server.ts +++ b/packages/core/micro-server/src/micro-server.ts @@ -2,7 +2,9 @@ import {createServer} from 'http'; import {alwatrRegisteredList, createLogger} from '@alwatr/logger'; -import type {Methods, ReplyContent} from './type.js'; +import {coreHelper} from './middleware/core-helpers.js'; + +import type {Methods, ReplyContent, ServerOptions as ResponseOptions} from './type.js'; import type {IncomingMessage, ServerResponse} from 'http'; alwatrRegisteredList.push({ @@ -182,7 +184,7 @@ export class AlwatrConnection { } } - reply(content: ReplyContent): void { + reply(content: ReplyContent, options?: ResponseOptions): void { this.logger.logMethodArgs('reply', {content}); if (this.serverResponse.headersSent) { @@ -210,6 +212,11 @@ export class AlwatrConnection { ); } + // set core helper header + if (options?.coreHelper !== undefined) { + coreHelper(this.serverResponse, options?.coreHelper); + } + this.serverResponse.writeHead(content.statusCode, { 'Content-Length': body.length, 'Content-Type': 'application/json', diff --git a/packages/core/micro-server/src/middleware/core-helpers.ts b/packages/core/micro-server/src/middleware/core-helpers.ts new file mode 100644 index 000000000..88c0d5320 --- /dev/null +++ b/packages/core/micro-server/src/middleware/core-helpers.ts @@ -0,0 +1,17 @@ +import {CoreHelperHeader} from '../type'; + +import type {ServerResponse} from 'http'; + +export function coreHelper(response: ServerResponse, header: CoreHelperHeader): void { + if (header.allowOrigin !== undefined) { + response.setHeader('Access-Control-Allow-Origin', header.allowOrigin); + } + + if (header.allowMethod !== undefined) { + response.setHeader('Access-Control-Allow-Method', header.allowMethod); + } + + if (header.maxAge !== undefined) { + response.setHeader('Access-Control-Max-Age', header.maxAge); + } +} diff --git a/packages/core/micro-server/src/type.ts b/packages/core/micro-server/src/type.ts index 683a87054..acb6acb9c 100644 --- a/packages/core/micro-server/src/type.ts +++ b/packages/core/micro-server/src/type.ts @@ -11,6 +11,16 @@ interface ReplySuccessContent { data: Record; } +export interface ServerOptions { + coreHelper?: CoreHelperHeader; +} + +export interface CoreHelperHeader { + allowOrigin?: string; + allowMethod?: string; + maxAge?: number; +} + export type ReplyContent = ReplyFailedContent | ReplySuccessContent; export type Methods = ('all' | 'get' | 'post' | 'put' | 'delete' | 'patch' | 'options') & string; diff --git a/packages/starter/microservice/src/route/home.ts b/packages/starter/microservice/src/route/home.ts index 402a2ebbf..d1a275096 100644 --- a/packages/starter/microservice/src/route/home.ts +++ b/packages/starter/microservice/src/route/home.ts @@ -1,12 +1,14 @@ import {app} from '../app.js'; app.route('all', '/', async (connection) => { - connection.reply({ - ok: true, - statusCode: 200, - data: { - app: 'Alwatr Microservice Starter Kit', - message: 'Hello ;)', - }, - }); + connection.reply( + { + ok: true, + statusCode: 200, + data: { + app: 'Alwatr Microservice Starter Kit', + message: 'Hello ;)', + }, + }, + ); }); From fc6253e9b5f7e097195cf2fff819c0c773531901 Mon Sep 17 00:00:00 2001 From: Amir Najafi Date: Fri, 13 May 2022 22:53:02 +0430 Subject: [PATCH 2/5] chore(micro-server): add cors helper documentation --- packages/core/micro-server/README.md | 28 +++++++++++++++++++ .../core/micro-server/src/micro-server.ts | 10 +++---- .../{core-helpers.ts => cors-helpers.ts} | 4 +-- packages/core/micro-server/src/type.ts | 6 ++-- packages/starter/microservice/src/index.ts | 1 + .../starter/microservice/src/route/cors.ts | 21 ++++++++++++++ .../starter/microservice/src/route/home.ts | 18 ++++++------ 7 files changed, 68 insertions(+), 20 deletions(-) rename packages/core/micro-server/src/middleware/{core-helpers.ts => cors-helpers.ts} (75%) create mode 100644 packages/starter/microservice/src/route/cors.ts diff --git a/packages/core/micro-server/README.md b/packages/core/micro-server/README.md index 9aa2bdd36..21ef2ee9c 100644 --- a/packages/core/micro-server/README.md +++ b/packages/core/micro-server/README.md @@ -1,3 +1,31 @@ # @alwatr/micro-server Elegant powerful nodejs server for microservice use cases, written in tiny TypeScript module. + +## Usage + +### Middleware + +#### [Core Helper](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) + +```typescript +app.route('all', '/', async (connection) => { + connection.reply( + { + ok: true, + statusCode: 200, + data: { + app: 'Alwatr Microservice', + message: 'Hello World', + }, + }, + { + coreHelper: { + allowOrigin: 'https://developer.mozilla.org', // That should not end with "/" + allowMethod: '*', + maxAge: 5 * 60, // 5 Minute + }, + } + ); +}); +``` diff --git a/packages/core/micro-server/src/micro-server.ts b/packages/core/micro-server/src/micro-server.ts index ed2e34426..23f32e7ee 100644 --- a/packages/core/micro-server/src/micro-server.ts +++ b/packages/core/micro-server/src/micro-server.ts @@ -2,9 +2,9 @@ import {createServer} from 'http'; import {alwatrRegisteredList, createLogger} from '@alwatr/logger'; -import {coreHelper} from './middleware/core-helpers.js'; +import {corsHelper} from './middleware/cors-helpers.js'; -import type {Methods, ReplyContent, ServerOptions as ResponseOptions} from './type.js'; +import type {Methods, ReplyContent, ResponseOptions} from './type.js'; import type {IncomingMessage, ServerResponse} from 'http'; alwatrRegisteredList.push({ @@ -212,9 +212,9 @@ export class AlwatrConnection { ); } - // set core helper header - if (options?.coreHelper !== undefined) { - coreHelper(this.serverResponse, options?.coreHelper); + // set cors helper header + if (options?.corsHelper !== undefined) { + corsHelper(this.serverResponse, options?.corsHelper); } this.serverResponse.writeHead(content.statusCode, { diff --git a/packages/core/micro-server/src/middleware/core-helpers.ts b/packages/core/micro-server/src/middleware/cors-helpers.ts similarity index 75% rename from packages/core/micro-server/src/middleware/core-helpers.ts rename to packages/core/micro-server/src/middleware/cors-helpers.ts index 88c0d5320..7debf999f 100644 --- a/packages/core/micro-server/src/middleware/core-helpers.ts +++ b/packages/core/micro-server/src/middleware/cors-helpers.ts @@ -1,8 +1,8 @@ -import {CoreHelperHeader} from '../type'; +import {CorsHelperHeader} from '../type'; import type {ServerResponse} from 'http'; -export function coreHelper(response: ServerResponse, header: CoreHelperHeader): void { +export function corsHelper(response: ServerResponse, header: CorsHelperHeader): void { if (header.allowOrigin !== undefined) { response.setHeader('Access-Control-Allow-Origin', header.allowOrigin); } diff --git a/packages/core/micro-server/src/type.ts b/packages/core/micro-server/src/type.ts index acb6acb9c..cf5b704ad 100644 --- a/packages/core/micro-server/src/type.ts +++ b/packages/core/micro-server/src/type.ts @@ -11,11 +11,11 @@ interface ReplySuccessContent { data: Record; } -export interface ServerOptions { - coreHelper?: CoreHelperHeader; +export interface ResponseOptions { + corsHelper?: CorsHelperHeader; } -export interface CoreHelperHeader { +export interface CorsHelperHeader { allowOrigin?: string; allowMethod?: string; maxAge?: number; diff --git a/packages/starter/microservice/src/index.ts b/packages/starter/microservice/src/index.ts index 8df466824..4d9cd1b46 100644 --- a/packages/starter/microservice/src/index.ts +++ b/packages/starter/microservice/src/index.ts @@ -1,5 +1,6 @@ import './route/echo.js'; import './route/home.js'; +import './route/cors.js'; import {logger} from './config.js'; logger.logOther(`..:: Alwatr Microservice Starter Kit ::..`); diff --git a/packages/starter/microservice/src/route/cors.ts b/packages/starter/microservice/src/route/cors.ts new file mode 100644 index 000000000..f3870ab82 --- /dev/null +++ b/packages/starter/microservice/src/route/cors.ts @@ -0,0 +1,21 @@ +import {app} from '../app.js'; + +app.route('all', '/cors', async (connection) => { + connection.reply( + { + ok: true, + statusCode: 200, + data: { + app: 'Alwatr Microservice Starter Kit', + message: 'CORS work!', + }, + }, + { + corsHelper: { + allowMethod: '*', + allowOrigin: '*', + maxAge: 5 * 60, // 5 min + }, + }, + ); +}); diff --git a/packages/starter/microservice/src/route/home.ts b/packages/starter/microservice/src/route/home.ts index d1a275096..402a2ebbf 100644 --- a/packages/starter/microservice/src/route/home.ts +++ b/packages/starter/microservice/src/route/home.ts @@ -1,14 +1,12 @@ import {app} from '../app.js'; app.route('all', '/', async (connection) => { - connection.reply( - { - ok: true, - statusCode: 200, - data: { - app: 'Alwatr Microservice Starter Kit', - message: 'Hello ;)', - }, - }, - ); + connection.reply({ + ok: true, + statusCode: 200, + data: { + app: 'Alwatr Microservice Starter Kit', + message: 'Hello ;)', + }, + }); }); From 8b86e90cc5ecbad297a0086c3d4d043a2a94a416 Mon Sep 17 00:00:00 2001 From: Amir Najafi Date: Fri, 13 May 2022 23:46:19 +0430 Subject: [PATCH 3/5] feat(micro-server): add more header for cors helper --- packages/core/micro-server/README.md | 4 ++-- .../micro-server/src/middleware/cors-helpers.ts | 16 ++++++++++++++-- packages/core/micro-server/src/type.ts | 7 +++++-- packages/starter/microservice/src/route/cors.ts | 2 +- 4 files changed, 22 insertions(+), 7 deletions(-) diff --git a/packages/core/micro-server/README.md b/packages/core/micro-server/README.md index 21ef2ee9c..b15f8b171 100644 --- a/packages/core/micro-server/README.md +++ b/packages/core/micro-server/README.md @@ -6,7 +6,7 @@ Elegant powerful nodejs server for microservice use cases, written in tiny TypeS ### Middleware -#### [Core Helper](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) +#### [CORS Helper](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) ```typescript app.route('all', '/', async (connection) => { @@ -20,7 +20,7 @@ app.route('all', '/', async (connection) => { }, }, { - coreHelper: { + corsHelper: { allowOrigin: 'https://developer.mozilla.org', // That should not end with "/" allowMethod: '*', maxAge: 5 * 60, // 5 Minute diff --git a/packages/core/micro-server/src/middleware/cors-helpers.ts b/packages/core/micro-server/src/middleware/cors-helpers.ts index 7debf999f..e82cb04a2 100644 --- a/packages/core/micro-server/src/middleware/cors-helpers.ts +++ b/packages/core/micro-server/src/middleware/cors-helpers.ts @@ -7,8 +7,20 @@ export function corsHelper(response: ServerResponse, header: CorsHelperHeader): response.setHeader('Access-Control-Allow-Origin', header.allowOrigin); } - if (header.allowMethod !== undefined) { - response.setHeader('Access-Control-Allow-Method', header.allowMethod); + if (header.allowMethods !== undefined) { + response.setHeader('Access-Control-Allow-Methods', header.allowMethods); + } + + if (header.allowHeaders !== undefined) { + response.setHeader('Access-Control-Allow-Headers', header.allowHeaders); + } + + if (header.exposeHeaders !== undefined) { + response.setHeader('Access-Control-Expose-Headers', header.exposeHeaders); + } + + if (header.allowCredentials !== undefined) { + response.setHeader('Access-Control-Allow-Credentials', String(header.allowCredentials)); } if (header.maxAge !== undefined) { diff --git a/packages/core/micro-server/src/type.ts b/packages/core/micro-server/src/type.ts index cf5b704ad..3217e69d9 100644 --- a/packages/core/micro-server/src/type.ts +++ b/packages/core/micro-server/src/type.ts @@ -16,8 +16,11 @@ export interface ResponseOptions { } export interface CorsHelperHeader { - allowOrigin?: string; - allowMethod?: string; + allowOrigin: string; + allowMethods?: string; + allowHeaders?: string; + exposeHeaders?: string; + allowCredentials?: boolean; maxAge?: number; } diff --git a/packages/starter/microservice/src/route/cors.ts b/packages/starter/microservice/src/route/cors.ts index f3870ab82..f4c88a926 100644 --- a/packages/starter/microservice/src/route/cors.ts +++ b/packages/starter/microservice/src/route/cors.ts @@ -12,8 +12,8 @@ app.route('all', '/cors', async (connection) => { }, { corsHelper: { - allowMethod: '*', allowOrigin: '*', + allowMethods: '*', maxAge: 5 * 60, // 5 min }, }, From 3b1d78e04cfa195dbd6fd65d7d633c685f960ea6 Mon Sep 17 00:00:00 2001 From: Amir Najafi Date: Sat, 14 May 2022 21:45:13 +0430 Subject: [PATCH 4/5] documention(micro-server): add more documention --- packages/core/micro-server/README.md | 25 ++++++++++++++++++- .../core/micro-server/src/micro-server.ts | 1 - .../src/middleware/cors-helpers.ts | 4 +++ .../starter/microservice/src/route/cors.ts | 4 ++- .../starter/microservice/src/route/echo.ts | 4 ++- .../starter/microservice/src/route/home.ts | 4 ++- 6 files changed, 37 insertions(+), 5 deletions(-) diff --git a/packages/core/micro-server/README.md b/packages/core/micro-server/README.md index b15f8b171..4c7dffa78 100644 --- a/packages/core/micro-server/README.md +++ b/packages/core/micro-server/README.md @@ -4,9 +4,32 @@ Elegant powerful nodejs server for microservice use cases, written in tiny TypeS ## Usage +### Create server + +```typescript +import {AlwatrMicroServer} from '@alwatr/micro-server'; + +import type {AlwatrConnection} from '@alwatr/micro-server'; + +const app = new AlwatrMicroServer(8000); + +app.route('all', '/', async (connection: AlwatrConnection) => { + connection.reply({ + ok: true, + statusCode: 200, + data: { + app: 'Alwatr Microservice', + message: 'Hello ;)', + }, + }); +}); +``` + ### Middleware -#### [CORS Helper](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) +#### CORS Helper + +Read about [Cross-Origin Resource Sharing](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS). ```typescript app.route('all', '/', async (connection) => { diff --git a/packages/core/micro-server/src/micro-server.ts b/packages/core/micro-server/src/micro-server.ts index 23f32e7ee..c95a5898d 100644 --- a/packages/core/micro-server/src/micro-server.ts +++ b/packages/core/micro-server/src/micro-server.ts @@ -212,7 +212,6 @@ export class AlwatrConnection { ); } - // set cors helper header if (options?.corsHelper !== undefined) { corsHelper(this.serverResponse, options?.corsHelper); } diff --git a/packages/core/micro-server/src/middleware/cors-helpers.ts b/packages/core/micro-server/src/middleware/cors-helpers.ts index e82cb04a2..16ec93049 100644 --- a/packages/core/micro-server/src/middleware/cors-helpers.ts +++ b/packages/core/micro-server/src/middleware/cors-helpers.ts @@ -2,6 +2,10 @@ import {CorsHelperHeader} from '../type'; import type {ServerResponse} from 'http'; +/** + * Set CORS helper header. + * https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS + */ export function corsHelper(response: ServerResponse, header: CorsHelperHeader): void { if (header.allowOrigin !== undefined) { response.setHeader('Access-Control-Allow-Origin', header.allowOrigin); diff --git a/packages/starter/microservice/src/route/cors.ts b/packages/starter/microservice/src/route/cors.ts index f4c88a926..6b484cd9e 100644 --- a/packages/starter/microservice/src/route/cors.ts +++ b/packages/starter/microservice/src/route/cors.ts @@ -1,6 +1,8 @@ import {app} from '../app.js'; -app.route('all', '/cors', async (connection) => { +import type {AlwatrConnection} from '@alwatr/micro-server'; + +app.route('all', '/cors', async (connection: AlwatrConnection) => { connection.reply( { ok: true, diff --git a/packages/starter/microservice/src/route/echo.ts b/packages/starter/microservice/src/route/echo.ts index 8601cc39f..915f4ea10 100644 --- a/packages/starter/microservice/src/route/echo.ts +++ b/packages/starter/microservice/src/route/echo.ts @@ -1,6 +1,8 @@ import {app} from '../app.js'; -app.route('post', '/echo', async (connection) => { +import type {AlwatrConnection} from '@alwatr/micro-server'; + +app.route('post', '/echo', async (connection: AlwatrConnection) => { const jsonBody = await connection.requireJsonBody(); if (jsonBody == null) return; diff --git a/packages/starter/microservice/src/route/home.ts b/packages/starter/microservice/src/route/home.ts index 402a2ebbf..4d387e4e9 100644 --- a/packages/starter/microservice/src/route/home.ts +++ b/packages/starter/microservice/src/route/home.ts @@ -1,6 +1,8 @@ import {app} from '../app.js'; -app.route('all', '/', async (connection) => { +import type {AlwatrConnection} from '@alwatr/micro-server'; + +app.route('all', '/', async (connection: AlwatrConnection) => { connection.reply({ ok: true, statusCode: 200, From fda9d1f78c8661da4ab161af8115fd5edbfc7187 Mon Sep 17 00:00:00 2001 From: Amir Najafi Date: Mon, 30 May 2022 21:27:47 +0430 Subject: [PATCH 5/5] refactor(micro-server): move CORS helper to AlwatrMicroServer --- .../core/micro-server/src/micro-server.ts | 16 ++++++++----- packages/starter/microservice/src/app.ts | 8 ++++++- packages/starter/microservice/src/index.ts | 1 - .../starter/microservice/src/route/cors.ts | 23 ------------------- 4 files changed, 17 insertions(+), 31 deletions(-) delete mode 100644 packages/starter/microservice/src/route/cors.ts diff --git a/packages/core/micro-server/src/micro-server.ts b/packages/core/micro-server/src/micro-server.ts index c95a5898d..710c823d1 100644 --- a/packages/core/micro-server/src/micro-server.ts +++ b/packages/core/micro-server/src/micro-server.ts @@ -16,7 +16,7 @@ export class AlwatrMicroServer { protected logger = createLogger(`micro-server:${this.port}`); protected server = createServer(this.handleRequest); - constructor(protected port: number, autoListen = true) { + constructor(protected port: number, autoListen = true, public options?: ResponseOptions) { this.logger.logMethodArgs('new', {port, listen: autoListen}); this.server = createServer(this.handleRequest.bind(this)); @@ -92,7 +92,7 @@ export class AlwatrMicroServer { return; } - const connection = new AlwatrConnection(incomingMessage, serverResponse); + const connection = new AlwatrConnection(incomingMessage, serverResponse, this.options); const route = connection.url.pathname; const method = connection.incomingMessage.method?.toLowerCase(); @@ -145,7 +145,11 @@ export class AlwatrConnection { readonly body = this._getRequestBody(); - constructor(public incomingMessage: IncomingMessage, public serverResponse: ServerResponse) { + constructor( + public incomingMessage: IncomingMessage, + public serverResponse: ServerResponse, + public options?: ResponseOptions, + ) { this.logger.logMethodArgs('new', {method: incomingMessage.method, url: incomingMessage.url}); } @@ -184,7 +188,7 @@ export class AlwatrConnection { } } - reply(content: ReplyContent, options?: ResponseOptions): void { + reply(content: ReplyContent): void { this.logger.logMethodArgs('reply', {content}); if (this.serverResponse.headersSent) { @@ -212,8 +216,8 @@ export class AlwatrConnection { ); } - if (options?.corsHelper !== undefined) { - corsHelper(this.serverResponse, options?.corsHelper); + if (this.options?.corsHelper !== undefined) { + corsHelper(this.serverResponse, this.options?.corsHelper); } this.serverResponse.writeHead(content.statusCode, { diff --git a/packages/starter/microservice/src/app.ts b/packages/starter/microservice/src/app.ts index 97dd88780..595ec4d7b 100644 --- a/packages/starter/microservice/src/app.ts +++ b/packages/starter/microservice/src/app.ts @@ -2,4 +2,10 @@ import {AlwatrMicroServer} from '@alwatr/micro-server'; import {config} from './config.js'; -export const app = new AlwatrMicroServer(config.port); +export const app = new AlwatrMicroServer(config.port, undefined, { + corsHelper: { + allowOrigin: '*', + allowMethods: '*', + maxAge: 5 * 60, // 5 min + }, +}); diff --git a/packages/starter/microservice/src/index.ts b/packages/starter/microservice/src/index.ts index 4d9cd1b46..8df466824 100644 --- a/packages/starter/microservice/src/index.ts +++ b/packages/starter/microservice/src/index.ts @@ -1,6 +1,5 @@ import './route/echo.js'; import './route/home.js'; -import './route/cors.js'; import {logger} from './config.js'; logger.logOther(`..:: Alwatr Microservice Starter Kit ::..`); diff --git a/packages/starter/microservice/src/route/cors.ts b/packages/starter/microservice/src/route/cors.ts deleted file mode 100644 index 6b484cd9e..000000000 --- a/packages/starter/microservice/src/route/cors.ts +++ /dev/null @@ -1,23 +0,0 @@ -import {app} from '../app.js'; - -import type {AlwatrConnection} from '@alwatr/micro-server'; - -app.route('all', '/cors', async (connection: AlwatrConnection) => { - connection.reply( - { - ok: true, - statusCode: 200, - data: { - app: 'Alwatr Microservice Starter Kit', - message: 'CORS work!', - }, - }, - { - corsHelper: { - allowOrigin: '*', - allowMethods: '*', - maxAge: 5 * 60, // 5 min - }, - }, - ); -});