Skip to content

Commit 62e6863

Browse files
committed
Inherit content type from source in COPY handler
1 parent 31860bb commit 62e6863

File tree

2 files changed

+44
-40
lines changed

2 files changed

+44
-40
lines changed

lib/handlers/copy.js

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,16 @@ async function handler (req, res, next) {
2222
const ldp = req.app.locals.ldp
2323
const serverRoot = ldp.resourceMapper.resolveUrl(req.hostname)
2424
const copyFromUrl = fromExternal ? copyFrom : serverRoot + copyFrom
25-
const copyTo = res.locals.path || req.path
26-
const { path: copyToPath } = await ldp.resourceMapper.mapUrlToFile({ url: req })
27-
ldpCopy(copyToPath, copyFromUrl, function (err) {
28-
if (err) {
29-
let statusCode = err.statusCode || 500
30-
let errorMessage = err.statusMessage || err.message
31-
debug.handlers('Error with COPY request:' + errorMessage)
32-
return next(error(statusCode, errorMessage))
33-
}
34-
res.set('Location', copyTo)
35-
res.sendStatus(201)
36-
next()
37-
})
25+
const copyToUrl = res.locals.path || req.path
26+
try {
27+
await ldpCopy(ldp.resourceMapper, copyToUrl, copyFromUrl)
28+
} catch (err) {
29+
let statusCode = err.statusCode || 500
30+
let errorMessage = err.statusMessage || err.message
31+
debug.handlers('Error with COPY request:' + errorMessage)
32+
return next(error(statusCode, errorMessage))
33+
}
34+
res.set('Location', copyToUrl)
35+
res.sendStatus(201)
36+
next()
3837
}

lib/ldp-copy.js

Lines changed: 32 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ module.exports = copy
33
const debug = require('./debug')
44
const fs = require('fs')
55
const mkdirp = require('fs-extra').mkdirp
6+
const error = require('./http-error')
67
const path = require('path')
78
const http = require('http')
89
const https = require('https')
@@ -21,47 +22,51 @@ function cleanupFileStream (stream) {
2122

2223
/**
2324
* Performs an LDP Copy operation, imports a remote resource to a local path.
24-
* @param copyToPath {String} Local path to copy the resource into
25+
* @param resourceMapper {ResourceMapper} A resource mapper instance.
26+
* @param copyToUri {Object} The location (in the current domain) to copy to.
2527
* @param copyFromUri {String} Location of remote resource to copy from
26-
* @param callback {Function} Node error callback
28+
* @return A promise resolving when the copy operation is finished
2729
*/
28-
function copy (copyToPath, copyFromUri, callback) {
29-
mkdirp(path.dirname(copyToPath), function (err) {
30-
if (err) {
31-
debug.handlers('COPY -- Error creating destination directory: ' + err)
32-
return callback(
33-
new Error('Failed to create the path to the destination resource: ' +
34-
err))
35-
}
36-
const destinationStream = fs.createWriteStream(copyToPath)
37-
.on('error', function (err) {
38-
cleanupFileStream(this)
39-
return callback(new Error('Error writing data: ' + err))
40-
})
41-
.on('finish', function () {
42-
// Success
43-
debug.handlers('COPY -- Wrote data to: ' + copyToPath)
44-
callback()
45-
})
30+
function copy (resourceMapper, copyToUri, copyFromUri) {
31+
return new Promise((resolve, reject) => {
4632
const request = /^https:/.test(copyFromUri) ? https : http
4733
request.get(copyFromUri)
4834
.on('error', function (err) {
4935
debug.handlers('COPY -- Error requesting source file: ' + err)
5036
this.end()
51-
cleanupFileStream(destinationStream)
52-
return callback(new Error('Error writing data: ' + err))
37+
return reject(new Error('Error writing data: ' + err))
5338
})
5439
.on('response', function (response) {
5540
if (response.statusCode !== 200) {
56-
debug.handlers('COPY -- HTTP error reading source file: ' +
57-
response.statusMessage)
41+
debug.handlers('COPY -- HTTP error reading source file: ' + response.statusMessage)
5842
this.end()
59-
cleanupFileStream(destinationStream)
6043
let error = new Error('Error reading source file: ' + response.statusMessage)
6144
error.statusCode = response.statusCode
62-
return callback(error)
45+
return reject(error)
6346
}
64-
response.pipe(destinationStream)
47+
// Grab the content type from the source
48+
const contentType = response.headers['content-type']
49+
resourceMapper.mapUrlToFile({ url: copyToUri, createIfNotExists: true, contentType })
50+
.then(({ path: copyToPath }) => {
51+
mkdirp(path.dirname(copyToPath), function (err) {
52+
if (err) {
53+
debug.handlers('COPY -- Error creating destination directory: ' + err)
54+
return reject(new Error('Failed to create the path to the destination resource: ' + err))
55+
}
56+
const destinationStream = fs.createWriteStream(copyToPath)
57+
.on('error', function (err) {
58+
cleanupFileStream(this)
59+
return reject(new Error('Error writing data: ' + err))
60+
})
61+
.on('finish', function () {
62+
// Success
63+
debug.handlers('COPY -- Wrote data to: ' + copyToPath)
64+
resolve()
65+
})
66+
response.pipe(destinationStream)
67+
})
68+
})
69+
.catch(() => reject(error(500, 'Could not find target file to copy')))
6570
})
6671
})
6772
}

0 commit comments

Comments
 (0)