Skip to content

Commit 4581242

Browse files
committed
Add storage description link discovery
1 parent 2caddca commit 4581242

2 files changed

Lines changed: 105 additions & 56 deletions

File tree

lib/header.mjs

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@ import debug from './debug.mjs'
55
import { pathBasename } from './utils.mjs'
66
import HTTPError from './http-error.mjs'
77

8-
const MODES = ['Read', 'Write', 'Append', 'Control']
9-
const PERMISSIONS = MODES.map(m => m.toLowerCase())
8+
const MODES = ['Read', 'Write', 'Append', 'Control']
9+
const PERMISSIONS = MODES.map(m => m.toLowerCase())
10+
const STORAGE_DESCRIPTION = 'http://www.w3.org/ns/solid/terms#storageDescription'
11+
const STORAGE_DESCRIPTION_METHODS = ['GET', 'HEAD', 'OPTIONS']
1012

1113
export function addLink (res, value, rel) {
1214
const oldLink = res.get('Link')
@@ -72,13 +74,20 @@ export async function linksHandler (req, res, next) {
7274
if (fileMetadata.isContainer && req.method === 'OPTIONS') {
7375
res.header('Accept-Post', '*/*')
7476
}
75-
// Add ACL and Meta Link in header
76-
addLink(res, pathBasename(req.path) + ldp.suffixAcl, 'acl')
77-
addLink(res, pathBasename(req.path) + ldp.suffixMeta, 'describedBy')
78-
// Add other Link headers
79-
addLinks(res, fileMetadata)
80-
next()
81-
}
77+
// Add ACL and Meta Link in header
78+
addLink(res, pathBasename(req.path) + ldp.suffixAcl, 'acl')
79+
addLink(res, pathBasename(req.path) + ldp.suffixMeta, 'describedBy')
80+
if (STORAGE_DESCRIPTION_METHODS.includes(req.method) && !isAuxiliaryResource(req.path, ldp)) {
81+
addLink(res, ldp.resourceMapper.resolveUrl(req.hostname, '/' + ldp.suffixMeta), STORAGE_DESCRIPTION)
82+
}
83+
// Add other Link headers
84+
addLinks(res, fileMetadata)
85+
next()
86+
}
87+
88+
function isAuxiliaryResource (resourcePath, ldp) {
89+
return resourcePath.endsWith(ldp.suffixAcl) || resourcePath.endsWith(ldp.suffixMeta)
90+
}
8291

