Creating a Class 1 WebDAV Server

Class 1 / Class 3 WebDAV Server provides basic file management features available in every WebDAV server. On a Class 1 / Class 3 server, you can create files, copy, move and deleting files and folders as well as create, read and delete custom properties for each file or folder. Note that many WebDAV clients, such as Microsoft Office applications, Microsoft Web Folders client and Mac OS X WebDAV client require Class 2 server. 

Framework Workflow

To create basic WebDAV server, you must implement IFile and IFolder interfaces, create DavContext class derived from DavContextBase and create instance of DavEngine, which is basic implementation of DAV server. Also, you must create Http listener and provide callback function to handle requests:

Typical workflow is:

1. Create instance of DavEngine class.
2. Set license using DavEngine.license property.
3. For each request:
    a. Create an instance of your DavContext class derived from DavContextBase using DavRequest and DavResponse instances.
    b. Call DavEngine.run() function providing the engine with DavContext instance.
    c. Engine calls DavContextBase.getHierarchyItem().
    d. Engine calls members of interfaces IFile , IFolder , etc.

Class1 initialization code for NodeJs server

                            
                        

Storage Interfaces

Now let's see how the storage is represented in IT Hit WebDAV Server package. The storage is the place where you keep files tree structure, files content, custom properties, etc.

The IFile interface, in addition to IHierarchyItem, implements IContent interface that provides functions for managing file content. The class diagram below shows these classes:

storage interfaces hierarchy

As you can see the IHierarchyItem is inherited by IFolder indirectly, IFolder inherits IItemCollection that adds getChildren() functions for enumerating folder content. In your code, you must implement IFolder and IFile interfaces and create your class derived from DavContextBase, that implements DavContextBase.getHierarchyItem() function.

Hierarchy Items

There are 2 types of items in a Class 1 WebDAV repository: folders, represented by IFolder interface and files represented by IFile interface. Both IFolder and IFile interfaces are derived from IHierarchyItem  interface. Most of IHierarchyItem interface members are self explanatory and represent properties that each folder and file has, such as name of the item, item path, creation and modification date and functions for manipulating the item such as copyTo()moveTo() and delete() functions.

The path that you store in your IHierarchyItem.path property should be relative to WebDAV root. If your server root is located at http://example.webdavsystem.com:8080/myserver/ and the item URL is http://example.webdavsystem.com:8080/myserver/myfolder/myitem.doc this property implementation must return myfolder/myitem.doc. To calculate the entire item URL the engine will call DavRequest.applicationPath property and attach it to url returned by path property.

Note that when you rename the item in a WebDAV client, the IHierarchyItem.moveTo() function is called, there is no any separate function for renaming the item.

IFolder Interface

Besides functions provided by IHierarchyItem, the IFolder interface provides a function for enumerating folder children derived from IItemCollection  interface as well as functions for creating files and folders. In your IFolder.getChildren() implementation, you must create and return the list of files and folders contained in this folder. Often in your getChildren() implementation you will also verify user permissions and return only items that the user has rights to see. Here is example how to get list of direct children of folder:

Called when children of this folder are being listed. This code is part of WebDAV Server File System sample provided with IT Hit WebDAV Server Engine for Node.js

                            
                        

IFile Interface

In addition to IHierarchyItem functions, IFile interface has members specific for files: functions for getting MIME type, length of the file content in bytes, and functions for reading and writing resource content.

When WebDAV client is uploading a file to the server the IFile.write() function is called.  The IT Hit Node.js WebDAV Server Library supports upload of the file in segments - resumable upload. The WebDAV client application can submit to server either entire file or submit only a part of a file. The framework can process both cases and IFile.write() has parameters that provide information to implementers about position of the submitted segment inside content and total file size:

Called when a file or its part is being uploaded. This code is part of WebDAV Server File System sample provided with IT Hit WebDAV Server Engine for Node.js

                            
                        

Note to WebDAV client implementers: To submit a file segment attach the Content-Range header to PUT request: Content-Range: bytes XXX-XXX/XXX. If no Content-Range header is found the IT Hit Node.js WebDAV Server Library assumes the entire content is submitted.

The IT Hit WebDAV Server Engine also supports file upload via multipart-encoded form using POST verb.

For getting file content, the IFile interface provides read() function. The WebDAV client application can request  either entire file or only a file segment. The IT Hit Node.js WebDAV Server Library can handle both cases, providing parameters in IFile.read() that specify which bytes of the file are being requested:

Called when a client is downloading a file. Copies file contents to ouput stream. This code is part of WebDAV Server File System sample provided with IT Hit WebDAV Server Engine for Node.js

                            
                        

Usually, the segmented download is used by download managers to restore broken or paused downloads.

Determining File Content-Type / Mime-Type

Most WebDAV clients, including Web Folders, do not submit Content-Type header when uploading a file, so the contentType parameter of the IFile.write() function will be null in most cases. However providing the correct Content-Type / mime-type is vital when serving file content. Some browsers, such as Firefox, rely on the Mime-Type returned in Content-Type header to determine what action to take when the user clicks on file hyperlink. Depending on the mime-type provided by the server, the browser can either load file content in a browser window or can display File Open / File Save dialog.

To get the file mime-type the IT Hit Node.js WebDAV Server Library provides MimeType class that returns mime-type by extension. Usually you will use this class in IFile.contentType() function implementation:

 Note that unlike Firefox, Internet Explorer relies on file extension when deciding what action to take.

Custom Response Code

By default, the IT Hit Node.js WebDAV Server Library assumes that the request was processed successfully and returns response code specified in WebDAV or other standards. In case you need to return any custom response code, you can throw an instance of DavException class.
Often you will throw the exception to inform the client that there is not enough permissions for accessing specific file or creating file or folder:

This code is part of WebDAV Server File System sample provided with IT Hit WebDAV Server Engine for Node.js

                            
                        

Custom Properties

Each item in a repository can have custom string properties associated with the item. Some WebDAV client applications, for instance Microsoft Office and Microsoft Mini-redirector (Windows WebDAV client) can set and read custom properties.

Each property is represented by PropertyValue class and has qualifiedName and value. QualifiedName represeted by PropertyName class and has name and namespace. For manipulating string properties IHierarchyItem interface provides getProperties()getPropertyNames() and updateProperties() functions. When a client application requests properties the framework calls getProperties() passing the list of properties requested by client or null if all properties are requested. In your implementation, you will create and return the list of properties.

To assist with retrieving properties the IFolder.getChildren() and ISearch.search() functions provide a properties list parameter. Using this parameter you can extract all needed properties for all items from your back-end storage in one request and save in your IHierarchyItem implementation object. After calling getChildren() (or search()) functions, the framework will call IHierarchyItem.getProperties() for each item, you will return saved properties to the Engine.

If any property failed to create, update or delete you can throw MultistatusException, to provide client with information which properties failed to update. You must combine all exceptions using MultistatusException.addInnerException() overloaded functions. Note that some WebDAV clients, for example Microsoft Mini-redirector, will ignore error descriptions and will display a generic error.

To get the names of available custom properties you can implement getPropertyNames() function. However most WebDAV clients never request property names without values, so the implementation usually could be left blank.