feature - body-parser middleware
MODIFY
example/controllers.ts
example/controllers.ts
@@ -14,8 +14,9 @@ export const root$: Effect = request$ => request$
export const hello$: Effect = request$ => request$
.pipe(
filter(req => req.url === '/hello'),
+ filter(req => req.method === 'POST'),
map(req => ({
status: StatusCode.OK,
- body: { data: `Hello, world! @ ${req.url}` },
+ body: { data: `Hello, ${req.body.data}! @ ${req.url}` },
}))
);

MODIFY
example/index.ts
example/index.ts
import * as http from 'http';
import { root$, hello$ } from './controllers';
-import { httpListener, logger$ } from '../src';
+import { httpListener, logger$, bodyParser$ } from '../src';
const createServer = () => {
const HOSTNAME = '127.0.0.1';
@@ -8,6 +8,7 @@ const createServer = () => {
const middlewares = [
logger$,
+ bodyParser$,
];
const effects = [

MODIFY
src/http.interface.ts
src/http.interface.ts
import * as http from 'http';
export interface HttpRequest extends http.IncomingMessage {
+ body?: any;
[key: string]: any;
}

ADD
src/middlewares/bodyParser.middleware.ts
+import { Observable } from 'rxjs';
+import { switchMap, tap, toArray, map } from 'rxjs/operators';
+import { HttpRequest } from '../http.interface';
+import { Effect } from '../effects/effects.interface';
+import { ContentType } from '../util';
+
+export const fromReadableStream = (stream: HttpRequest): Observable<any> => {
+ stream.pause();
+ return Observable.create(observer => {
+ const next = chunk => observer.next(chunk);
+ const complete = () => observer.complete();
+ const error = err => observer.error(err);
+
+ stream
+ .on('data', next)
+ .on('error', error)
+ .on('end', complete)
+ .resume();
+
+ return () => {
+ stream.removeListener('data', next);
+ stream.removeListener('error', error);
+ stream.removeListener('end', complete);
+ };
+ });
+};
+
+export const getBody = (req: HttpRequest) =>
+ fromReadableStream(req)
+ .pipe(
+ toArray(),
+ map(chunks => Buffer.concat(chunks)),
+ map(buffer => buffer.toString()),
+ map(body => {
+ switch (req.headers['content-type']) {
+ case ContentType.APPLICATION_JSON:
+ return JSON.parse(body);
+ default:
+ return body;
+ }
+ }),
+ );
+
+export const bodyParser$: Effect<HttpRequest> = request$ => request$
+ .pipe(
+ switchMap(req =>
+ req.method === 'POST' || req.method === 'PUT' || req.method === 'PATCH'
+ ? request$.pipe(
+ switchMap(getBody),
+ tap(body => req.body = body),
+ map(body => req)
+ )
+ : request$
+ )
+ );

MODIFY
src/middlewares/index.ts
src/middlewares/index.ts
+export * from './bodyParser.middleware';
export * from './logger.middleware';

feature - body-parser middleware