change: Rename FirstCompositeHandler into WaterfallHandler.

This commit is contained in:
Ruben Verborgh 2020-12-08 21:07:19 +00:00 committed by Joachim Van Herwegen
parent ba47ce7951
commit f26178b1b5
14 changed files with 45 additions and 45 deletions

View File

@ -3,8 +3,8 @@
"@graph": [ "@graph": [
{ {
"@id": "urn:solid-server:default:CredentialsExtractor", "@id": "urn:solid-server:default:CredentialsExtractor",
"@type": "FirstCompositeHandler", "@type": "WaterfallHandler",
"FirstCompositeHandler:_handlers": [ "WaterfallHandler:_handlers": [
{ {
"@type": "DPoPWebIdExtractor", "@type": "DPoPWebIdExtractor",
"DPoPWebIdExtractor:_targetExtractor": { "DPoPWebIdExtractor:_targetExtractor": {

View File

@ -3,8 +3,8 @@
"@graph": [ "@graph": [
{ {
"@id": "urn:solid-server:default:OperationHandler", "@id": "urn:solid-server:default:OperationHandler",
"@type": "FirstCompositeHandler", "@type": "WaterfallHandler",
"FirstCompositeHandler:_handlers": [ "WaterfallHandler:_handlers": [
{ {
"@type": "DeleteOperationHandler", "@type": "DeleteOperationHandler",
"DeleteOperationHandler:_store": { "DeleteOperationHandler:_store": {

View File

@ -3,8 +3,8 @@
"@graph": [ "@graph": [
{ {
"@id": "urn:solid-server:default:PermissionsExtractor", "@id": "urn:solid-server:default:PermissionsExtractor",
"@type": "FirstCompositeHandler", "@type": "WaterfallHandler",
"FirstCompositeHandler:_handlers": [ "WaterfallHandler:_handlers": [
{ {
"@type": "MethodPermissionsExtractor" "@type": "MethodPermissionsExtractor"
}, },

View File

@ -14,8 +14,8 @@
"@id": "urn:solid-server:default:MetadataExtractor" "@id": "urn:solid-server:default:MetadataExtractor"
}, },
"BasicRequestParser:_args_bodyParser": { "BasicRequestParser:_args_bodyParser": {
"@type": "FirstCompositeHandler", "@type": "WaterfallHandler",
"FirstCompositeHandler:_handlers": [ "WaterfallHandler:_handlers": [
{ {
"@type": "SparqlUpdateBodyParser" "@type": "SparqlUpdateBodyParser"
}, },

View File

@ -31,8 +31,8 @@
}, },
{ {
"@id": "urn:solid-server:default:ResponseWriter", "@id": "urn:solid-server:default:ResponseWriter",
"@type": "FirstCompositeHandler", "@type": "WaterfallHandler",
"FirstCompositeHandler:_handlers": [ "WaterfallHandler:_handlers": [
{ {
"@type": "ErrorResponseWriter" "@type": "ErrorResponseWriter"
}, },

View File

@ -26,8 +26,8 @@
{ {
"@id": "urn:solid-server:default:RepresentationConverter", "@id": "urn:solid-server:default:RepresentationConverter",
"@type": "FirstCompositeHandler", "@type": "WaterfallHandler",
"FirstCompositeHandler:_handlers": [ "WaterfallHandler:_handlers": [
{ {
"@id": "urn:solid-server:default:RdfToQuadConverter" "@id": "urn:solid-server:default:RdfToQuadConverter"
}, },

View File

@ -182,9 +182,9 @@ export * from './util/locking/WrappedExpiringResourceLocker';
// Util // Util
export * from './util/AsyncHandler'; export * from './util/AsyncHandler';
export * from './util/FirstCompositeHandler';
export * from './util/HeaderUtil'; export * from './util/HeaderUtil';
export * from './util/PathUtil'; export * from './util/PathUtil';
export * from './util/QuadUtil'; export * from './util/QuadUtil';
export * from './util/SequenceHandler'; export * from './util/SequenceHandler';
export * from './util/StreamUtil'; export * from './util/StreamUtil';
export * from './util/WaterfallHandler';

View File

@ -5,18 +5,18 @@ import { HttpError } from './errors/HttpError';
import { InternalServerError } from './errors/InternalServerError'; import { InternalServerError } from './errors/InternalServerError';
/** /**
* Handler that combines several other handlers, * A composite handler that tries multiple handlers one by one
* thereby allowing other classes that depend on a single handler to still use multiple. * until it finds a handler that supports the input.
* The handlers will be checked in the order they appear in the input array, * The handlers will be checked in the order they appear in the input array,
* allowing for more fine-grained handlers to check before catch-all handlers. * allowing for more fine-grained handlers to check before catch-all handlers.
*/ */
export class FirstCompositeHandler<TIn, TOut> implements AsyncHandler<TIn, TOut> { export class WaterfallHandler<TIn, TOut> implements AsyncHandler<TIn, TOut> {
protected readonly logger = getLoggerFor(this); protected readonly logger = getLoggerFor(this);
private readonly handlers: AsyncHandler<TIn, TOut>[]; private readonly handlers: AsyncHandler<TIn, TOut>[];
/** /**
* Creates a new FirstCompositeHandler that stores the given handlers. * Creates a new WaterfallHandler that stores the given handlers.
* @param handlers - Handlers over which it will run. * @param handlers - Handlers over which it will run.
*/ */
public constructor(handlers: AsyncHandler<TIn, TOut>[]) { public constructor(handlers: AsyncHandler<TIn, TOut>[]) {

View File

@ -6,10 +6,10 @@ import type {
import { import {
AuthenticatedLdpHandler, AuthenticatedLdpHandler,
EmptyCredentialsExtractor, EmptyCredentialsExtractor,
FirstCompositeHandler,
MethodPermissionsExtractor, MethodPermissionsExtractor,
RdfToQuadConverter, RdfToQuadConverter,
QuadToRdfConverter, QuadToRdfConverter,
WaterfallHandler,
} from '../../src/index'; } from '../../src/index';
import type { ServerConfig } from './ServerConfig'; import type { ServerConfig } from './ServerConfig';
import { import {
@ -44,7 +44,7 @@ export class AuthenticatedDataAccessorBasedConfig implements ServerConfig {
const requestParser = getBasicRequestParser(); const requestParser = getBasicRequestParser();
const credentialsExtractor = new EmptyCredentialsExtractor(); const credentialsExtractor = new EmptyCredentialsExtractor();
const permissionsExtractor = new FirstCompositeHandler([ const permissionsExtractor = new WaterfallHandler([
new MethodPermissionsExtractor(), new MethodPermissionsExtractor(),
]); ]);

View File

@ -6,13 +6,13 @@ import {
AllowEverythingAuthorizer, AllowEverythingAuthorizer,
AuthenticatedLdpHandler, AuthenticatedLdpHandler,
EmptyCredentialsExtractor, EmptyCredentialsExtractor,
FirstCompositeHandler,
MethodPermissionsExtractor, MethodPermissionsExtractor,
QuadToRdfConverter, QuadToRdfConverter,
RawBodyParser, RawBodyParser,
RdfToQuadConverter, RdfToQuadConverter,
SparqlUpdateBodyParser, SparqlUpdateBodyParser,
SparqlPatchPermissionsExtractor, SparqlPatchPermissionsExtractor,
WaterfallHandler,
} from '../../src/index'; } from '../../src/index';
import type { ServerConfig } from './ServerConfig'; import type { ServerConfig } from './ServerConfig';
@ -50,7 +50,7 @@ export class BasicHandlersConfig implements ServerConfig {
]); ]);
const credentialsExtractor = new EmptyCredentialsExtractor(); const credentialsExtractor = new EmptyCredentialsExtractor();
const permissionsExtractor = new FirstCompositeHandler([ const permissionsExtractor = new WaterfallHandler([
new MethodPermissionsExtractor(), new MethodPermissionsExtractor(),
new SparqlPatchPermissionsExtractor(), new SparqlPatchPermissionsExtractor(),
]); ]);

View File

@ -5,10 +5,10 @@ import type {
import { import {
AuthenticatedLdpHandler, AuthenticatedLdpHandler,
EmptyCredentialsExtractor, EmptyCredentialsExtractor,
FirstCompositeHandler,
MethodPermissionsExtractor, MethodPermissionsExtractor,
RdfToQuadConverter, RdfToQuadConverter,
QuadToRdfConverter, QuadToRdfConverter,
WaterfallHandler,
} from '../../src/index'; } from '../../src/index';
import type { ServerConfig } from './ServerConfig'; import type { ServerConfig } from './ServerConfig';
import { import {
@ -42,7 +42,7 @@ export class BasicHandlersWithAclConfig implements ServerConfig {
const requestParser = getBasicRequestParser(); const requestParser = getBasicRequestParser();
const credentialsExtractor = new EmptyCredentialsExtractor(); const credentialsExtractor = new EmptyCredentialsExtractor();
const permissionsExtractor = new FirstCompositeHandler([ const permissionsExtractor = new WaterfallHandler([
new MethodPermissionsExtractor(), new MethodPermissionsExtractor(),
]); ]);

View File

@ -7,11 +7,11 @@ import {
AllowEverythingAuthorizer, AllowEverythingAuthorizer,
AuthenticatedLdpHandler, AuthenticatedLdpHandler,
EmptyCredentialsExtractor, EmptyCredentialsExtractor,
FirstCompositeHandler,
MethodPermissionsExtractor, MethodPermissionsExtractor,
QuadToRdfConverter, QuadToRdfConverter,
RawBodyParser, RawBodyParser,
RdfToQuadConverter, RdfToQuadConverter,
WaterfallHandler,
} from '../../src/index'; } from '../../src/index';
import type { ServerConfig } from './ServerConfig'; import type { ServerConfig } from './ServerConfig';
import { import {
@ -44,7 +44,7 @@ export class DataAccessorBasedConfig implements ServerConfig {
const requestParser = getBasicRequestParser([ new RawBodyParser() ]); const requestParser = getBasicRequestParser([ new RawBodyParser() ]);
const credentialsExtractor = new EmptyCredentialsExtractor(); const credentialsExtractor = new EmptyCredentialsExtractor();
const permissionsExtractor = new FirstCompositeHandler([ const permissionsExtractor = new WaterfallHandler([
new MethodPermissionsExtractor(), new MethodPermissionsExtractor(),
]); ]);
const authorizer = new AllowEverythingAuthorizer(); const authorizer = new AllowEverythingAuthorizer();

View File

@ -22,7 +22,6 @@ import {
DataAccessorBasedStore, DataAccessorBasedStore,
DeleteOperationHandler, DeleteOperationHandler,
ErrorResponseWriter, ErrorResponseWriter,
FirstCompositeHandler,
GetOperationHandler, GetOperationHandler,
HeadOperationHandler, HeadOperationHandler,
InMemoryDataAccessor, InMemoryDataAccessor,
@ -40,6 +39,7 @@ import {
SlugParser, SlugParser,
SparqlUpdatePatchHandler, SparqlUpdatePatchHandler,
UrlBasedAclManager, UrlBasedAclManager,
WaterfallHandler,
WebAclAuthorizer, WebAclAuthorizer,
} from '../../src/index'; } from '../../src/index';
import { CONTENT_TYPE, HTTP, RDF } from '../../src/util/UriConstants'; import { CONTENT_TYPE, HTTP, RDF } from '../../src/util/UriConstants';
@ -82,8 +82,8 @@ export const getConvertingStore =
(store: ResourceStore, converters: RepresentationConverter[], inType?: string): (store: ResourceStore, converters: RepresentationConverter[], inType?: string):
RepresentationConvertingStore => RepresentationConvertingStore =>
new RepresentationConvertingStore(store, { new RepresentationConvertingStore(store, {
inConverter: new FirstCompositeHandler(converters), inConverter: new WaterfallHandler(converters),
outConverter: new FirstCompositeHandler(converters), outConverter: new WaterfallHandler(converters),
inType, inType,
}); });
@ -114,7 +114,7 @@ export const getOperationHandler = (store: ResourceStore): OperationHandler => {
new PatchOperationHandler(store), new PatchOperationHandler(store),
new DeleteOperationHandler(store), new DeleteOperationHandler(store),
]; ];
return new FirstCompositeHandler<Operation, ResponseDescription>(handlers); return new WaterfallHandler<Operation, ResponseDescription>(handlers);
}; };
export const getResponseWriter = (): ResponseWriter => { export const getResponseWriter = (): ResponseWriter => {
@ -128,7 +128,7 @@ export const getResponseWriter = (): ResponseWriter => {
}), }),
]); ]);
return new FirstCompositeHandler<{ response: HttpResponse; result: ResponseDescription | Error }, void>([ return new WaterfallHandler<{ response: HttpResponse; result: ResponseDescription | Error }, void>([
new ErrorResponseWriter(), new ErrorResponseWriter(),
new BasicResponseWriter(serializer), new BasicResponseWriter(serializer),
]); ]);
@ -157,7 +157,7 @@ export const getBasicRequestParser = (bodyParsers: BodyParser[] = []): BasicRequ
// If no body parser is given (array is empty), default to RawBodyParser // If no body parser is given (array is empty), default to RawBodyParser
bodyParser = new RawBodyParser(); bodyParser = new RawBodyParser();
} else { } else {
bodyParser = new FirstCompositeHandler(bodyParsers); bodyParser = new WaterfallHandler(bodyParsers);
} }
return new BasicRequestParser({ return new BasicRequestParser({
targetExtractor: new BasicTargetExtractor(), targetExtractor: new BasicTargetExtractor(),

View File

@ -1,19 +1,19 @@
import type { AsyncHandler } from '../../../src/util/AsyncHandler'; import type { AsyncHandler } from '../../../src/util/AsyncHandler';
import { BadRequestHttpError } from '../../../src/util/errors/BadRequestHttpError'; import { BadRequestHttpError } from '../../../src/util/errors/BadRequestHttpError';
import { HttpError } from '../../../src/util/errors/HttpError'; import { HttpError } from '../../../src/util/errors/HttpError';
import { FirstCompositeHandler } from '../../../src/util/FirstCompositeHandler'; import { WaterfallHandler } from '../../../src/util/WaterfallHandler';
import { StaticAsyncHandler } from '../../util/StaticAsyncHandler'; import { StaticAsyncHandler } from '../../util/StaticAsyncHandler';
describe('A FirstCompositeHandler', (): void => { describe('A WaterfallHandler', (): void => {
describe('with no handlers', (): void => { describe('with no handlers', (): void => {
it('can never handle data.', async(): Promise<void> => { it('can never handle data.', async(): Promise<void> => {
const handler = new FirstCompositeHandler([]); const handler = new WaterfallHandler([]);
await expect(handler.canHandle(null)).rejects.toThrow(Error); await expect(handler.canHandle(null)).rejects.toThrow(Error);
}); });
it('errors if its handle function is called.', async(): Promise<void> => { it('errors if its handle function is called.', async(): Promise<void> => {
const handler = new FirstCompositeHandler([]); const handler = new WaterfallHandler([]);
await expect(handler.handle(null)).rejects.toThrow(Error); await expect(handler.handle(null)).rejects.toThrow(Error);
}); });
@ -36,13 +36,13 @@ describe('A FirstCompositeHandler', (): void => {
}); });
it('can handle data if a handler supports it.', async(): Promise<void> => { it('can handle data if a handler supports it.', async(): Promise<void> => {
const handler = new FirstCompositeHandler([ handlerFalse, handlerTrue ]); const handler = new WaterfallHandler([ handlerFalse, handlerTrue ]);
await expect(handler.canHandle(null)).resolves.toBeUndefined(); await expect(handler.canHandle(null)).resolves.toBeUndefined();
}); });
it('can not handle data if no handler supports it.', async(): Promise<void> => { it('can not handle data if no handler supports it.', async(): Promise<void> => {
const handler = new FirstCompositeHandler([ handlerFalse, handlerFalse ]); const handler = new WaterfallHandler([ handlerFalse, handlerFalse ]);
await expect(handler.canHandle(null)).rejects.toThrow('[Not supported, Not supported]'); await expect(handler.canHandle(null)).rejects.toThrow('[Not supported, Not supported]');
}); });
@ -51,13 +51,13 @@ describe('A FirstCompositeHandler', (): void => {
handlerFalse.canHandle = async(): Promise<void> => { handlerFalse.canHandle = async(): Promise<void> => {
throw 'apple'; throw 'apple';
}; };
const handler = new FirstCompositeHandler([ handlerFalse, handlerFalse ]); const handler = new WaterfallHandler([ handlerFalse, handlerFalse ]);
await expect(handler.canHandle(null)).rejects.toThrow('[Unknown error, Unknown error]'); await expect(handler.canHandle(null)).rejects.toThrow('[Unknown error, Unknown error]');
}); });
it('handles data if a handler supports it.', async(): Promise<void> => { it('handles data if a handler supports it.', async(): Promise<void> => {
const handler = new FirstCompositeHandler([ handlerFalse, handlerTrue ]); const handler = new WaterfallHandler([ handlerFalse, handlerTrue ]);
await expect(handler.handle('test')).resolves.toEqual('test'); await expect(handler.handle('test')).resolves.toEqual('test');
expect(canHandleFn).toHaveBeenCalledTimes(1); expect(canHandleFn).toHaveBeenCalledTimes(1);
@ -65,13 +65,13 @@ describe('A FirstCompositeHandler', (): void => {
}); });
it('errors if the handle function is called but no handler supports the data.', async(): Promise<void> => { it('errors if the handle function is called but no handler supports the data.', async(): Promise<void> => {
const handler = new FirstCompositeHandler([ handlerFalse, handlerFalse ]); const handler = new WaterfallHandler([ handlerFalse, handlerFalse ]);
await expect(handler.handle('test')).rejects.toThrow('All handlers failed'); await expect(handler.handle('test')).rejects.toThrow('All handlers failed');
}); });
it('only calls the canHandle function once of its handlers when handleSafe is called.', async(): Promise<void> => { it('only calls the canHandle function once of its handlers when handleSafe is called.', async(): Promise<void> => {
const handler = new FirstCompositeHandler([ handlerFalse, handlerTrue ]); const handler = new WaterfallHandler([ handlerFalse, handlerTrue ]);
await expect(handler.handleSafe('test')).resolves.toEqual('test'); await expect(handler.handleSafe('test')).resolves.toEqual('test');
expect(canHandleFn).toHaveBeenCalledTimes(1); expect(canHandleFn).toHaveBeenCalledTimes(1);
@ -79,7 +79,7 @@ describe('A FirstCompositeHandler', (): void => {
}); });
it('throws the canHandle error when calling handleSafe if the data is not supported.', async(): Promise<void> => { it('throws the canHandle error when calling handleSafe if the data is not supported.', async(): Promise<void> => {
const handler = new FirstCompositeHandler([ handlerFalse, handlerFalse ]); const handler = new WaterfallHandler([ handlerFalse, handlerFalse ]);
await expect(handler.handleSafe(null)).rejects.toThrow('[Not supported, Not supported]'); await expect(handler.handleSafe(null)).rejects.toThrow('[Not supported, Not supported]');
}); });
@ -88,7 +88,7 @@ describe('A FirstCompositeHandler', (): void => {
handlerTrue.canHandle = async(): Promise<void> => { handlerTrue.canHandle = async(): Promise<void> => {
throw new HttpError(401, 'UnauthorizedHttpError'); throw new HttpError(401, 'UnauthorizedHttpError');
}; };
const handler = new FirstCompositeHandler([ handlerTrue, handlerTrue ]); const handler = new WaterfallHandler([ handlerTrue, handlerTrue ]);
await expect(handler.canHandle(null)).rejects.toMatchObject({ await expect(handler.canHandle(null)).rejects.toMatchObject({
statusCode: 401, statusCode: 401,
@ -103,7 +103,7 @@ describe('A FirstCompositeHandler', (): void => {
handlerFalse.canHandle = async(): Promise<void> => { handlerFalse.canHandle = async(): Promise<void> => {
throw new Error('Server is crashing!'); throw new Error('Server is crashing!');
}; };
const handler = new FirstCompositeHandler([ handlerTrue, handlerFalse ]); const handler = new WaterfallHandler([ handlerTrue, handlerFalse ]);
await expect(handler.canHandle(null)).rejects.toMatchObject({ await expect(handler.canHandle(null)).rejects.toMatchObject({
statusCode: 500, statusCode: 500,
@ -118,7 +118,7 @@ describe('A FirstCompositeHandler', (): void => {
handlerFalse.canHandle = async(): Promise<void> => { handlerFalse.canHandle = async(): Promise<void> => {
throw new HttpError(415, 'UnsupportedMediaTypeHttpError'); throw new HttpError(415, 'UnsupportedMediaTypeHttpError');
}; };
const handler = new FirstCompositeHandler([ handlerTrue, handlerFalse ]); const handler = new WaterfallHandler([ handlerTrue, handlerFalse ]);
await expect(handler.canHandle(null)).rejects.toThrow(BadRequestHttpError); await expect(handler.canHandle(null)).rejects.toThrow(BadRequestHttpError);
}); });