Skip to content

Server's options and customizations

Adrien Castex edited this page Jan 25, 2019 · 6 revisions

Table of contents

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).
privilegeManager new FakePrivilegeManager() Allow to check the privileges of the user (grant or restrict access).
rootResource new RootResource() The root resource to use as /.
userManager new SimpleUserManager() Define the object which will provide the users.
lockTimeout 3600 Define the lock timeout (in seconds).
canChunk true Define if the server must recreate the full message or if it must keep it splitted (if false, IResource.append(...) will never be called, only IResource.write(...)). Set the value to false if you encounter a problem with the order of the content, this feature hasn't been tested enough.
hostname '::' Define the scope of the listening server.
port 1900 The default port to use if no port is specified when calling server.start().
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).
https null Define the options to start an HTTPS request listener. This option is directly passed to https.createServer(...).
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 whenn called. It is designed to load a file saved by the autoSave.

The autoSave option is an object of type :

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

The autoLoad option is an object of type :

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

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 WebDAVRequest
{
    (arg : MethodCallArgs, callback : () => void) : void // Unchunked version

    chunked ?: (arg : MethodCallArgs, callback : () => void) => void // Chunked version
    isValidFor ?: (type ?: ResourceType) => boolean // Test if the method is allowed (to display or not in the 'Allow' header'
}

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

// When a request with the method METHOD_NAME is received, the function 'myMethod' in called (or the `chunked` method if it exists and a body exists in the request)
server.method('METHOD_NAME', myMethod);

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

server.onUnknownMethod(myFunction);

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 WebDAVRequest interface and default methods at the Supported WebDAV methods page.

Resource tree

You can add a resource tree to the server. By default, the resource tree provided will be added to the root resource of the server, but you can specify a custom resource to which add the resource tree.

interface IResourceTreeNode
{
    r ?: IResource // Shorthand for 'resource'
    resource ?: IResource
    c ?: ResourceTreeNode[] // Shorthand for 'children'
    children ?: ResourceTreeNode[]
}
type ResourceTreeNode = IResourceTreeNode | IResource | IResourceTreeNode[] | IResource[];

class WebDAVServer
{
    addResourceTree(resoureceTree : ResourceTreeNode, callback : (e : Error) => void);
    addResourceTree(rootResource : IResource, resoureceTree : ResourceTreeNode, callback : (e : Error) => void);
    addResourceTree(_rootResource : IResource | ResourceTreeNode, _resoureceTree : ResourceTreeNode | (() => void), _callback ?: (e : Error) => void);

    // [...]
}

For examples, you can look at the Examples page.

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((arg, next) => {
    console.log('>>', arg.request.method, arg.uri, '>', arg.response.statusCode, arg.response.statusMessage);
    next();
})

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

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

If you don't call arg.exit(), then you MUST call next(), otherwise the request execution will stop at the end of the function. Both arg.exit() and next() can be called asynchronously.

Events

The events are called when a special event on a resource on the server is executed. The events are triggered by the server, not by the resources.

An event listener function must match this signature :

type DetailsType = IResource | FSPath | Lock | XMLElement;
type Listener = (arg : MethodCallArgs, subjectResource : IResource, details ?: DetailsType) => void;

Here is the list of the events :

Event name Description details argument
'create' Triggered when the create method of a resource is called by the server. None
'delete' Triggered when the delete method of a resource is called by the server. None
'copy' Triggered when a copy occured. Created resource (IResource)
'move' Triggered when the moveTo method of a resource is called by the server. Destination path (FSPath)
'lock' Triggered when the setLock method of a resource is called by the server. Created lock (Lock)
'refreshLock' Triggered when a lock is refreshed. Refreshed lock (Lock)
'unlock' Triggered when the removeLock method of a resource is called by the server. Removed lock (Lock)
'setProperty' Triggered when the setProperty method of a resource is called by the server (not triggered by a copy). XML element of the request (XMLElement)
'removeProperty' Triggered when the removeProperty method of a resource is called by the server. XML element of the request (XMLElement)
'write' Triggered when the write method of a resource is called by the server. None
'read' Triggered when the read method of a resource is called by the server. None
'addChild' Triggered when the addChild method of a resource is called by the server. Added resource (IResource)

You can add to the server an event with :

server.on('addChild', (arg, subjectResource, addedResource) => {
    console.log('Resource added');
});

You can add a named event :

server.on('addChild', 'myEvent', (arg, subjectResource, addedResource) => {
    console.log('Resource added');
});

Then, you can remove an event :

server.removeEvent('addChild', myFunction);
server.removeEvent('addChild', 'myEvent'); // or, if provided, by using its name

You can clear all the events with :

server.clearEvents('addChild');
Clone this wiki locally