mirror of
https://github.com/CommunitySolidServer/CommunitySolidServer.git
synced 2024-10-03 14:55:10 +00:00
feat: Create RedirectAllHttpHandler
This handler will redirect all requests to a specific URL
This commit is contained in:
parent
facf691e86
commit
02df2905de
@ -216,6 +216,7 @@ export * from './server/middleware/StaticAssetHandler';
|
|||||||
export * from './server/middleware/WebSocketAdvertiser';
|
export * from './server/middleware/WebSocketAdvertiser';
|
||||||
|
|
||||||
// Server/Util
|
// Server/Util
|
||||||
|
export * from './server/util/RedirectAllHttpHandler';
|
||||||
export * from './server/util/RouterHandler';
|
export * from './server/util/RouterHandler';
|
||||||
|
|
||||||
// Storage/Accessors
|
// Storage/Accessors
|
||||||
|
46
src/server/util/RedirectAllHttpHandler.ts
Normal file
46
src/server/util/RedirectAllHttpHandler.ts
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
import { RedirectResponseDescription } from '../../ldp/http/response/RedirectResponseDescription';
|
||||||
|
import type { ResponseWriter } from '../../ldp/http/ResponseWriter';
|
||||||
|
import type { TargetExtractor } from '../../ldp/http/TargetExtractor';
|
||||||
|
import { NotImplementedHttpError } from '../../util/errors/NotImplementedHttpError';
|
||||||
|
import { getRelativeUrl, joinUrl } from '../../util/PathUtil';
|
||||||
|
import type { HttpHandlerInput } from '../HttpHandler';
|
||||||
|
import { HttpHandler } from '../HttpHandler';
|
||||||
|
|
||||||
|
export interface RedirectAllHttpHandlerArgs {
|
||||||
|
baseUrl: string;
|
||||||
|
target: string;
|
||||||
|
targetExtractor: TargetExtractor;
|
||||||
|
responseWriter: ResponseWriter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will redirect all incoming requests to the given target.
|
||||||
|
* In case the incoming request already has the correct target,
|
||||||
|
* the `canHandle` call will reject the input.
|
||||||
|
*/
|
||||||
|
export class RedirectAllHttpHandler extends HttpHandler {
|
||||||
|
private readonly baseUrl: string;
|
||||||
|
private readonly target: string;
|
||||||
|
private readonly targetExtractor: TargetExtractor;
|
||||||
|
private readonly responseWriter: ResponseWriter;
|
||||||
|
|
||||||
|
public constructor(args: RedirectAllHttpHandlerArgs) {
|
||||||
|
super();
|
||||||
|
this.baseUrl = args.baseUrl;
|
||||||
|
this.target = args.target;
|
||||||
|
this.targetExtractor = args.targetExtractor;
|
||||||
|
this.responseWriter = args.responseWriter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async canHandle({ request }: HttpHandlerInput): Promise<void> {
|
||||||
|
const target = await getRelativeUrl(this.baseUrl, request, this.targetExtractor);
|
||||||
|
if (target === this.target) {
|
||||||
|
throw new NotImplementedHttpError('Target is already correct.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async handle({ response }: HttpHandlerInput): Promise<void> {
|
||||||
|
const result = new RedirectResponseDescription(joinUrl(this.baseUrl, this.target));
|
||||||
|
await this.responseWriter.handleSafe({ response, result });
|
||||||
|
}
|
||||||
|
}
|
53
test/unit/server/util/RedirectAllHttpHandler.test.ts
Normal file
53
test/unit/server/util/RedirectAllHttpHandler.test.ts
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
import type { ResponseWriter } from '../../../../src/ldp/http/ResponseWriter';
|
||||||
|
import type { TargetExtractor } from '../../../../src/ldp/http/TargetExtractor';
|
||||||
|
import type { ResourceIdentifier } from '../../../../src/ldp/representation/ResourceIdentifier';
|
||||||
|
import type { HttpRequest } from '../../../../src/server/HttpRequest';
|
||||||
|
import type { HttpResponse } from '../../../../src/server/HttpResponse';
|
||||||
|
import { RedirectAllHttpHandler } from '../../../../src/server/util/RedirectAllHttpHandler';
|
||||||
|
import { NotImplementedHttpError } from '../../../../src/util/errors/NotImplementedHttpError';
|
||||||
|
import { joinUrl } from '../../../../src/util/PathUtil';
|
||||||
|
import { SOLID_HTTP } from '../../../../src/util/Vocabularies';
|
||||||
|
|
||||||
|
describe('A RedirectAllHttpHandler', (): void => {
|
||||||
|
const baseUrl = 'http://test.com/';
|
||||||
|
const target = '/foo';
|
||||||
|
const absoluteTarget = 'http://test.com/foo';
|
||||||
|
let request: HttpRequest;
|
||||||
|
const response: HttpResponse = {} as any;
|
||||||
|
let targetExtractor: jest.Mocked<TargetExtractor>;
|
||||||
|
let responseWriter: jest.Mocked<ResponseWriter>;
|
||||||
|
let handler: RedirectAllHttpHandler;
|
||||||
|
|
||||||
|
beforeEach(async(): Promise<void> => {
|
||||||
|
request = { url: '/foo' } as any;
|
||||||
|
|
||||||
|
targetExtractor = {
|
||||||
|
handleSafe: jest.fn(({ request: req }): ResourceIdentifier => ({ path: joinUrl(baseUrl, req.url!) })),
|
||||||
|
} as any;
|
||||||
|
|
||||||
|
responseWriter = { handleSafe: jest.fn() } as any;
|
||||||
|
|
||||||
|
handler = new RedirectAllHttpHandler({ baseUrl, target, targetExtractor, responseWriter });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('rejects requests for the target.', async(): Promise<void> => {
|
||||||
|
request.url = target;
|
||||||
|
await expect(handler.canHandle({ request, response })).rejects.toThrow(NotImplementedHttpError);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('accepts all other requests.', async(): Promise<void> => {
|
||||||
|
request.url = '/otherPath';
|
||||||
|
await expect(handler.canHandle({ request, response })).resolves.toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('writes out a redirect response.', async(): Promise<void> => {
|
||||||
|
await expect(handler.handle({ request, response })).resolves.toBeUndefined();
|
||||||
|
expect(responseWriter.handleSafe).toHaveBeenCalledTimes(1);
|
||||||
|
expect(responseWriter.handleSafe).toHaveBeenLastCalledWith({
|
||||||
|
response,
|
||||||
|
result: expect.objectContaining({ statusCode: 302 }),
|
||||||
|
});
|
||||||
|
const { metadata } = responseWriter.handleSafe.mock.calls[0][0].result;
|
||||||
|
expect(metadata?.get(SOLID_HTTP.terms.location)?.value).toBe(absoluteTarget);
|
||||||
|
});
|
||||||
|
});
|
Loading…
x
Reference in New Issue
Block a user