Skip to content

Commit

Permalink
Implemented the new chunked version of the PUT method
Browse files Browse the repository at this point in the history
  • Loading branch information
AdrienCastex committed Jun 4, 2017
1 parent a322b75 commit 7f605b1
Show file tree
Hide file tree
Showing 9 changed files with 150 additions and 93 deletions.
6 changes: 1 addition & 5 deletions lib/server/WebDAVRequest.d.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
/// <reference types="node" />
import { MethodCallArgs } from './MethodCallArgs';
import { HTTPError } from '../Errors';
export { MethodCallArgs } from './MethodCallArgs';
export { HTTPCodes } from './HTTPCodes';
export declare type ChunkOnDataCallback = (chunk: Buffer, isFirst: boolean, isLast: boolean) => void;
export declare type StartChunkedCallback = (error: HTTPError, onData: ChunkOnDataCallback) => void;
export interface WebDAVRequest {
(arg: MethodCallArgs, callback: () => void): void;
startChunked?: (arg: MethodCallArgs, callback: StartChunkedCallback) => void;
chunked?: (arg: MethodCallArgs, callback: () => void) => void;
}
85 changes: 85 additions & 0 deletions lib/server/commands/Put.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,3 +120,88 @@ function unchunkedMethod(arg, callback) {
});
}
exports.default = unchunkedMethod;
unchunkedMethod.chunked = function (arg, callback) {
var targetSource = arg.findHeader('source', 'F').toUpperCase() === 'T';
arg.getResource(function (e, r) {
if (e && e !== Errors_1.Errors.ResourceNotFound) {
arg.setCode(WebDAVRequest_1.HTTPCodes.InternalServerError);
callback();
return;
}
arg.checkIfHeader(r, function () {
if (arg.contentLength === 0) {
if (r) {
arg.requirePrivilege(targetSource ? ['canSource', 'canWrite'] : ['canWrite'], r, function () {
r.write(targetSource, function (e, stream) { return process.nextTick(function () {
if (stream)
stream.end();
if (e)
arg.setCode(WebDAVRequest_1.HTTPCodes.InternalServerError);
else
arg.setCode(WebDAVRequest_1.HTTPCodes.OK);
callback();
}); });
});
return;
}
createResource(arg, callback, function (r) {
arg.setCode(WebDAVRequest_1.HTTPCodes.OK);
callback();
});
}
else {
if (e) {
createResource(arg, callback, function (r) {
r.write(targetSource, function (e, stream) { return process.nextTick(function () {
if (e) {
arg.setCode(WebDAVRequest_1.HTTPCodes.InternalServerError);
callback();
return;
}
arg.request.pipe(stream);
stream.on('finish', function (e) {
arg.setCode(WebDAVRequest_1.HTTPCodes.OK);
callback();
});
stream.on('error', function (e) {
arg.setCode(WebDAVRequest_1.HTTPCodes.InternalServerError);
callback();
});
}); });
});
return;
}
arg.requirePrivilege(targetSource ? ['canSource', 'canWrite'] : ['canWrite'], r, function () {
r.type(function (e, type) { return process.nextTick(function () {
if (e) {
arg.setCode(WebDAVRequest_1.HTTPCodes.InternalServerError);
callback();
return;
}
if (!type.isFile) {
arg.setCode(WebDAVRequest_1.HTTPCodes.MethodNotAllowed);
callback();
return;
}
r.write(targetSource, function (e, stream) { return process.nextTick(function () {
if (e) {
arg.setCode(WebDAVRequest_1.HTTPCodes.InternalServerError);
callback();
return;
}
arg.request.pipe(stream);
stream.on('finish', function (e) {
arg.setCode(WebDAVRequest_1.HTTPCodes.OK);
callback();
});
stream.on('error', function (e) {
arg.setCode(WebDAVRequest_1.HTTPCodes.InternalServerError);
callback();
});
}); });
}); });
});
}
});
});
};
23 changes: 2 additions & 21 deletions lib/server/webDAVServer/StartStop.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ function start(port, callback) {
base.response.end();
_this.invokeAfterRequest(base, null);
};
if (!_this.options.canChunk || !method.startChunked || base.contentLength <= 0) {
if (!_this.options.canChunk || !method.chunked || base.contentLength <= 0) {
var go_1 = function () {
_this.invokeBeforeRequest(base, function () {
method(base, base.exit);
Expand All @@ -67,26 +67,7 @@ function start(port, callback) {
}
else {
_this.invokeBeforeRequest(base, function () {
_this.invokeBeforeRequest(base, function () {
method.startChunked(base, function (error, onData) {
if (error) {
base.setCode(error.HTTPCode);
base.exit();
return;
}
if (!onData) {
base.exit();
return;
}
var size = 0;
req.on('data', function (chunk) {
if (chunk.constructor === String)
chunk = new Buffer(chunk);
size += chunk.length;
onData(chunk, size === chunk.length, size >= base.contentLength);
});
});
});
method.chunked(base, base.exit);
});
}
});
Expand Down
2 changes: 1 addition & 1 deletion lib/server/webDAVServer/WebDAVServer.d.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/// <reference types="node" />
import { WebDAVRequest } from '../WebDAVRequest';
import { WebDAVServerOptions } from '../WebDAVServerOptions';
import { ResourceTreeNode, WebDAVServerStartCallback } from './Types';
import { WebDAVRequest } from '../WebDAVRequest';
import { IResource, ReturnCallback } from '../../resource/IResource';
import { HTTPAuthentication } from '../../user/authentication/HTTPAuthentication';
import { IPrivilegeManager } from '../../user/privilege/IPrivilegeManager';
Expand Down
5 changes: 1 addition & 4 deletions src/server/WebDAVRequest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,9 @@ import { HTTPError } from '../Errors'
export { MethodCallArgs } from './MethodCallArgs'
export { HTTPCodes } from './HTTPCodes'

export type ChunkOnDataCallback = (chunk : Buffer, isFirst : boolean, isLast : boolean) => void
export type StartChunkedCallback = (error : HTTPError, onData : ChunkOnDataCallback) => void

export interface WebDAVRequest
{
(arg : MethodCallArgs, callback : () => void) : void

startChunked ?: (arg : MethodCallArgs, callback : StartChunkedCallback) => void
chunked ?: (arg : MethodCallArgs, callback : () => void) => void
}
88 changes: 55 additions & 33 deletions src/server/commands/Put.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { HTTPCodes, MethodCallArgs, WebDAVRequest, StartChunkedCallback } from '../WebDAVRequest'
import { HTTPCodes, MethodCallArgs, WebDAVRequest } from '../WebDAVRequest'
import { IResource, ResourceType } from '../../resource/IResource'
import { Errors, HTTPError } from '../../Errors'
import * as path from 'path'
Expand Down Expand Up @@ -145,38 +145,16 @@ export default function unchunkedMethod(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)
(unchunkedMethod as WebDAVRequest).chunked = function(arg : MethodCallArgs, callback)
{
const targetSource = arg.findHeader('source', 'F').toUpperCase() === 'T';

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

Expand All @@ -186,22 +164,48 @@ function asyncWrite(arg : MethodCallArgs, callback : StartChunkedCallback, resou
if(r)
{ // Resource exists => empty it
arg.requirePrivilege(targetSource ? [ 'canSource', 'canWrite' ] : [ 'canWrite' ], r, () => {
asyncWrite(arg, callback, r, targetSource);
r.write(targetSource, (e, stream) => process.nextTick(() => {
if(stream)
stream.end();

if(e)
arg.setCode(HTTPCodes.InternalServerError)
else
arg.setCode(HTTPCodes.OK)
callback()
}))
})
return;
}

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

arg.request.pipe(stream);
stream.on('finish', (e) => {
arg.setCode(HTTPCodes.OK)
callback();
});
stream.on('error', (e) => {
arg.setCode(HTTPCodes.InternalServerError)
callback();
});
}))
})
return;
}
Expand All @@ -210,20 +214,38 @@ function asyncWrite(arg : MethodCallArgs, callback : StartChunkedCallback, resou
r.type((e, type) => process.nextTick(() => {
if(e)
{
callback(new HTTPError(HTTPCodes.InternalServerError, e), null);
arg.setCode(HTTPCodes.InternalServerError);
callback();
return;
}
if(!type.isFile)
{
callback(new HTTPError(HTTPCodes.MethodNotAllowed, Errors.ExpectedAFileResourceType), null);
arg.setCode(HTTPCodes.MethodNotAllowed);
callback();
return;
}

asyncWrite(arg, callback, r, targetSource);
r.write(targetSource, (e, stream) => process.nextTick(() => {
if(e)
{
arg.setCode(HTTPCodes.InternalServerError);
callback();
return;
}

arg.request.pipe(stream);
stream.on('finish', (e) => {
arg.setCode(HTTPCodes.OK)
callback();
});
stream.on('error', (e) => {
arg.setCode(HTTPCodes.InternalServerError)
callback();
});
}))
}))
})
}
})
})
}
*/
30 changes: 3 additions & 27 deletions src/server/webDAVServer/StartStop.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { HTTPCodes, MethodCallArgs, WebDAVRequest, ChunkOnDataCallback } from '../WebDAVRequest'
import { HTTPCodes, MethodCallArgs, WebDAVRequest } from '../WebDAVRequest'
import { WebDAVServerStartCallback } from './Types'
import { Errors, HTTPError } from '../../Errors'
import * as http from 'http'
Expand Down Expand Up @@ -52,7 +52,7 @@ export function start(port ?: number | WebDAVServerStartCallback, callback ?: We
this.invokeAfterRequest(base, null);
};

