diff --git a/config/ldp/metadata-parser/default.json b/config/ldp/metadata-parser/default.json index b6e66735c..818a76ec5 100644 --- a/config/ldp/metadata-parser/default.json +++ b/config/ldp/metadata-parser/default.json @@ -1,14 +1,19 @@ { "@context": "https://linkedsoftwaredependencies.org/bundles/npm/@solid/community-server/^1.0.0/components/context.jsonld", + "import": [ + "files-scs:config/ldp/metadata-parser/parsers/content-type.json", + "files-scs:config/ldp/metadata-parser/parsers/slug.json", + "files-scs:config/ldp/metadata-parser/parsers/link.json" + ], "@graph": [ { "comment": "Converts request metadata (e.g. headers) to RDF metadata.", "@id": "urn:solid-server:default:MetadataParser", "@type": "ParallelHandler", "handlers": [ - { "@type": "ContentTypeParser" }, - { "@type": "LinkTypeParser" }, - { "@type": "SlugParser" } + { "@id": "urn:solid-server:default:ContentTypeParser" }, + { "@id": "urn:solid-server:default:SlugParser" }, + { "@id": "urn:solid-server:default:LinkRelParser" } ] } ] diff --git a/config/ldp/metadata-parser/parsers/content-type.json b/config/ldp/metadata-parser/parsers/content-type.json new file mode 100644 index 000000000..8c3963d1b --- /dev/null +++ b/config/ldp/metadata-parser/parsers/content-type.json @@ -0,0 +1,10 @@ +{ + "@context": "https://linkedsoftwaredependencies.org/bundles/npm/@solid/community-server/^1.0.0/components/context.jsonld", + "@graph": [ + { + "comment": "Converts content-type headers into RDF metadata.", + "@id": "urn:solid-server:default:ContentTypeParser", + "@type": "ContentTypeParser" + } + ] +} diff --git a/config/ldp/metadata-parser/parsers/link.json b/config/ldp/metadata-parser/parsers/link.json new file mode 100644 index 000000000..64c6abd9c --- /dev/null +++ b/config/ldp/metadata-parser/parsers/link.json @@ -0,0 +1,20 @@ +{ + "@context": "https://linkedsoftwaredependencies.org/bundles/npm/@solid/community-server/^1.0.0/components/context.jsonld", + "@graph": [ + { + "comment": "Converts link headers into RDF metadata.", + "@id": "urn:solid-server:default:LinkRelParser", + "@type": "LinkRelParser", + "linkRelMap": [ + { + "LinkRelParser:_linkRelMap_key": "type", + "LinkRelParser:_linkRelMap_value": "http://www.w3.org/1999/02/22-rdf-syntax-ns#type" + }, + { + "LinkRelParser:_linkRelMap_key": "http://www.w3.org/ns/ldp#inbox", + "LinkRelParser:_linkRelMap_value": "http://www.w3.org/ns/ldp#inbox" + } + ] + } + ] +} diff --git a/config/ldp/metadata-parser/parsers/slug.json b/config/ldp/metadata-parser/parsers/slug.json new file mode 100644 index 000000000..9c983b4dc --- /dev/null +++ b/config/ldp/metadata-parser/parsers/slug.json @@ -0,0 +1,10 @@ +{ + "@context": "https://linkedsoftwaredependencies.org/bundles/npm/@solid/community-server/^1.0.0/components/context.jsonld", + "@graph": [ + { + "comment": "Converts slug headers into RDF metadata.", + "@id": "urn:solid-server:default:SlugParser", + "@type": "SlugParser" + } + ] +} diff --git a/config/ldp/metadata-writer/writers/link-rel.json b/config/ldp/metadata-writer/writers/link-rel.json index bd21fbe1a..55452dd3e 100644 --- a/config/ldp/metadata-writer/writers/link-rel.json +++ b/config/ldp/metadata-writer/writers/link-rel.json @@ -13,6 +13,10 @@ { "LinkRelMetadataWriter:_linkRelMap_key": "http://www.w3.org/ns/auth/acl#accessControl", "LinkRelMetadataWriter:_linkRelMap_value": "acl" + }, + { + "LinkRelMetadataWriter:_linkRelMap_key": "http://www.w3.org/ns/ldp#inbox", + "LinkRelMetadataWriter:_linkRelMap_value": "http://www.w3.org/ns/ldp#inbox" } ] } diff --git a/src/index.ts b/src/index.ts index 3994f8c37..9d9f0b39a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -97,7 +97,7 @@ export * from './ldp/http/conditions/ConditionsParser'; export * from './ldp/http/metadata/ConstantMetadataWriter'; export * from './ldp/http/metadata/ContentTypeParser'; export * from './ldp/http/metadata/LinkRelMetadataWriter'; -export * from './ldp/http/metadata/LinkTypeParser'; +export * from './ldp/http/metadata/LinkRelParser'; export * from './ldp/http/metadata/MappedMetadataWriter'; export * from './ldp/http/metadata/MetadataParser'; export * from './ldp/http/metadata/MetadataWriter'; diff --git a/src/ldp/http/metadata/LinkTypeParser.ts b/src/ldp/http/metadata/LinkRelParser.ts similarity index 65% rename from src/ldp/http/metadata/LinkTypeParser.ts rename to src/ldp/http/metadata/LinkRelParser.ts index cc71c7920..c2b6bf397 100644 --- a/src/ldp/http/metadata/LinkTypeParser.ts +++ b/src/ldp/http/metadata/LinkRelParser.ts @@ -1,17 +1,27 @@ +import type { NamedNode } from '@rdfjs/types'; import { DataFactory } from 'n3'; import { getLoggerFor } from '../../../logging/LogUtil'; import type { HttpRequest } from '../../../server/HttpRequest'; import { parseParameters, splitAndClean, transformQuotedStrings } from '../../../util/HeaderUtil'; -import { RDF } from '../../../util/Vocabularies'; import type { RepresentationMetadata } from '../../representation/RepresentationMetadata'; import { MetadataParser } from './MetadataParser'; +import namedNode = DataFactory.namedNode; /** - * Parses Link headers with "rel=type" parameters and adds them as RDF.type metadata. + * Parses Link headers with a specific `rel` value and adds them as metadata with the given predicate. */ -export class LinkTypeParser extends MetadataParser { +export class LinkRelParser extends MetadataParser { protected readonly logger = getLoggerFor(this); + private readonly linkRelMap: Record; + + public constructor(linkRelMap: Record) { + super(); + this.linkRelMap = Object.fromEntries( + Object.entries(linkRelMap).map(([ header, uri ]): [string, NamedNode] => [ header, namedNode(uri) ]), + ); + } + public async handle(input: { request: HttpRequest; metadata: RepresentationMetadata }): Promise { const link = input.request.headers.link ?? []; const entries: string[] = Array.isArray(link) ? link : [ link ]; @@ -29,8 +39,8 @@ export class LinkTypeParser extends MetadataParser { continue; } for (const { name, value } of parseParameters(parameters, replacements)) { - if (name === 'rel' && value === 'type') { - metadata.add(RDF.type, DataFactory.namedNode(link.slice(1, -1))); + if (name === 'rel' && this.linkRelMap[value]) { + metadata.add(this.linkRelMap[value], namedNode(link.slice(1, -1))); } } } diff --git a/test/unit/ldp/http/metadata/LinkTypeParser.test.ts b/test/unit/ldp/http/metadata/LinkParser.test.ts similarity index 87% rename from test/unit/ldp/http/metadata/LinkTypeParser.test.ts rename to test/unit/ldp/http/metadata/LinkParser.test.ts index 0001aa42b..0c0192433 100644 --- a/test/unit/ldp/http/metadata/LinkTypeParser.test.ts +++ b/test/unit/ldp/http/metadata/LinkParser.test.ts @@ -1,10 +1,10 @@ -import { LinkTypeParser } from '../../../../../src/ldp/http/metadata/LinkTypeParser'; +import { LinkRelParser } from '../../../../../src/ldp/http/metadata/LinkRelParser'; import { RepresentationMetadata } from '../../../../../src/ldp/representation/RepresentationMetadata'; import type { HttpRequest } from '../../../../../src/server/HttpRequest'; import { RDF } from '../../../../../src/util/Vocabularies'; -describe('A LinkTypeParser', (): void => { - const parser = new LinkTypeParser(); +describe('A LinkParser', (): void => { + const parser = new LinkRelParser({ type: 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type' }); let request: HttpRequest; let metadata: RepresentationMetadata; @@ -18,7 +18,7 @@ describe('A LinkTypeParser', (): void => { expect(metadata.quads()).toHaveLength(0); }); - it('stores link headers with rel = type as metadata.', async(): Promise => { + it('stores link headers with rel matching the given value as metadata.', async(): Promise => { request.headers.link = ';rel="type"'; await expect(parser.handle({ request, metadata })).resolves.toBeUndefined(); expect(metadata.quads()).toHaveLength(1);