fix(core): mismatched requests
MODIFY
packages/core/src/http/router/http.router.interface.ts
packages/core/src/http/router/http.router.interface.ts
-import { Subject } from 'rxjs';
+import { Observable } from 'rxjs';
import { HttpMethod, HttpRequest } from '../http.interface';
import { HttpEffect, HttpMiddlewareEffect, HttpEffectResponse } from '../effects/http.effects.interface';
@@ -50,7 +50,7 @@ export type Routing = RoutingItem[];
export interface BootstrappedRoutingItem extends Omit<RoutingItem, 'methods'> {
methods: Partial<Record<HttpMethod, {
- subject: Subject<HttpRequest>;
+ process: (req$: Observable<HttpRequest>) => Observable<HttpEffectResponse>;
parameters?: string[];
}>>;
}
@@ -58,7 +58,7 @@ export interface BootstrappedRoutingItem extends Omit<RoutingItem, 'methods'> {
export type BootstrappedRouting = BootstrappedRoutingItem[];
export interface RouteMatched {
- subject: Subject<HttpRequest>;
+ process: (req$: Observable<HttpRequest>) => Observable<HttpEffectResponse>;
params: Record<string, string>;
path: string;
}

MODIFY
packages/core/src/http/router/http.router.matcher.ts
packages/core/src/http/router/http.router.matcher.ts
@@ -21,7 +21,7 @@ export const matchRoute = (routing: BootstrappedRouting) => (url: string, method
}
return {
- subject: matchedMethod.subject,
+ process: matchedMethod.process,
params,
path,
};

MODIFY
packages/core/src/http/router/http.router.resolver.v2.ts
packages/core/src/http/router/http.router.resolver.v2.ts
-import { Subject, zip, OperatorFunction, of, fromEvent, Observable } from 'rxjs';
-import { publish, catchError, map, filter, takeUntil, share, take} from 'rxjs/operators';
+import { Subject, zip, of, fromEvent, Observable } from 'rxjs';
+import { publish, catchError, map, takeUntil, share, take} from 'rxjs/operators';
import { EffectContext } from '../../effects/effects.interface';
import { HttpServer, HttpRequest } from '../http.interface';
import { defaultError$ } from '../error/http.error.effect';
import { HttpEffectResponse, HttpErrorEffect, HttpOutputEffect } from '../effects/http.effects.interface';
-import { isError } from '../../+internal/utils';
import { Routing, BootstrappedRoutingItem } from './http.router.interface';
import { queryParamsFactory } from './http.router.query.factory';
import { matchRoute } from './http.router.matcher';
+import { ROUTE_NOT_FOUND_ERROR } from './http.router.effects';
export const resolveRouting = (
routing: Routing,
@@ -32,16 +32,6 @@ export const resolveRouting = (
? error$(errorStream$, ctx)
: defaultError$(errorStream$, ctx);
- const errorGuard: OperatorFunction<[HttpEffectResponse, HttpRequest], [HttpEffectResponse, HttpRequest]> =
- filter(response => {
- if (isError(response[0])) {
- errorSubject.next({ error: response[0], req: response[1] });
- return false;
- }
-
- return true;
- });
-
const outputFlow$ = zip(
outputEffect,
outputStream$.pipe(map(out => out.req)),
@@ -76,28 +66,18 @@ export const resolveRouting = (
const { middleware, effect, parameters } = methodItem;
- const inputSubject = new Subject<HttpRequest>();
- const inputStream$ = inputSubject.asObservable().pipe(takeUntil(close$));
-
- const subscribe = (stream$: Observable<any>) =>
- stream$.subscribe(
- ([res, req]) => outputSubject.next({ req, res }),
- undefined,
- () => subscribe(stream$),
- );
+ const process = (req$: Observable<HttpRequest>) =>
+ middleware
+ ? effect(middleware(req$, ctx), ctx)
+ : effect(req$, ctx);
- const flow$ = zip(
- inputStream$.pipe(
- publish(req$ => middleware ? middleware(req$, ctx) : req$),
- publish(req$ => effect(req$, ctx)),
- catchError(error => of(error)),
- ),
- inputStream$,
- ).pipe(errorGuard)
-
- subscribe(flow$);
-
- return { ...acc, [method]: { subject: inputSubject, parameters } };
+ return {
+ ...acc,
+ [method]: {
+ process,
+ parameters,
+ },
+ };
}, {}),
}));
@@ -107,14 +87,24 @@ export const resolveRouting = (
const [urlPath, urlQuery] = req.url.split('?');
const resolvedRoute = find(urlPath, req.method);
- if (!resolvedRoute) { return; }
+ if (!resolvedRoute) {
+ return errorSubject.next({ req, error: ROUTE_NOT_FOUND_ERROR });
+ }
req.query = queryParamsFactory(urlQuery);
req.params = resolvedRoute.params;
req.meta = {};
req.meta.path = resolvedRoute.path;
- return resolvedRoute.subject;
+ of(req)
+ .pipe(
+ publish(resolvedRoute.process),
+ take(1),
+ )
+ .subscribe(
+ res => outputSubject.next({ res, req }),
+ error => errorSubject.next({ error, req }),
+ );
};
return {

MODIFY
packages/core/src/http/router/specs/http.router.resolver.v2.spec.ts
packages/core/src/http/router/specs/http.router.resolver.v2.spec.ts
@@ -59,11 +59,11 @@ describe('#resolveRouting', () => {
},
);
- resolve(req1)?.next(req1);
- resolve(req2)?.next(req2);
- resolve(req3)?.next(req3);
- resolve(req4)?.next(req4);
- resolve(req5)?.next(req5);
+ resolve(req1);
+ resolve(req2);
+ resolve(req3);
+ resolve(req4);
+ resolve(req5);
});
test('returns undefined if route cannot be resolved', () => {

MODIFY
packages/core/src/http/server/http.server.listener.ts
packages/core/src/http/server/http.server.listener.ts
@@ -5,7 +5,6 @@ import { handleResponse } from '../response/http.responseHandler';
import { RouteEffect, RouteEffectGroup, Routing } from '../router/http.router.interface';
import { resolveRouting } from '../router/http.router.resolver.v2';
import { factorizeRoutingWithDefaults } from '../router/http.router.factory';
-import { ROUTE_NOT_FOUND_ERROR } from '../router/http.router.effects';
import { createEffectContext } from '../../effects/effectsContext.factory';
import { useContext } from '../../context/context.hook';
import { createListener } from '../../listener/listener.factory';
@@ -34,7 +33,7 @@ export const httpListener = createListener<HttpListenerConfig, HttpListener>(con
const client = useContext(ServerClientToken)(ask);
const effectContext = createEffectContext({ ask, client });
const routing = factorizeRoutingWithDefaults(effects, middlewares ?? []);
- const { resolve, errorSubject } = resolveRouting(routing, effectContext)(output$, error$);
+ const { resolve } = resolveRouting(routing, effectContext)(output$, error$);
const handle = (req: IncomingMessage, res: OutgoingMessage) => {
const marbleReq = req as HttpRequest;
@@ -43,13 +42,7 @@ export const httpListener = createListener<HttpListenerConfig, HttpListener>(con
marbleRes.send = handleResponse(ask)(marbleRes)(marbleReq);
marbleReq.response = marbleRes;
- const routeSubject = resolve(marbleReq);
-
- if (routeSubject) {
- routeSubject.next(marbleReq);
- } else {
- errorSubject.next({ req: marbleReq, error: ROUTE_NOT_FOUND_ERROR });
- }
+ resolve(marbleReq);
};
handle.config = { routing };

fix(core): mismatched requests