Skip to content

Commit

Permalink
Merge pull request nodeSolidServer#1754 from nodeSolidServer/accept-h…
Browse files Browse the repository at this point in the history
…eaders

Accept-Patch Accept-Post Accept-Put headers
  • Loading branch information
bourgeoa authored Feb 6, 2024
2 parents 7c8ccc6 + 4dc7849 commit 7ae2bcc
Show file tree
Hide file tree
Showing 8 changed files with 78 additions and 20 deletions.
2 changes: 1 addition & 1 deletion lib/create-app.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const corsSettings = cors({
methods: [
'OPTIONS', 'HEAD', 'GET', 'PATCH', 'POST', 'PUT', 'DELETE'
],
exposedHeaders: 'Authorization, User, Location, Link, Vary, Last-Modified, ETag, Accept-Patch, Accept-Post, Updates-Via, Allow, WAC-Allow, Content-Length, WWW-Authenticate, MS-Author-Via, X-Powered-By',
exposedHeaders: 'Authorization, User, Location, Link, Vary, Last-Modified, ETag, Accept-Patch, Accept-Post, Accept-Put, Updates-Via, Allow, WAC-Allow, Content-Length, WWW-Authenticate, MS-Author-Via, X-Powered-By',
credentials: true,
maxAge: 1728000,
origin: true,
Expand Down
7 changes: 7 additions & 0 deletions lib/handlers/get.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,13 @@ async function handler (req, res, next) {
const requestedType = negotiator.mediaType()
const possibleRDFType = negotiator.mediaType(RDFs)

// deprecated kept for compatibility
res.header('MS-Author-Via', 'SPARQL')

res.header('Accept-Patch', 'text/n3, application/sparql-update, application/sparql-update-single-match')
res.header('Accept-Post', '*/*')
if (!path.endsWith('/') && !glob.hasMagic(path)) res.header('Accept-Put', '*/*')

// Set live updates
if (ldp.live) {
res.header('Updates-Via', ldp.resourceMapper.resolveUrl(req.hostname).replace(/^http/, 'ws'))
Expand All @@ -49,6 +54,8 @@ async function handler (req, res, next) {
try {
ret = await ldp.get(options, req.accepts(['html', 'turtle', 'rdf+xml', 'n3', 'ld+json']) === 'html')
} catch (err) {
// set Accept-Put if container do not exist
if (err.status === 404 && path.endsWith('/')) res.header('Accept-Put', 'text/turtle')
// use globHandler if magic is detected
if (err.status === 404 && glob.hasMagic(path)) {
debug('forwarding to glob request')
Expand Down
8 changes: 5 additions & 3 deletions lib/handlers/options.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ module.exports = handler
function handler (req, res, next) {
linkServiceEndpoint(req, res)
linkAuthProvider(req, res)
linkSparqlEndpoint(res)
linkAcceptEndpoint(res)

res.status(204)

Expand All @@ -28,6 +28,8 @@ function linkServiceEndpoint (req, res) {
addLink(res, serviceEndpoint, 'service')
}

function linkSparqlEndpoint (res) {
res.header('Accept-Patch', 'application/sparql-update')
function linkAcceptEndpoint (res) {
res.header('Accept-Patch', 'text/n3, application/sparql-update, application/sparql-update-single-match')
res.header('Accept-Post', '*/*')
res.header('Accept-Put', '*/*')
}
3 changes: 1 addition & 2 deletions lib/handlers/patch.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ function contentForNew (contentType) {
// Handles a PATCH request
async function patchHandler (req, res, next) {
debug(`PATCH -- ${req.originalUrl}`)
res.header('MS-Author-Via', 'SPARQL')
try {
// Obtain details of the target resource
const ldp = req.app.locals.ldp
Expand Down Expand Up @@ -77,7 +76,7 @@ async function patchHandler (req, res, next) {
if (!parsePatch) {
throw error(415, `Unsupported patch content type: ${patch.contentType}`)
}

res.header('Accept-Patch', patch.contentType) // is this needed ?
// Parse the patch document and verify permissions
const patchObject = await parsePatch(url, patch.uri, patch.text)
await checkPermission(req, patchObject, resourceExists)
Expand Down
3 changes: 2 additions & 1 deletion lib/handlers/put.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ const { stringToStream } = require('../utils')

async function handler (req, res, next) {
debug(req.originalUrl)
res.header('MS-Author-Via', 'SPARQL')
// deprecated kept for compatibility
res.header('MS-Author-Via', 'SPARQL') // is this needed ?
const contentType = req.get('content-type')

// check whether a folder or resource with same name exists
Expand Down
14 changes: 13 additions & 1 deletion test/integration/header-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ describe('Header handler', () => {
request = supertest(server)
})

describe('MS-Author-Via', () => {
describe('MS-Author-Via', () => { // deprecated
describeHeaderTest('read/append for the public', {
resource: '/public-ra',
headers: {
Expand All @@ -30,6 +30,18 @@ describe('Header handler', () => {
})
})

describe('Accept-* for a resource document', () => {
describeHeaderTest('read/append for the public', {
resource: '/public-ra',
headers: {
'Accept-Patch': 'text/n3, application/sparql-update, application/sparql-update-single-match',
'Accept-Post': '*/*',
'Accept-Put': '*/*',
'Access-Control-Expose-Headers': /(^|,\s*)Accept-Patch, Accept-Post, Accept-Put(,|$)/
}
})
})

describe('WAC-Allow', () => {
describeHeaderTest('read/append for the public', {
resource: '/public-ra',
Expand Down
59 changes: 48 additions & 11 deletions test/integration/http-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,26 +110,32 @@ describe('HTTP APIs', function () {
.expect('Access-Control-Allow-Origin', 'http://example.com')
.expect('Access-Control-Allow-Credentials', 'true')
.expect('Access-Control-Allow-Methods', 'OPTIONS,HEAD,GET,PATCH,POST,PUT,DELETE')
.expect('Access-Control-Expose-Headers', 'Authorization, User, Location, Link, Vary, Last-Modified, ETag, Accept-Patch, Accept-Post, Updates-Via, Allow, WAC-Allow, Content-Length, WWW-Authenticate, MS-Author-Via, X-Powered-By')
.expect('Access-Control-Expose-Headers', 'Authorization, User, Location, Link, Vary, Last-Modified, ETag, Accept-Patch, Accept-Post, Accept-Put, Updates-Via, Allow, WAC-Allow, Content-Length, WWW-Authenticate, MS-Author-Via, X-Powered-By')
.expect(204, done)
})

describe('Accept-Patch header', function () {
describe('Accept-* headers', function () {
it('should be present for resources', function (done) {
server.options('/sampleContainer/example1.ttl')
.expect('Accept-Patch', 'application/sparql-update')
.expect('Accept-Patch', 'text/n3, application/sparql-update, application/sparql-update-single-match')
.expect('Accept-Post', '*/*')
.expect('Accept-Put', '*/*')
.expect(204, done)
})

it('should be present for containers', function (done) {
server.options('/sampleContainer/')
.expect('Accept-Patch', 'application/sparql-update')
.expect('Accept-Patch', 'text/n3, application/sparql-update, application/sparql-update-single-match')
.expect('Accept-Post', '*/*')
.expect('Accept-Put', '*/*')
.expect(204, done)
})

it('should be present for non-rdf resources', function (done) {
server.options('/sampleContainer/solid.png')
.expect('Accept-Patch', 'application/sparql-update')
.expect('Accept-Patch', 'text/n3, application/sparql-update, application/sparql-update-single-match')
.expect('Accept-Post', '*/*')
.expect('Accept-Put', '*/*')
.expect(204, done)
})
})
Expand Down Expand Up @@ -329,6 +335,11 @@ describe('HTTP APIs', function () {
server.get('/invalidfile.foo')
.expect(404, done)
})
it('should return 404 for non-existent container', function (done) { // alain
server.get('/inexistant/')
.expect('Accept-Put', 'text/turtle')
.expect(404, done)
})
it('should return basic container link for directories', function (done) {
server.get('/')
.expect('Link', /http:\/\/www.w3.org\/ns\/ldp#BasicContainer/)
Expand Down Expand Up @@ -411,13 +422,39 @@ describe('HTTP APIs', function () {
.expect('content-type', /text\/turtle/)
.end(done)
})
it('should still redirect to the right container URI if missing / and HTML is requested',
function (done) {
server.get('/sampleContainer')
.set('accept', 'text/html')
.expect('location', /\/sampleContainer\//)
.expect(301, done)
it('should still redirect to the right container URI if missing / and HTML is requested', function (done) {
server.get('/sampleContainer')
.set('accept', 'text/html')
.expect('location', /\/sampleContainer\//)
.expect(301, done)
})

describe('Accept-* headers', function () {
it('should return 404 for non-existent resource', function (done) {
server.get('/invalidfile.foo')
.expect('Accept-Patch', 'text/n3, application/sparql-update, application/sparql-update-single-match')
.expect('Accept-Post', '*/*')
.expect('Accept-put', '*/*')
.expect(404, done)
})
it('Accept-Put=text/turtle for non-existent container', function (done) {
server.get('/inexistant/')
.expect('Accept-Patch', 'text/n3, application/sparql-update, application/sparql-update-single-match')
.expect('Accept-Post', '*/*')
.expect('Accept-Put', 'text/turtle')
.expect(404, done)
})
it('Accept-Put header do not exist for existing container', (done) => {
server.get('/sampleContainer/')
.expect(200)
.expect('Accept-Patch', 'text/n3, application/sparql-update, application/sparql-update-single-match')
.expect('Accept-Post', '*/*')
.expect((res) => {
if (res.headers['Accept-Put']) return done(new Error('Accept-Put header should not exist'))
})
.end(done)
})
})
})

describe('HEAD API', function () {
Expand Down
2 changes: 1 addition & 1 deletion test/integration/patch-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const serverOptions = {
forceUser: `${serverUri}/profile/card#me`
}

describe('PATCH', () => {
describe('PATCH through text/n3', () => {
let request
let server

Expand Down

0 comments on commit 7ae2bcc

Please sign in to comment.