Skip to content

Commit 71c7073

Browse files
committed
Added the ability to switch to the chunked version of a command (method) when possible
1 parent 6396a81 commit 71c7073

File tree

7 files changed

+107
-36
lines changed

7 files changed

+107
-36
lines changed

lib/server/MethodCallArgs.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ export declare class MethodCallArgs {
1717
host: string;
1818
path: FSPath;
1919
uri: string;
20-
data: string;
20+
data: Int8Array;
2121
user: IUser;
2222
protected constructor(server: WebDAVServer, request: http.IncomingMessage, response: http.ServerResponse, exit: () => void, callback: () => void);
2323
static create(server: WebDAVServer, request: http.IncomingMessage, response: http.ServerResponse, callback: (error: Error, mca: MethodCallArgs) => void): void;

lib/server/WebDAVRequest.d.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
1-
import MethodCallArgs from './MethodCallArgs';
1+
/// <reference types="node" />
2+
import { MethodCallArgs } from './MethodCallArgs';
3+
import { HTTPError } from '../Errors';
24
export { MethodCallArgs } from './MethodCallArgs';
35
export { HTTPCodes } from './HTTPCodes';
6+
export declare type ChunkOnDataCallback = (chunk: Buffer, isFirst: boolean, isLast: boolean) => void;
7+
export declare type StartChunkedCallback = (error: HTTPError, onData: ChunkOnDataCallback) => void;
48
export interface WebDAVRequest {
59
(arg: MethodCallArgs, callback: () => void): void;
6-
chunked?: boolean;
10+
startChunked?: (arg: MethodCallArgs, callback: StartChunkedCallback) => void;
711
}

lib/server/WebDAVServer.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/// <reference types="node" />
2+
import { MethodCallArgs, WebDAVRequest } from './WebDAVRequest';
23
import { WebDAVServerOptions } from './WebDAVServerOptions';
34
import { SerializedObject } from '../manager/ISerializer';
4-
import { MethodCallArgs, WebDAVRequest } from './WebDAVRequest';
55
import { IResource, ReturnCallback } from '../resource/IResource';
66
import { HTTPAuthentication } from '../user/authentication/HTTPAuthentication';
77
import { IPrivilegeManager } from '../user/privilege/IPrivilegeManager';

lib/server/WebDAVServer.js

Lines changed: 40 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
"use strict";
22
Object.defineProperty(exports, "__esModule", { value: true });
3+
var WebDAVRequest_1 = require("./WebDAVRequest");
34
var WebDAVServerOptions_1 = require("./WebDAVServerOptions");
45
var ISerializer_1 = require("../manager/ISerializer");
5-
var WebDAVRequest_1 = require("./WebDAVRequest");
66
var FSManager_1 = require("../manager/FSManager");
77
var Errors_1 = require("../Errors");
88
var Commands_1 = require("./commands/Commands");
@@ -182,32 +182,59 @@ var WebDAVServer = (function () {
182182
res.end();
183183
return;
184184
}
185-
if (!method.chunked) {
186-
var data_1 = '';
185+
base.exit = function () {
186+
base.response.end();
187+
_this.invokeAfterRequest(base, null);
188+
};
189+
if (!_this.options.canChunk || !method.startChunked || base.contentLength <= 0) {
187190
var go_1 = function () {
188-
base.data = data_1;
189191
_this.invokeBeforeRequest(base, function () {
190-
base.exit = function () {
191-
res.end();
192-
_this.invokeAfterRequest(base, null);
193-
};
194192
method(base, base.exit);
195193
});
196194
};
197-
if (base.contentLength === 0) {
195+
if (base.contentLength <= 0) {
196+
base.data = new Buffer(0);
198197
go_1();
199198
}
200199
else {
200+
var data_1 = new Buffer(base.contentLength);
201+
var index_1 = 0;
201202
req.on('data', function (chunk) {
202-
data_1 += chunk.toString();
203-
if (data_1.length >= base.contentLength) {
204-
if (data_1.length > base.contentLength)
205-
data_1 = data_1.substring(0, base.contentLength);
203+
if (chunk.constructor === String)
204+
chunk = new Buffer(chunk);
205+
for (var i = 0; i < chunk.length && index_1 < data_1.length; ++i, ++index_1)
206+
data_1[index_1] = chunk[i];
207+
if (index_1 >= base.contentLength) {
208+
base.data = data_1;
206209
go_1();
207210
}
208211
});
209212
}
210213
}
214+
else {
215+
_this.invokeBeforeRequest(base, function () {
216+
_this.invokeBeforeRequest(base, function () {
217+
method.startChunked(base, function (error, onData) {
218+
if (error) {
219+
base.setCode(error.HTTPCode);
220+
base.exit();
221+
return;
222+
}
223+
if (!onData) {
224+
base.exit();
225+
return;
226+
}
227+
var size = 0;
228+
req.on('data', function (chunk) {
229+
if (chunk.constructor === String)
230+
chunk = new Buffer(chunk);
231+
size += chunk.length;
232+
onData(chunk, size === chunk.length, size >= base.contentLength);
233+
});
234+
});
235+
});
236+
});
237+
}
211238
});
212239
});
213240
}

