Skip to content

Server's options and customizations [v2]

Adrien Castex edited this page Nov 17, 2019 · 12 revisions

Options

To set options to the server, you can provide an object to the constructor of the WebDAVServer class.

const server = new webdav.WebDAVServer({
    /* Options */
})

Here is the complete list of supported options :

Key Default value Description
requireAuthentification false Define if your require to be authenticated.
httpAuthentication new HTTPBasicAuthentication('default realm') Define the object which will provide the authentication method (HTTP : Basic, Digest, custom, etc).
Learn more.
privilegeManager new PrivilegeManager() Allow to check the privileges of the user (grant or restrict access).
Learn more.
rootFileSystem new VirtualFileSystem() The root resource to use as /.
Learn more.
lockTimeout 3600 Define the lock timeout (in seconds).
strictMode false Define if the server must blindly follow the WebDAV RFC (true) or allow more flexibility (false) (for instance disallow a body in a request which doesn't use a body).
hostname '::' Define the scope of the listening server.
https null Define the options to start an HTTPS request listener. This option is directly passed to https.createServer(...).
port 1900 The default port to use if no port is specified when calling server.start().
serverName 'webdav-server' Define the name of the server which will display in the Server HTTP header.
version npm version Define the version of the server to display in the Server HTTP header.
autoSave null Define an auto-saver to automatically save the state of the server and taking care of any conflict which can happen while writing the persistence file and limit the number of writes when some are not required (3 PUT in a row will lead to 2 writes, the first and last ones) (the GET request, for instance, doesn't lead to a write).
autoLoad null Define the way the autoLoad method will behave when called. It is designed to load a file saved by the autoSave.
storageManager new NoStorageManager() Define the storage manager to manage the storage capacity (an existing implementation: PerUserStorageManager).
Learn more.
enableLocationTag false Enable the tag <DAV:location> in the response of the PROPFIND requests. It is disabled by default because it is causing trouble in Finder of OS X.
maxRequestDepth 1 Define the maximum value the Depth header can have in a request (negative values = Infinity). Note that this option can take any number, not only 0, 1 and Infinity.
headers undefined Define custom headers to provide for every response. This option is of type : { [name: string]: string | string[] }

autoSave

The autoSave option is an object of type :

interface IAutoSave
{
    treeFilePath : string,
    tempTreeFilePath ?: string,
    onSaveError ?: (error : Error) => void,
    streamProvider ?: (callback : (inputStream ?: Writable, outputStream ?: Writable) => void) => void
}

If the tempTreeFilePath is not specified, its default value will be the value of treeFilePath plus the .tmp string.

autoLoad

The autoLoad option is an object of type :

interface IAutoLoad
{
    treeFilePath ?: string,
    serializers ?: FileSystemSerializer[],
    streamProvider ?: (inputStream : Readable, callback : (outputStream ?: Readable) => void) => void
}

If serializers is not specified, its default value will be the embedded serializers (VirtualSerializer and PhysicalSerializer).

If the treeFilePath is not specified, its default value will be the value of treeFilePath in the autoSave option of the server.

HTTP methods

You can remove, add and replace HTTP methods of the server.

To add or replace a method, you need to create a function matching the following signature :

interface HTTPMethod
{
    unchunked?(ctx : HTTPRequestContext, data : Buffer, callback : () => void) : void
    chunked?(ctx : HTTPRequestContext, inputStream : Readable, callback : () => void) : void
    isValidFor?(ctx : HTTPRequestContext, type ?: ResourceType) : boolean
}

Then, you have to register this function to the server :

// When a request with the method METHOD_NAME is received, the 'myMethod' object's method is called (`chunked` or `unchunked`)
server.method('METHOD_NAME', myMethod);

You can replace the default function called when no registered function has been found :

server.onUnknownMethod(myNoMethod);

You can remove a method from the server with :

delete server.methods['METHOD_NAME'];

And, you can get the list of supported methods with :

const supportedMethods = server.methods;
for(const name of Object.keys(supportedMethods))
    console.log('The method', name, 'is supported.');

You can find more information about the HTTPMethod interface and default methods at the Supported WebDAV methods page.

File system

You can map a file system to a path in the server. To do so, you can use the method setFileSystem(...) of the WebDAVServer instance.

server.setFileSystem('/folder1', myFileSystem, (success) => console.log(success));

This method will fail if a file system is already mapped to this path. To override it, you can use the override argument or remove the file system.

server.setFileSystem('/folder1', myFileSystem, true, (success) => console.log(success));
server.removeFileSystem('/folder1', (nbRemoved) => {
    server.setFileSystem('/folder1', myFileSystem, (success) => console.log(success));
})

Then, you can remove this file system. Note that you can remove a file system by its path or by its reference.

server.removeFileSystem('/folder1', callback); // Remove by path
server.removeFileSystem(myFileSystem, callback); // Remove by reference
server.removeFileSystem(myFileSystem, false, callback); // Remove by comparing its serializer unique id (will remove all instances using the serializer of myFileSystem)
server.removeFileSystem(myFileSystem, true, callback); // Remove by reference

You can get the path of a file system :

server.getFileSystemPath(myFileSystem, (path) => console.log(path)); // By reference
server.getFileSystemPath(myFileSystem, true, (path) => console.log(path)); // By reference
server.getFileSystemPath(myFileSystem, false, (path) => console.log(path)); // By serializer unique id

You can retrieve a file system and some information with the getFileSystemPath method.

server.getFileSystem('/folder1/folder2/file3.txt', (fileSystem, rootPath, subPath) => {
    console.log('The path of the file system is :', rootPath);
    console.log('The sub path of the requested path is :', subPath); // If rootPath is '/folder1', then subPath is '/folder2/file3.txt'
});

Resource tree

You can add a resource tree to the server.

server.rootFileSystem().addSubTree({
    'folder1': {                                   // /folder1
        'file1.txt': webdav.ResourceType.File,     // /folder1/file1.txt
        'file2.txt': webdav.ResourceType.File,     // /folder1/file2.txt
        'folder2': {
            'file3.txt': webdav.ResourceType.File  // /folder1/folder2/file1.txt
        }
    },
    'file0.txt': webdav.ResourceType.File          // /file0.txt
}, (e) => {
    if(e)
        throw e;
})

You can also specify the content of the files :

server.rootFileSystem().addSubTree({
    'folder1': {                                     // /folder1
        'file1.txt': 'content of the file no 1',     // /folder1/file1.txt
        'file2.txt': 'content of the file no 2',     // /folder1/file2.txt
        'folder2': {
            'file3.txt': 'content of the file no 3'  // /folder1/folder2/file1.txt
        }
    },
    'file0.txt': 'content of the file no 0'          // /file0.txt
}, (e) => {
    if(e)
        throw e;
})

After/Before listeners

You can execute a code or filter requests by using the after/before listeners. The after listeners are executed after the method function and the before listeners are executed before the method function. You can add a listener with :

server.beforeRequest(/* [...] */);
server.afterRequest(/* [...] */);

Here is a little example :

server.afterRequest((ctx, next) => {
    console.log('>>', ctx.request.method, ctx.requested.uri, '>', ctx.response.statusCode, ctx.response.statusMessage);
    next();
})

When executing the before listeners, you can call ctx.exit() to skip and to send the response and execute the after listeners, skipping the method function. Here is an example :

server.beforeRequest((ctx, next) => {
    if(ctx.requested.uri.indexOf('/') !== 0)
    {
        ctx.setCode(400); // Bad request
        ctx.exit();
    }
    else
        next();
})

If you don't call ctx.exit(), then you MUST call next(), otherwise the request execution will stop at the end of the function. Both ctx.exit() and next() can be called asynchronously but they must not be called twice. Only on of these functions must be called, not both.

Clone this wiki locally