Skip to content

Commit

Permalink
Implemented the chunked version of the PUT method
Browse files Browse the repository at this point in the history
  • Loading branch information
AdrienCastex committed May 25, 2017
1 parent 7e942c2 commit 5923925
Show file tree
Hide file tree
Showing 3 changed files with 149 additions and 6 deletions.
2 changes: 1 addition & 1 deletion lib/server/commands/Put.d.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
import { MethodCallArgs } from '../WebDAVRequest';
export default function (arg: MethodCallArgs, callback: any): void;
export default function unchunkedMethod(arg: MethodCallArgs, callback: any): void;
66 changes: 64 additions & 2 deletions lib/server/commands/Put.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ function createResource(arg, callback, validCallback) {
});
});
}
function default_1(arg, callback) {
function unchunkedMethod(arg, callback) {
var targetSource = arg.findHeader('source', 'F').toUpperCase() === 'T';
arg.getResource(function (e, r) {
if (e && e !== Errors_1.Errors.ResourceNotFound) {
Expand Down Expand Up @@ -104,4 +104,66 @@ function default_1(arg, callback) {
});
});
}
exports.default = default_1;
exports.default = unchunkedMethod;
function asyncWrite(arg, callback, resource, targetSource) {
function errorCallback(isLast) {
return function (error) {
if (error)
callback(new Errors_1.HTTPError(WebDAVRequest_1.HTTPCodes.InternalServerError, error), null);
else if (isLast) {
arg.setCode(WebDAVRequest_1.HTTPCodes.OK);
arg.exit();
}
};
}
callback(null, function (data, isFirst, isLast) {
if (isFirst)
resource.write(data, targetSource, errorCallback(isLast));
else
resource.append(data, targetSource, errorCallback(isLast));
});
}
unchunkedMethod.startChunked = function (arg, callback) {
var targetSource = arg.findHeader('source', 'F').toUpperCase() === 'T';
arg.getResource(function (e, r) {
if (e && e !== Errors_1.Errors.ResourceNotFound) {
callback(new Errors_1.HTTPError(WebDAVRequest_1.HTTPCodes.InternalServerError, e), null);
return;
}
arg.checkIfHeader(r, function () {
if (arg.contentLength === 0) {
if (r) {
arg.requirePrivilege(targetSource ? ['canSource', 'canWrite'] : ['canWrite'], r, function () {
asyncWrite(arg, callback, r, targetSource);
});
return;
}
createResource(arg, callback, function (r) {
arg.setCode(WebDAVRequest_1.HTTPCodes.OK);
callback(null, null);
});
}
else {
if (e) {
createResource(arg, callback, function (r) {
asyncWrite(arg, callback, r, targetSource);
});
return;
}
arg.requirePrivilege(targetSource ? ['canSource', 'canWrite'] : ['canWrite'], r, function () {
r.type(function (e, type) { return process.nextTick(function () {
if (e) {
callback(new Errors_1.HTTPError(WebDAVRequest_1.HTTPCodes.InternalServerError, e), null);
return;
}
if (!type.isFile) {
callback(new Errors_1.HTTPError(WebDAVRequest_1.HTTPCodes.MethodNotAllowed, Errors_1.Errors.ExpectedAFileResourceType), null);
return;
}
asyncWrite(arg, callback, r, targetSource);
}); });
});
}
});
});
};
87 changes: 84 additions & 3 deletions src/server/commands/Put.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { HTTPCodes, MethodCallArgs, WebDAVRequest } from '../WebDAVRequest'
import { HTTPCodes, MethodCallArgs, WebDAVRequest, StartChunkedCallback } from '../WebDAVRequest'
import { IResource, ResourceType } from '../../resource/IResource'
import { Errors } from '../../Errors'
import { Errors, HTTPError } from '../../Errors'
import * as path from 'path'

function createResource(arg : MethodCallArgs, callback, validCallback : (resource : IResource) => void)
Expand Down Expand Up @@ -46,7 +46,7 @@ function createResource(arg : MethodCallArgs, callback, validCallback : (resourc
})
}

export default function(arg : MethodCallArgs, callback)
export default function unchunkedMethod(arg : MethodCallArgs, callback)
{
const targetSource = arg.findHeader('source', 'F').toUpperCase() === 'T';

Expand Down Expand Up @@ -126,3 +126,84 @@ export default function(arg : MethodCallArgs, callback)
})
})
}

function asyncWrite(arg : MethodCallArgs, callback : StartChunkedCallback, resource : IResource, targetSource : boolean)
{
function errorCallback(isLast : boolean)
{
return (error : Error) => {
if(error)
callback(new HTTPError(HTTPCodes.InternalServerError, error), null)
else if(isLast)
{
arg.setCode(HTTPCodes.OK);
arg.exit();
}
}
}

callback(null, (data, isFirst, isLast) => {
if(isFirst)
resource.write(data, targetSource, errorCallback(isLast))
else
resource.append(data, targetSource, errorCallback(isLast))
})
}

(unchunkedMethod as WebDAVRequest).startChunked = function(arg : MethodCallArgs, callback : StartChunkedCallback)
{
const targetSource = arg.findHeader('source', 'F').toUpperCase() === 'T';

arg.getResource((e, r) => {
if(e && e !== Errors.ResourceNotFound)
{
callback(new HTTPError(HTTPCodes.InternalServerError, e), null);
return;
}

arg.checkIfHeader(r, () => {
if(arg.contentLength === 0)
{ // Create file
if(r)
{ // Resource exists => empty it
arg.requirePrivilege(targetSource ? [ 'canSource', 'canWrite' ] : [ 'canWrite' ], r, () => {
asyncWrite(arg, callback, r, targetSource);
})
return;
}

createResource(arg, callback, (r) => {
arg.setCode(HTTPCodes.OK)
callback(null, null);
})
}
else
{ // Write to a file
if(e)
{ // Resource not found
createResource(arg, callback, (r) => {
asyncWrite(arg, callback, r, targetSource);
})
return;
}

arg.requirePrivilege(targetSource ? [ 'canSource', 'canWrite' ] : [ 'canWrite' ], r, () => {
r.type((e, type) => process.nextTick(() => {
if(e)
{
callback(new HTTPError(HTTPCodes.InternalServerError, e), null);
return;
}
if(!type.isFile)
{
callback(new HTTPError(HTTPCodes.MethodNotAllowed, Errors.ExpectedAFileResourceType), null);
return;
}

asyncWrite(arg, callback, r, targetSource);
}))
})
}
})
})
}

0 comments on commit 5923925

Please sign in to comment.