src/server/MethodCallArgs.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export class MethodCallArgs
1818
path : FSPath
1919
uri : string
2020

21-
data : string
21+
data : Int8Array
2222
user : IUser
2323

2424
protected constructor(

src/server/WebDAVRequest.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
11
import { IResource, ReturnCallback } from '../resource/IResource'
2+
import { MethodCallArgs } from './MethodCallArgs'
23
import { WebDAVServer } from '../server/WebDAVServer'
4+
import { HTTPError } from '../Errors'
35
import { FSPath } from '../manager/FSManager'
46
import HTTPCodes from './HTTPCodes'
5-
import MethodCallArgs from './MethodCallArgs'
67
import * as http from 'http'
78
import * as url from 'url'
89

910
export { MethodCallArgs } from './MethodCallArgs'
1011
export { HTTPCodes } from './HTTPCodes'
1112

13+
export type ChunkOnDataCallback = (chunk : Buffer, isFirst : boolean, isLast : boolean) => void
14+
export type StartChunkedCallback = (error : HTTPError, onData : ChunkOnDataCallback) => void
15+
1216
export interface WebDAVRequest
1317
{
1418
(arg : MethodCallArgs, callback : () => void) : void
1519

16-
chunked ?: boolean
20+
startChunked ?: (arg : MethodCallArgs, callback : StartChunkedCallback) => void
1721
}

src/server/WebDAVServer.ts

Lines changed: 52 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1+
import { HTTPCodes, MethodCallArgs, WebDAVRequest, ChunkOnDataCallback } from './WebDAVRequest'
12
import { WebDAVServerOptions, setDefaultServerOptions } from './WebDAVServerOptions'
23
import { SerializedObject, unserialize, serialize } from '../manager/ISerializer'
3-
import { HTTPCodes, MethodCallArgs, WebDAVRequest } from './WebDAVRequest'
44
import { IResource, ReturnCallback } from '../resource/IResource'
55
import { FakePrivilegeManager } from '../user/privilege/FakePrivilegeManager'
66
import { HTTPAuthentication } from '../user/authentication/HTTPAuthentication'
77
import { IPrivilegeManager } from '../user/privilege/IPrivilegeManager'
88
import { SimpleUserManager } from '../user/simple/SimpleUserManager'
99
import { FSManager, FSPath } from '../manager/FSManager'
10+
import { Errors, HTTPError } from '../Errors'
1011
import { RootResource } from '../resource/std/RootResource'
1112
import { IUserManager } from '../user/IUserManager'
12-
import { Errors } from '../Errors'
1313
import Commands from './commands/Commands'
1414
import * as http from 'http'
1515

@@ -273,39 +273,75 @@ export class WebDAVServer
273273
return;
274274
}
275275

276-
if(!method.chunked)
276+
base.exit = () =>
277+
{
278+
base.response.end();
279+
this.invokeAfterRequest(base, null);
280+
};
281+
282+
if(!this.options.canChunk || !method.startChunked || base.contentLength <= 0)
277283
{
278-
let data = '';
279284
const go = () =>
280285
{
281-
base.data = data;
282286
this.invokeBeforeRequest(base, () => {
283-
base.exit = () =>
284-
{
285-
res.end();
286-
this.invokeAfterRequest(base, null);
287-
};
288287
method(base, base.exit);
289288
})
290289
}
291-
292-
if(base.contentLength === 0)
290+
291+
if(base.contentLength <= 0)
293292
{
293+
base.data = new Buffer(0);
294294
go();
295295
}
296296
else
297297
{
298+
const data = new Buffer(base.contentLength);
299+
let index = 0;
298300
req.on('data', (chunk) => {
299-
data += chunk.toString();
300-
if(data.length >= base.contentLength)
301+
if(chunk.constructor === String)
302+
chunk = new Buffer(chunk as string);
303+
304+
for(let i = 0; i < chunk.length && index < data.length; ++i, ++index)
305+
data[index] = (chunk as Buffer)[i];
306+
307+
if(index >= base.contentLength)
301308
{
302-
if(data.length > base.contentLength)
303-
data = data.substring(0, base.contentLength);
309+
base.data = data;
304310
go();
305311
}
306312
});
307313
}
308314
}
315+
else
316+
{
317+
this.invokeBeforeRequest(base, () => {
318+
this.invokeBeforeRequest(base, () => {
319+
method.startChunked(base, (error : HTTPError, onData : ChunkOnDataCallback) => {
320+
if(error)
321+
{
322+
base.setCode(error.HTTPCode);
323+
base.exit();
324+
return;
325+
}
326+
327+
if(!onData)
328+
{
329+
base.exit();
330+
return;
331+
}
332+
333+
let size = 0;
334+
req.on('data', (chunk) => {
335+
if(chunk.constructor === String)
336+
chunk = new Buffer(chunk as string);
337+
size += chunk.length;
338+
339+
onData(chunk as Buffer, size === chunk.length, size >= base.contentLength);
340+
});
341+
});
342+
})
343+
})
344+
}
309345
})
310346
})
311347
}

0 commit comments

Comments
 (0)