if(!this.options.canChunk || !method.startChunked || base.contentLength <= 0)
if(!this.options.canChunk || !method.chunked || base.contentLength <= 0)
{
const go = () =>
{
Expand Down Expand Up @@ -88,31 +88,7 @@ export function start(port ?: number | WebDAVServerStartCallback, callback ?: We
else
{
this.invokeBeforeRequest(base, () => {
this.invokeBeforeRequest(base, () => {
method.startChunked(base, (error : HTTPError, onData : ChunkOnDataCallback) => {
if(error)
{
base.setCode(error.HTTPCode);
base.exit();
return;
}

if(!onData)
{
base.exit();
return;
}

let size = 0;
req.on('data', (chunk) => {
if(chunk.constructor === String)
chunk = new Buffer(chunk as string);
size += chunk.length;

onData(chunk as Buffer, size === chunk.length, size >= base.contentLength);
});
});
})
method.chunked(base, base.exit);
})
}
})
Expand Down
2 changes: 1 addition & 1 deletion src/server/webDAVServer/Types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { HTTPCodes, MethodCallArgs, WebDAVRequest, ChunkOnDataCallback } from '../WebDAVRequest'
import { WebDAVServerOptions, setDefaultServerOptions } from '../WebDAVServerOptions'
import { SerializedObject, unserialize, serialize } from '../../manager/ISerializer'
import { HTTPCodes, MethodCallArgs, WebDAVRequest } from '../WebDAVRequest'
import { IResource, ReturnCallback } from '../../resource/IResource'
import { FakePrivilegeManager } from '../../user/privilege/FakePrivilegeManager'
import { HTTPAuthentication } from '../../user/authentication/HTTPAuthentication'
Expand Down
2 changes: 1 addition & 1 deletion src/server/webDAVServer/WebDAVServer.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { HTTPCodes, MethodCallArgs, WebDAVRequest, ChunkOnDataCallback } from '../WebDAVRequest'
import { WebDAVServerOptions, setDefaultServerOptions } from '../WebDAVServerOptions'
import { ResourceTreeNode, WebDAVServerStartCallback } from './Types'
import { HTTPCodes, MethodCallArgs, WebDAVRequest } from '../WebDAVRequest'
import { IResource, ReturnCallback } from '../../resource/IResource'
import { HTTPAuthentication } from '../../user/authentication/HTTPAuthentication'
import { IPrivilegeManager } from '../../user/privilege/IPrivilegeManager'
Expand Down

0 comments on commit 7f605b1

Please sign in to comment.