fix: Make getParentContainer work with query parameters

This commit is contained in:
Joachim Van Herwegen 2024-04-18 11:18:03 +02:00
parent f73dfb31c0
commit 099897013c
2 changed files with 17 additions and 6 deletions

View File

@ -1,9 +1,19 @@
import type { ResourceIdentifier } from '../../http/representation/ResourceIdentifier';
import { errorTermsToMetadata } from '../errors/HttpErrorUtil';
import { InternalServerError } from '../errors/InternalServerError';
import { ensureTrailingSlash, isContainerIdentifier } from '../PathUtil';
import { isContainerIdentifier } from '../PathUtil';
import type { IdentifierStrategy } from './IdentifierStrategy';
/**
* Regular expression used to determine the parent container of a resource.
*/
const parentRegex = /^(.+\/)[^/]+\/*$/u;
/**
* Used during containment check to determine if an identifier is a direct child or not.
*/
const tailRegex = /\/./u;
/**
* Provides a default implementation for `getParentContainer`
* which checks if the identifier is supported and not a root container.
@ -26,10 +36,9 @@ export abstract class BaseIdentifierStrategy implements IdentifierStrategy {
throw new InternalServerError(`Cannot obtain the parent of ${identifier.path} because it is a root container.`);
}
// Trailing slash is necessary for URL library
const parentPath = new URL('..', ensureTrailingSlash(identifier.path)).href;
return { path: parentPath };
// Due to the checks above we know this will always succeed
const match = parentRegex.exec(identifier.path);
return { path: match![1] };
}
public abstract isRootContainer(identifier: ResourceIdentifier): boolean;
@ -49,6 +58,6 @@ export abstract class BaseIdentifierStrategy implements IdentifierStrategy {
const tail = identifier.path.slice(container.path.length);
// If there is at least one `/` followed by a char this is not a direct parent container
return !/\/./u.test(tail);
return !tailRegex.test(tail);
}
}

View File

@ -19,7 +19,9 @@ describe('A BaseIdentifierStrategy', (): void => {
describe('getParentContainer', (): void => {
it('returns the parent identifier.', async(): Promise<void> => {
expect(strategy.getParentContainer({ path: 'http://example.com/foo/bar' })).toEqual({ path: 'http://example.com/foo/' });
expect(strategy.getParentContainer({ path: 'http://example.com/foo//' })).toEqual({ path: 'http://example.com/' });
expect(strategy.getParentContainer({ path: 'http://example.com/foo/bar/' })).toEqual({ path: 'http://example.com/foo/' });
expect(strategy.getParentContainer({ path: 'http://example.com/foo/bar?q=5' })).toEqual({ path: 'http://example.com/foo/' });
});
it('errors when attempting to get the parent of an unsupported identifier.', async(): Promise<void> => {