8392
export function parseMetadataFromHeader (linkHeader) {
8493
const fileMetadata = new metadata.Metadata()

test/integration/http-test.mjs

Lines changed: 87 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,10 @@ import { assert, expect } from 'chai'
99
const __filename = fileURLToPath(import.meta.url)
1010
const __dirname = path.dirname(__filename)
1111

12-
const suffixAcl = '.acl'
13-
const suffixMeta = '.meta'
14-
const server = setupSupertestServer({
12+
const suffixAcl = '.acl'
13+
const suffixMeta = '.meta'
14+
const storageDescription = 'http://www.w3.org/ns/solid/terms#storageDescription'
15+
const server = setupSupertestServer({
1516
live: true,
1617
dataBrowserPath: 'default',
1718
root: path.join(__dirname, '../resources'),
@@ -162,13 +163,20 @@ describe('HTTP APIs', function () {
162163
.end(done)
163164
})
164165

165-
it('should have set acl and describedBy Links for resource',
166-
function (done) {
167-
server.options('/sampleContainer2/example1.ttl')
168-
.expect(hasHeader('acl', 'example1.ttl' + suffixAcl))
169-
.expect(hasHeader('describedBy', 'example1.ttl' + suffixMeta))
170-
.end(done)
171-
})
166+
it('should have set acl and describedBy Links for resource',
167+
function (done) {
168+
server.options('/sampleContainer2/example1.ttl')
169+
.expect(hasHeader('acl', 'example1.ttl' + suffixAcl))
170+
.expect(hasHeader('describedBy', 'example1.ttl' + suffixMeta))
171+
.end(done)
172+
})
173+
174+
it('should have set storageDescription Link for resource',
175+
function (done) {
176+
server.options('/sampleContainer2/example1.ttl')
177+
.expect(hasHeader(storageDescription, 'https://localhost/' + suffixMeta))
178+
.end(done)
179+
})
172180

173181
it('should have set Link as resource', function (done) {
174182
server.options('/sampleContainer2/example1.ttl')
@@ -198,12 +206,18 @@ describe('HTTP APIs', function () {
198206
.end(done)
199207
})
200208

201-
it('should have set acl and describedBy Links for container', function (done) {
202-
server.options('/sampleContainer2/')
203-
.expect(hasHeader('acl', suffixAcl))
204-
.expect(hasHeader('describedBy', suffixMeta))
205-
.end(done)
206-
})
209+
it('should have set acl and describedBy Links for container', function (done) {
210+
server.options('/sampleContainer2/')
211+
.expect(hasHeader('acl', suffixAcl))
212+
.expect(hasHeader('describedBy', suffixMeta))
213+
.end(done)
214+
})
215+
216+
it('should have set storageDescription Link for container', function (done) {
217+
server.options('/sampleContainer2/')
218+
.expect(hasHeader(storageDescription, 'https://localhost/' + suffixMeta))
219+
.end(done)
220+
})
207221
})
208222

209223
describe('Not allowed method should return 405 and allow header', function (done) {
@@ -265,14 +279,21 @@ describe('HTTP APIs', function () {
265279
.expect('updates-via', /wss?:\/\//)
266280
.expect(200, done)
267281
})
268-
it('should have set acl and describedBy Links for resource',
269-
function (done) {
270-
server.get('/sampleContainer2/example1.ttl')
271-
.expect('content-type', /text\/turtle/)
272-
.expect(hasHeader('acl', 'example1.ttl' + suffixAcl))
273-
.expect(hasHeader('describedBy', 'example1.ttl' + suffixMeta))
274-
.end(done)
275-
})
282+
it('should have set acl and describedBy Links for resource',
283+
function (done) {
284+
server.get('/sampleContainer2/example1.ttl')
285+
.expect('content-type', /text\/turtle/)
286+
.expect(hasHeader('acl', 'example1.ttl' + suffixAcl))
287+
.expect(hasHeader('describedBy', 'example1.ttl' + suffixMeta))
288+
.end(done)
289+
})
290+
it('should have set storageDescription Link for resource',
291+
function (done) {
292+
server.get('/sampleContainer2/example1.ttl')
293+
.expect('content-type', /text\/turtle/)
294+
.expect(hasHeader(storageDescription, 'https://localhost/' + suffixMeta))
295+
.end(done)
296+
})
276297
it('should have set Link as Container/BasicContainer', function (done) {
277298
server.get('/sampleContainer2/')
278299
.expect('content-type', /text\/turtle/)
@@ -383,14 +404,21 @@ describe('HTTP APIs', function () {
383404
})
384405
.end(done)
385406
})
386-
it('should have set acl and describedBy Links for container',
387-
function (done) {
388-
server.get('/sampleContainer2/')
389-
.expect(hasHeader('acl', suffixAcl))
390-
.expect(hasHeader('describedBy', suffixMeta))
391-
.expect('content-type', /text\/turtle/)
392-
.end(done)
393-
})
407+
it('should have set acl and describedBy Links for container',
408+
function (done) {
409+
server.get('/sampleContainer2/')
410+
.expect(hasHeader('acl', suffixAcl))
411+
.expect(hasHeader('describedBy', suffixMeta))
412+
.expect('content-type', /text\/turtle/)
413+
.end(done)
414+
})
415+
it('should have set storageDescription Link for container',
416+
function (done) {
417+
server.get('/sampleContainer2/')
418+
.expect(hasHeader(storageDescription, 'https://localhost/' + suffixMeta))
419+
.expect('content-type', /text\/turtle/)
420+
.end(done)
421+
})
394422
it('should return requested index.html resource by default', function (done) {
395423
server.get('/sampleContainer/index.html')
396424
.set('accept', 'text/html')
@@ -510,13 +538,19 @@ describe('HTTP APIs', function () {
510538
.expect('Link', /<http:\/\/www.w3.org\/ns\/ldp#Resource>; rel="type"/)
511539
.expect(200, done)
512540
})
513-
it('should have set acl and describedBy Links for resource',
514-
function (done) {
515-
server.head('/sampleContainer2/example1.ttl')
516-
.expect(hasHeader('acl', 'example1.ttl' + suffixAcl))
517-
.expect(hasHeader('describedBy', 'example1.ttl' + suffixMeta))
518-
.end(done)
519-
})
541+
it('should have set acl and describedBy Links for resource',
542+
function (done) {
543+
server.head('/sampleContainer2/example1.ttl')
544+
.expect(hasHeader('acl', 'example1.ttl' + suffixAcl))
545+
.expect(hasHeader('describedBy', 'example1.ttl' + suffixMeta))
546+
.end(done)
547+
})
548+
it('should have set storageDescription Link for resource',
549+
function (done) {
550+
server.head('/sampleContainer2/example1.ttl')
551+
.expect(hasHeader(storageDescription, 'https://localhost/' + suffixMeta))
552+
.end(done)
553+
})
520554
it('should have set Content-Type as text/turtle for Container',
521555
function (done) {
522556
server.head('/sampleContainer2/')
@@ -530,14 +564,20 @@ describe('HTTP APIs', function () {
530564
.expect('Link', /<http:\/\/www.w3.org\/ns\/ldp#Container>; rel="type"/)
531565
.expect(200, done)
532566
})
533-
it('should have set acl and describedBy Links for container',
534-
function (done) {
535-
server.head('/sampleContainer2/')
536-
.expect(hasHeader('acl', suffixAcl))
537-
.expect(hasHeader('describedBy', suffixMeta))
538-
.end(done)
539-
})
540-
})
567+
it('should have set acl and describedBy Links for container',
568+
function (done) {
569+
server.head('/sampleContainer2/')
570+
.expect(hasHeader('acl', suffixAcl))
571+
.expect(hasHeader('describedBy', suffixMeta))
572+
.end(done)
573+
})
574+
it('should have set storageDescription Link for container',
575+
function (done) {
576+
server.head('/sampleContainer2/')
577+
.expect(hasHeader(storageDescription, 'https://localhost/' + suffixMeta))
578+
.end(done)
579+
})
580+
})
541581

542582
describe('PUT API', function () {
543583
const putRequestBody = fs.readFileSync(path.join(__dirname,

0 commit comments

Comments
 (0)