Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions lib/handlers/patch.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,18 @@ var utils = require('../utils.js')
var error = require('../http-error')

function handler (req, res, next) {
req.setEncoding('utf8')
req.text = ''
req.on('data', function (chunk) {
req.text += chunk
})

req.on('end', function () {
patchHandler(req, res, next)
})
}

function patchHandler (req, res, next) {
var ldp = req.app.locals.ldp
debug('PATCH -- ' + req.originalUrl)
debug('PATCH -- text length: ' + (req.text ? req.text.length : 'undefined2'))
Expand Down
80 changes: 55 additions & 25 deletions lib/handlers/post.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
module.exports = handler

var debug = require('../debug').handlers
var Busboy = require('busboy')
var each = require('async').each
var debug = require('debug')('ldnode:post')
var header = require('../header')
var patch = require('./patch')
var error = require('../http-error')
Expand All @@ -12,52 +14,80 @@ function handler (req, res, next) {
// Handle SPARQL(-update?) query
if (contentType === 'application/sparql' ||
contentType === 'application/sparql-update') {
debug('POST -- Handling sparql query via PATCH')
debug('switching to sparql query')
return patch(req, res, next)
}

// Handle container path
var containerPath = req.path
debug('POST -- On parent: ' + containerPath)

// Not a container
if (containerPath[containerPath.length - 1] !== '/') {
containerPath += '/'
}

debug('POST -- Content Type: ' + contentType)

var linkHeader = header.parseMetadataFromHeader(req.get('Link'))

// Check if container exists
ldp.exists(req.hostname, containerPath, function (err, stats) {
if (err) {
return next(error(err, 'Container not valid'))
}

// Check if container is a directory
if (!stats.isDirectory()) {
debug('POST -- Path is not a container')
res.set('Allow', 'GET,HEAD,PUT,DELETE')
debug('path is not a container, 405!')
return next(error(405, 'Requested resource is not a container'))
}

// TODO: possibly package this in ldp.post
ldp.getAvailablePath(req.hostname, containerPath, req.get('Slug'), function (resourcePath) {
debug('POST -- Will create at: ' + resourcePath)
var meta = ''
if (linkHeader.isBasicContainer) {
resourcePath += '/'
meta = ldp.suffixMeta
}
// Dispatch to the right handler
if (contentType === 'multipart/form-data') {
multi(req, res, next)
} else {
one(req, res, next)
}
})

function multi () {
debug('receving multiple files')
var busboy = new Busboy({ headers: req.headers })
var files = []

ldp.put(req.hostname, resourcePath + meta, req.text, function (err) {
busboy.on('file', function (fieldname, file, filename, encoding, mimetype) {
debug('one file received via multipart: ' + filename)
files.push({stream: file, name: filename})
})
busboy.on('finish', function () {
each(
files,
function (file, callback) {
ldp.post(
req.hostname,
containerPath,
file.filename,
file.stream,
false,
callback)
}, function (err) {
debug('done storing files' + (err ? 'with error' + err.message : 'with no error'))
res.sendStatus(err ? 500 : 200)
})
})
}

function one () {
debug('receving one file')
var linkHeader = header.parseMetadataFromHeader(req.get('Link'))
ldp.post(
req.hostname,
containerPath,
req.get('Slug'),
req,
linkHeader.isBasicContainer,
function (err, resourcePath) {
if (err) {
return next(err)
next(err)
}

header.addLinks(res, linkHeader)
res.set('Location', resourcePath)
res.sendStatus(201)
return next()
})
})
})
}
}

11 changes: 6 additions & 5 deletions lib/handlers/put.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
module.exports = handler

var debug = require('../debug').handlers
var debug = require('debug')('ldnode:put')

function handler (req, res, next) {
var ldp = req.app.locals.ldp
debug('PUT -- originalUrl: ' + req.originalUrl)
debug(req.originalUrl)
res.header('MS-Author-Via', 'SPARQL')

ldp.put(req.hostname, req.path, req.text, function (err) {
ldp.put(req.hostname, req.path, req, function (err) {
if (err) {
debug('PUT -- Write error: ' + err.message)
debug('error putting the file:' + err.message)
err.message = 'Can\'t write file: ' + err.message
return next(err)
}

debug('PUT -- Write Ok. Bytes written: ' + req.text.length)
debug('succeded putting the file')

res.sendStatus(201)
return next()
})
}

4 changes: 3 additions & 1 deletion lib/identity-provider.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ var forge = require('node-forge')
var asn1 = forge.asn1
var pki = forge.pki
var parse = require('./utils').parse
var stringToStream = require('./utils').stringToStream

function defaultBuildURI (account, host, port) {
var hostAndPort = (host || 'localhost') + (port || '')
Expand Down Expand Up @@ -51,10 +52,11 @@ IdentityProvider.prototype.putGraph = function (uri, graph) {
var self = this
return function (callback) {
var content = $rdf.serialize(content, graph, uri, 'text/turtle')
var stream = stringToStream(content)
var parsed = url.parse(uri)
var host = parsed.hostname
var path = parsed.path
return self.store.put(host, path, content, callback)
return self.store.put(host, path, stream, callback)
}
}

Expand Down
14 changes: 0 additions & 14 deletions lib/ldp-middleware.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
module.exports = LdpMiddleware

var express = require('express')
var getRawBody = require('raw-body')
var header = require('./header')
var acl = require('./acl')
var login = require('./login')
Expand All @@ -20,19 +19,6 @@ function LdpMiddleware (corsSettings) {
if (corsSettings) {
router.use(corsSettings)
}
router.use('/*', function (req, res, next) {
getRawBody(req, {
length: req.headers['content-length'],
encoding: 'utf-8' // typer.parse(req.headers['content-type']).parameters.charset
},
function (err, string) {
if (err) {
return next(err)
}
req.text = string
next()
})
})

router.use('/*', login.loginHandler)
router.get('/*', acl.allow('Read'), get)
Expand Down
38 changes: 30 additions & 8 deletions lib/ldp.js
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,30 @@ LDP.prototype.listContainer = function (filename, uri, containerData, contentTyp
})
}

LDP.prototype.put = function (host, resourcePath, contents, callback) {
LDP.prototype.post = function (hostname, containerPath, slug, stream, container, callback) {
var ldp = this

debug.handlers('POST -- On parent: ' + containerPath)

// TODO: possibly package this in ldp.post
ldp.getAvailablePath(hostname, containerPath, slug, function (resourcePath) {
debug.handlers('POST -- Will create at: ' + resourcePath)
var meta = ''

if (container) {
resourcePath += '/'
meta = ldp.suffixMeta
}

ldp.put(hostname, resourcePath + meta, stream, function (err) {
if (err) callback(err)

callback(null, resourcePath)
})
})
}

LDP.prototype.put = function (host, resourcePath, stream, callback) {
var ldp = this
var root = !ldp.idp ? ldp.root : ldp.root + host + '/'
var filePath = utils.uriToFilename(resourcePath, root, host)
Expand All @@ -326,13 +349,12 @@ LDP.prototype.put = function (host, resourcePath, contents, callback) {
debug.handlers('PUT -- Error creating directory: ' + err)
return callback(error(err))
}
return fs.writeFile(filePath, contents, function (err) {
if (err) {
debug.handlers('PUT -- Error writing file: ' + err)
return callback(error(err))
}
// Success!
return callback(null)
var file = stream.pipe(fs.createWriteStream(filePath))
file.on('error', function () {
callback(error(500))
})
file.on('finish', function () {
callback(null)
})
})
}
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"dependencies": {
"async": "^1.3.0",
"body-parser": "^1.14.2",
"busboy": "^0.2.12",
"cors": "^2.7.1",
"debug": "^2.2.0",
"express": "^4.13.3",
Expand Down
10 changes: 9 additions & 1 deletion test/http.js
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,15 @@ describe('HTTP APIs', function () {
.set('slug', 'loans')
.set('link', '<http://www.w3.org/ns/ldp#BasicContainer>; rel="type"')
.send(postRequest2Body)
.expect(201, done)
.expect(201)
.end(function (err) {
if (err) return done(err)
var stats = fs.statSync(__dirname + '/resources/loans/')
if (!stats.isDirectory()) {
return done(new Error('Cannot read file just created'))
}
done()
})
})
it('should be able to access container', function (done) {
server.get('/loans')
Expand Down
10 changes: 7 additions & 3 deletions test/ldp.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ var assert = require('chai').assert
var $rdf = require('rdflib')
var ns = require('../lib/vocab/ns.js').ns
var LDP = require('../lib/ldp')
var stringToStream = require('../lib/utils').stringToStream

// Helper functions for the FS
var rm = require('./test-utils').rm
Expand Down Expand Up @@ -68,7 +69,8 @@ describe('LDP', function () {

describe('put', function () {
it('should write a file in an existing dir', function (done) {
ldp.put('localhost', '/resources/testPut.txt', 'hello world', function (err) {
var stream = stringToStream('hello world')
ldp.put('localhost', '/resources/testPut.txt', stream, function (err) {
assert.notOk(err)
var found = read('testPut.txt')
rm('testPut.txt')
Expand All @@ -78,7 +80,8 @@ describe('LDP', function () {
})

it('should fail if a trailing `/` is passed', function (done) {
ldp.put('localhost', '/resources/', 'hello world', function (err) {
var stream = stringToStream('hello world')
ldp.put('localhost', '/resources/', stream, function (err) {
assert.equal(err.status, 409)
done()
})
Expand All @@ -87,7 +90,8 @@ describe('LDP', function () {

describe('delete', function () {
it('should delete a file in an existing dir', function (done) {
ldp.put('localhost', '/resources/testPut.txt', 'hello world', function (err) {
var stream = stringToStream('hello world')
ldp.put('localhost', '/resources/testPut.txt', stream, function (err) {
assert.notOk(err)
fs.stat(ldp.root + '/resources/testPut.txt', function (err) {
if (err) {
Expand Down
9 changes: 1 addition & 8 deletions test/resources/acl/append-acl/abc2.ttl.acl
Original file line number Diff line number Diff line change
@@ -1,8 +1 @@
<#Owner>
<http://www.w3.org/ns/auth/acl#accessTo> <./abc2.ttl>;
<http://www.w3.org/ns/auth/acl#agent> <https://user1.databox.me/profile/card#me>;
<http://www.w3.org/ns/auth/acl#mode> <http://www.w3.org/ns/auth/acl#Read>, <http://www.w3.org/ns/auth/acl#Write>, <http://www.w3.org/ns/auth/acl#Control> .
<#Restricted>
<http://www.w3.org/ns/auth/acl#accessTo> <./abc2.ttl>;
<http://www.w3.org/ns/auth/acl#agent> <https://user2.databox.me/profile/card#me>;
<http://www.w3.org/ns/auth/acl#mode> <http://www.w3.org/ns/auth/acl#Read>, <http://www.w3.org/ns/auth/acl#Write>.
[object Object]
11 changes: 1 addition & 10 deletions test/resources/acl/read-acl/.acl
Original file line number Diff line number Diff line change
@@ -1,10 +1 @@
<#Owner>
a <http://www.w3.org/ns/auth/acl#Authorization> ;
<http://www.w3.org/ns/auth/acl#accessTo> <./>;
<http://www.w3.org/ns/auth/acl#agent> <https://user1.databox.me/profile/card#me>;
<http://www.w3.org/ns/auth/acl#mode> <http://www.w3.org/ns/auth/acl#Read>, <http://www.w3.org/ns/auth/acl#Write>, <http://www.w3.org/ns/auth/acl#Control> .
<#Public>
a <http://www.w3.org/ns/auth/acl#Authorization> ;
<http://www.w3.org/ns/auth/acl#accessTo> <./>;
<http://www.w3.org/ns/auth/acl#agentClass> <http://xmlns.com/foaf/0.1/Agent>;
<http://www.w3.org/ns/auth/acl#mode> <http://www.w3.org/ns/auth/acl#Read> .
[object Object]