Skip to content

Commit

Permalink
Added the ability to switch to the chunked version of a command (meth…
Browse files Browse the repository at this point in the history
…od) when possible
  • Loading branch information
AdrienCastex committed May 25, 2017
1 parent 6396a81 commit 71c7073
Show file tree
Hide file tree
Showing 7 changed files with 107 additions and 36 deletions.
2 changes: 1 addition & 1 deletion lib/server/MethodCallArgs.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export declare class MethodCallArgs {
host: string;
path: FSPath;
uri: string;
data: string;
data: Int8Array;
user: IUser;
protected constructor(server: WebDAVServer, request: http.IncomingMessage, response: http.ServerResponse, exit: () => void, callback: () => void);
static create(server: WebDAVServer, request: http.IncomingMessage, response: http.ServerResponse, callback: (error: Error, mca: MethodCallArgs) => void): void;
Expand Down
8 changes: 6 additions & 2 deletions lib/server/WebDAVRequest.d.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import MethodCallArgs from './MethodCallArgs';
/// <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;
chunked?: boolean;
startChunked?: (arg: MethodCallArgs, callback: StartChunkedCallback) => void;
}
2 changes: 1 addition & 1 deletion lib/server/WebDAVServer.d.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/// <reference types="node" />
import { MethodCallArgs, WebDAVRequest } from './WebDAVRequest';
import { WebDAVServerOptions } from './WebDAVServerOptions';
import { SerializedObject } from '../manager/ISerializer';
import { MethodCallArgs, WebDAVRequest } from './WebDAVRequest';
import { IResource, ReturnCallback } from '../resource/IResource';
import { HTTPAuthentication } from '../user/authentication/HTTPAuthentication';
import { IPrivilegeManager } from '../user/privilege/IPrivilegeManager';
Expand Down
53 changes: 40 additions & 13 deletions lib/server/WebDAVServer.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var WebDAVRequest_1 = require("./WebDAVRequest");
var WebDAVServerOptions_1 = require("./WebDAVServerOptions");
var ISerializer_1 = require("../manager/ISerializer");
var WebDAVRequest_1 = require("./WebDAVRequest");
var FSManager_1 = require("../manager/FSManager");
var Errors_1 = require("../Errors");
var Commands_1 = require("./commands/Commands");
Expand Down Expand Up @@ -182,32 +182,59 @@ var WebDAVServer = (function () {
res.end();
return;
}
if (!method.chunked) {
var data_1 = '';
base.exit = function () {
base.response.end();
_this.invokeAfterRequest(base, null);
};
if (!_this.options.canChunk || !method.startChunked || base.contentLength <= 0) {
var go_1 = function () {
base.data = data_1;
_this.invokeBeforeRequest(base, function () {
base.exit = function () {
res.end();
_this.invokeAfterRequest(base, null);
};
method(base, base.exit);
});
};
if (base.contentLength === 0) {
if (base.contentLength <= 0) {
base.data = new Buffer(0);
go_1();
}
else {
var data_1 = new Buffer(base.contentLength);
var index_1 = 0;
req.on('data', function (chunk) {
data_1 += chunk.toString();
if (data_1.length >= base.contentLength) {
if (data_1.length > base.contentLength)
data_1 = data_1.substring(0, base.contentLength);
if (chunk.constructor === String)
chunk = new Buffer(chunk);
for (var i = 0; i < chunk.length && index_1 < data_1.length; ++i, ++index_1)
data_1[index_1] = chunk[i];
if (index_1 >= base.contentLength) {
base.data = data_1;
go_1();
}
});
}
}
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);
});
});
});
});
}
});
});
}
Expand Down
2 changes: 1 addition & 1 deletion src/server/MethodCallArgs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export class MethodCallArgs
path : FSPath
uri : string

data : string
data : Int8Array
user : IUser

protected constructor(
Expand Down
8 changes: 6 additions & 2 deletions src/server/WebDAVRequest.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
import { IResource, ReturnCallback } from '../resource/IResource'
import { MethodCallArgs } from './MethodCallArgs'
import { WebDAVServer } from '../server/WebDAVServer'
import { HTTPError } from '../Errors'
import { FSPath } from '../manager/FSManager'
import HTTPCodes from './HTTPCodes'
import MethodCallArgs from './MethodCallArgs'
import * as http from 'http'
import * as url from 'url'

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

chunked ?: boolean
startChunked ?: (arg : MethodCallArgs, callback : StartChunkedCallback) => void
}
68 changes: 52 additions & 16 deletions src/server/WebDAVServer.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
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'
import { IPrivilegeManager } from '../user/privilege/IPrivilegeManager'
import { SimpleUserManager } from '../user/simple/SimpleUserManager'
import { FSManager, FSPath } from '../manager/FSManager'
import { Errors, HTTPError } from '../Errors'
import { RootResource } from '../resource/std/RootResource'
import { IUserManager } from '../user/IUserManager'
import { Errors } from '../Errors'
import Commands from './commands/Commands'
import * as http from 'http'

Expand Down Expand Up @@ -273,39 +273,75 @@ export class WebDAVServer
return;
}

if(!method.chunked)
base.exit = () =>
{
base.response.end();
this.invokeAfterRequest(base, null);
};

if(!this.options.canChunk || !method.startChunked || base.contentLength <= 0)
{
let data = '';
const go = () =>
{
base.data = data;
this.invokeBeforeRequest(base, () => {
base.exit = () =>
{
res.end();
this.invokeAfterRequest(base, null);
};
method(base, base.exit);
})
}
if(base.contentLength === 0)

if(base.contentLength <= 0)
{
base.data = new Buffer(0);
go();
}
else
{
const data = new Buffer(base.contentLength);
let index = 0;
req.on('data', (chunk) => {
data += chunk.toString();
if(data.length >= base.contentLength)
if(chunk.constructor === String)
chunk = new Buffer(chunk as string);

for(let i = 0; i < chunk.length && index < data.length; ++i, ++index)
data[index] = (chunk as Buffer)[i];

if(index >= base.contentLength)
{
if(data.length > base.contentLength)
data = data.substring(0, base.contentLength);
base.data = data;
go();
}
});
}
}
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);
});
});
})
})
}
})
})
}
Expand Down

0 comments on commit 71c7073

Please sign in to comment.