fix: Expose auxiliary links on errors

This commit is contained in:
Joachim Van Herwegen 2024-04-04 10:11:26 +02:00
parent 419312ee5f
commit d7078ad692
2 changed files with 25 additions and 4 deletions

View File

@ -1,9 +1,10 @@
import { Util } from 'n3';
import { getLoggerFor } from '../../../logging/LogUtil'; import { getLoggerFor } from '../../../logging/LogUtil';
import type { HttpResponse } from '../../../server/HttpResponse'; import type { HttpResponse } from '../../../server/HttpResponse';
import { addHeader } from '../../../util/HeaderUtil'; import { addHeader } from '../../../util/HeaderUtil';
import { LDP, RDF, SOLID_ERROR } from '../../../util/Vocabularies';
import type { AuxiliaryStrategy } from '../../auxiliary/AuxiliaryStrategy'; import type { AuxiliaryStrategy } from '../../auxiliary/AuxiliaryStrategy';
import type { RepresentationMetadata } from '../../representation/RepresentationMetadata'; import type { RepresentationMetadata } from '../../representation/RepresentationMetadata';
import type { ResourceIdentifier } from '../../representation/ResourceIdentifier';
import { MetadataWriter } from './MetadataWriter'; import { MetadataWriter } from './MetadataWriter';
/** /**
@ -30,9 +31,17 @@ export class AuxiliaryLinkMetadataWriter extends MetadataWriter {
} }
public async handle(input: { response: HttpResponse; metadata: RepresentationMetadata }): Promise<void> { public async handle(input: { response: HttpResponse; metadata: RepresentationMetadata }): Promise<void> {
const identifier = { path: input.metadata.identifier.value }; let identifier: ResourceIdentifier | undefined;
if (input.metadata.has(RDF.terms.type, LDP.terms.Resource)) {
identifier = { path: input.metadata.identifier.value };
} else {
const target = input.metadata.get(SOLID_ERROR.terms.target);
if (target) {
identifier = { path: target.value };
}
}
// The metadata identifier will be a blank node in case an error was thrown. // The metadata identifier will be a blank node in case an error was thrown.
if (!this.auxiliaryStrategy.isAuxiliaryIdentifier(identifier) && !Util.isBlankNode(input.metadata.identifier)) { if (identifier && !this.auxiliaryStrategy.isAuxiliaryIdentifier(identifier)) {
const auxiliaryIdentifier = this.specificStrategy.getAuxiliaryIdentifier(identifier); const auxiliaryIdentifier = this.specificStrategy.getAuxiliaryIdentifier(identifier);
addHeader(input.response, 'Link', `<${auxiliaryIdentifier.path}>; rel="${this.relationType}"`); addHeader(input.response, 'Link', `<${auxiliaryIdentifier.path}>; rel="${this.relationType}"`);
} }

View File

@ -3,6 +3,7 @@ import { AuxiliaryLinkMetadataWriter } from '../../../../../src/http/output/meta
import { RepresentationMetadata } from '../../../../../src/http/representation/RepresentationMetadata'; import { RepresentationMetadata } from '../../../../../src/http/representation/RepresentationMetadata';
import type { ResourceIdentifier } from '../../../../../src/http/representation/ResourceIdentifier'; import type { ResourceIdentifier } from '../../../../../src/http/representation/ResourceIdentifier';
import type { HttpResponse } from '../../../../../src/server/HttpResponse'; import type { HttpResponse } from '../../../../../src/server/HttpResponse';
import { LDP, RDF, SOLID_ERROR } from '../../../../../src/util/Vocabularies';
import { SimpleSuffixStrategy } from '../../../../util/SimpleSuffixStrategy'; import { SimpleSuffixStrategy } from '../../../../util/SimpleSuffixStrategy';
describe('A LinkRelMetadataWriter', (): void => { describe('A LinkRelMetadataWriter', (): void => {
@ -18,6 +19,7 @@ describe('A LinkRelMetadataWriter', (): void => {
it('adds the correct link headers.', async(): Promise<void> => { it('adds the correct link headers.', async(): Promise<void> => {
const response = createResponse() as HttpResponse; const response = createResponse() as HttpResponse;
const metadata = new RepresentationMetadata(identifier); const metadata = new RepresentationMetadata(identifier);
metadata.add(RDF.terms.type, LDP.terms.Resource);
await expect(writer.handle({ response, metadata })).resolves.toBeUndefined(); await expect(writer.handle({ response, metadata })).resolves.toBeUndefined();
expect(response.getHeaders()).toEqual({ link: expect(response.getHeaders()).toEqual({ link:
@ -28,12 +30,22 @@ describe('A LinkRelMetadataWriter', (): void => {
const response = createResponse() as HttpResponse; const response = createResponse() as HttpResponse;
identifier.path += '.dummy'; identifier.path += '.dummy';
const metadata = new RepresentationMetadata(identifier); const metadata = new RepresentationMetadata(identifier);
metadata.add(RDF.terms.type, LDP.terms.Resource);
await expect(writer.handle({ response, metadata })).resolves.toBeUndefined(); await expect(writer.handle({ response, metadata })).resolves.toBeUndefined();
expect(response.getHeaders()).toEqual({}); expect(response.getHeaders()).toEqual({});
}); });
it('does not add link headers for blank node identifiers.', async(): Promise<void> => { it('adds link headers for errors.', async(): Promise<void> => {
const response = createResponse() as HttpResponse;
const metadata = new RepresentationMetadata();
metadata.add(SOLID_ERROR.terms.target, identifier.path);
await expect(writer.handle({ response, metadata })).resolves.toBeUndefined();
expect(response.getHeaders()).toEqual({ link:
`<${identifier.path}.meta>; rel="test"` });
});
it('does not add link headers for errors without a target.', async(): Promise<void> => {
const response = createResponse() as HttpResponse; const response = createResponse() as HttpResponse;
const metadata = new RepresentationMetadata(); const metadata = new RepresentationMetadata();
await expect(writer.handle({ response, metadata })).resolves.toBeUndefined(); await expect(writer.handle({ response, metadata })).resolves.toBeUndefined();