# Webserver Plugin

One of the cores of the innovaphone App Platform is the Webserver (see "The core of the innovaphone App Platform" for details). An App can plugin itself to the Webserver to receive HTTP or WebSocket requests. If an App wants to offer an JavaScript UI too, it actually must plugin itself into the Webserver. However, this can be done by using the IWebserverPlugin interface.
The app needs to give a path to the IWebserverPlugin on creation and call IWebserverPlugin::HttpListen(), IWebserverPlugin::WebsocketListen() or IWebserverPlugin::PassthroughListen() to receive the different requests. The path given to the interface on creation will be the applications web root. So if e.G. the system is accessible under http://192.168.1.100 and the application passes "/myapp" as path, it will be accessibly under http://192.168.1.100/myapp, which will be the apps root. The root of the system is reserved for the Manager of the innovaphone App Platform. The application will receive every request to that path and below.

The Webserver plugin is a collection of a bunch of interfaces, used for web communication. Each web request type (like GET, PUT, POST, ...) has it's own interface to handle the request. The interfaces also have their own user classes that an application must subclass and pass to the IWebserverPlugin instance to accept a request. This user class is responsible for sending and receiving data, settings additional informations (like chunk encoded transfer, the number of bytes the response have, the data type of the response).

The IWebserverPlugin also supports static files. Those files will be converted to a C++ file, compiled and finally linked to the applications binary. This files will be automatically handled by the IWebserverPlugin. That means, that a request of a static file never will reach the applications coded. Instead, the IWebserverPlugin will send the file to the Webserver who will send it to the client that requested the file. So for each incoming GET request, the IWebserverPlugin will at first look at the list of static files, if the request is for one of them. If not, the UWebserverPlugin::WebserverHttpListenResult() function will be called, so that the application can respond to that request or deny it. Note that the static files name also can include subfolder. So a static file can be linked to the applications binary as "images/icon.png", it can be accessed by a client at "http://<server-address>/<applications-root>/images/icon.png".

## File information

File | common/interface/webserver_plugin.h
Public functions | CreateWebserverPluginProvider GetResponseTypeForFileName WSCancelTypeToStr WSPCloseReasonToStr WSWebdavResultToStr
Classes | IWebserverPluginProvider IWebserverPlugin UWebserverPlugin IWebserverGet IWebserverGetRange UWebserverGet IWebserverPost UWebserverPost IWebserverPut UWebserverPut IWebserverPropfind UWebserverPropfind IWebserverMove UWebserverMove IWebserverMkCol UWebserverMkCol IWebserverCopy UWebserverCopy IWebserverDelete UWebserverDelete IWebserverLock UWebserverLock IWebserverUnlock UWebserverUnlock IWebserverProppatch UWebserverProppatch IWebserverOptions UWebserverOptions IWebsocket UWebsocket IWebserverPassthrough UWebserverPassthrough
Data types | WS_MAX_PATH_LENGTH WS_MAX_DATA_SIZE WS_RESPONSE_CHUNKED wsr_cancel_type_t wsp_path_type_t ws_webdav_result_t wsr_type_t wsr_flags_t wsp_close_reason_t ws_close_reason_t ws_request_type_t ws_update_auth_result_t IWebserverGetRange::range_type_t
Structures | ws_type_sfx_t
Examples | IWebserverPlugin - IWebserverGet IWebserverGet - IWebsocket

# Functions

## Functions to initialize

    extern IWebserverPluginProvider * CreateWebserverPluginProvider();

### Overview

This function must be used to create an instance of the IWebserverPluginProvider. With that instance, an IWebserverPlugin instance can be created.
CreateWebserverPluginProvider

  #### Return value

  The IWebserverPluginProvider instance. That instance can be freed as soon as it no longer is used by calling the C++ delete operator.

## Helper functions

    inline wsr_type_t GetResponseTypeForFileName(const char * fileName);
    inline const char * WSCancelTypeToStr(wsr_cancel_type_t c);
    inline const char * WSPCloseReasonToStr(wsp_close_reason_t cr);
    inline const char * WSWebdavResultToStr(ws_webdav_result_t r);

### Overview

This functions are helper function to make development life a little bit easier. While GetResponseTypeForFileName() iterates trough the list of resource types to get the resource type for a given file prefix, the other functions are for mapping an enum type to a human readable string. That helps especially for debugging purposes.
GetResponseTypeForFileName

  #### Parameters

  const char * filename | The filename to figure out the type to return for that request. That type will be written in the answers HTTP header.

  #### Return value

  The wsr_type_t resource type to set for a GET request. The response type will be returned depending on the file prefix. See wsr_type_t for more information.
WSCancelTypeToStr

  #### Parameters

  wsr_cancel_type_t c | The wsr_cancel_type_t value to convert to a string.

  #### Return value

  The given wsr_cancel_type_t value as human readable string, so that it can be written to a log instead of only a number value.
WSPCloseReasonToStr

  #### Parameters

  wsp_close_reason_t cr | The wsp_close_reason_t value to convert to a string.

  #### Return value

  The given wsp_close_reason_t value as human readable string, so that it can be written to a log instead of only a number value.
WSWebdavResultToStr

  #### Parameters

  ws_webdav_result_t r | The ws_webdav_result_t value to convert to a string.

  #### Return value

  The given ws_webdav_result_t value as human readable string, so that it can be written to a log instead of only a number value.

# Classes

## IWebserverPluginProvider

    class IWebserverPluginProvider {
    public:
        virtual ~IWebserverPluginProvider() {}
        virtual class IWebserverPlugin * CreateWebserverPlugin(class IIoMux * const iomux,
                                                               class ISocketProvider * localSocketProvider,
                                                               class UWebserverPlugin * const user,
                                                               const char * webserverAddress,
                                                               const char * appWebRoot,
                                                               class IInstanceLog * const log);
    };

### Overview

The IWebserverPluginProvider is used to create an instance of IWebserverPlugin. Multiple instances of IWebserverPlugin can be created, but generally only one IWebserverPlugin is needed for each AppInstance. The created IWebserverPlugin does not depend on the IWebserverPluginProvider it had been created from. So the IWebserverPluginProvider instance can be deleted as soon as no longer needed.

### Public functions

CreateWebserverPlugin
  Creates the IWebserverPlugin instance. The application is responsible to free the instance when no longer needed. This must not be done before calling IWebserverPlugin::Shutdown() and receiving the UWebserverPlugin::WebserverPluginShutdownComplete() callback.

  #### Parameters

  class IIoMux * const iomux | The IIoMux instance the IWebsocketPlugin instance will be registered to.
  class ISocketProvider * localSocketProvider | The ISocketProvider instance that will be used to create a local socket.
  class UWebserverPlugin * const user | The IIoMux instance the IWebsocketPlugin instance will be registered to.
  const char * webserverAddress | The address of the Webserver. Will be passed to the application from the manager.
  const char * appWebRoot | The root of the app inside the web structure. Can not be the root of the system ("/"), as well as not a folder already used by an other app.
  class IInstanceLog * const log | The IInstanceLog instance used for logging purposes.

  #### Return value

  The IWebserverPlugin instance It must be freed by the C++ operator delete, if no longer be used.

## IWebserverPlugin

    class IWebserverPlugin {
    public:
        virtual ~IWebserverPlugin() {};

        virtual void SendCertificate(const char * password, const byte * certBuf, size_t certLen, const char * hostName = nullptr, UWebserverPlugin * user = nullptr);
        virtual void HttpListen(const char * path = nullptr, UWebserverPlugin * user = nullptr, const char * authUser = nullptr, const char * authUserPwd = nullptr, const char * staticFilePrefix = nullptr);
        virtual void HttpListen(const char * path, UWebserverPlugin * user, bool dynamicAuth, const char * staticFilePrefix = nullptr);
        virtual void PassthroughListen(const char * path = nullptr, UWebserverPlugin * user = nullptr);
        virtual void WebsocketListen(const char * path = nullptr, UWebserverPlugin * user = nullptr);
        virtual void SetAuthConfig(const char * path, const char * authUser = nullptr, const char * authPwd = nullptr);
        virtual void SetAuthConfig(const char * path, bool enableDynAuth);

        virtual void Cancel(wsr_cancel_type_t reason);
        virtual void Redirect(const char * newDestination);

        virtual void Accept(class UWebserverGet * const user);
        virtual void Accept(class UWebserverPost * const user);
        virtual void Accept(class UWebserverPut * const user);
        virtual void Accept(class UWebserverPassthrough * const user);
        virtual void Accept(class UWebserverPropfind * const user);
        virtual void Accept(class UWebserverMove * const user);
        virtual void Accept(class UWebserverMkCol * const user);
        virtual void Accept(class UWebserverCopy * const user);
        virtual void Accept(class UWebserverDelete * const user);
        virtual void Accept(class UWebserverLock * const user);
        virtual void Accept(class UWebserverUnlock * const user);
        virtual void Accept(class UWebserverProppatch * const user);
        virtual void Accept(class UWebserverOptions * const  user);
        virtual void WebsocketAccept(class UWebsocket * user);

        virtual void RequestUserPasswordResult(dword connectionID, const char * user, const char * password);

        virtual void Close();
    };

### Overview

The IWebsocketPlugin is the interface used by an app to hook itself into the Webserver of the innovaphone App Platform. Doing so allows the app to receive HTTP requests (including WebDav) as well as WebSocket requests. This is primarily used to provide and communicate with a JavaScript UI. However, it can be used for HTTP communication beside this as well.
To receive request, an application first must call one of the listen functions of IWebserverPlugin. The functions can be called multiple times to listen to different paths, but only once per path. An exception is the difference of the listen call. So WebsocketListen() can be called for a path that already had been used for HttpListen(). But be careful with the order the listen calls will be made. When an application calls Listen() (HttpListen(), WebsocketListen() or PassthroughListen()) more than once to listen to different paths, this calls are handled asynchronous. That means, that after the first HttpListen() had been handled, an incoming connection can already accepted before the second HttpListen() had been handled by the Webserver (same for WebsocketListen() and PassthroughListen()). So if the second one goes to a subpath, that can lead to wrong listen result calls.
For example, an applications wants to listen to "/myapp" and "/myapp/image". But because a listen to "/myapp" also leads for a HttpListenResult if "/myapp/images/myimage.png" is requested, but "/myapp/images" is not yet registered for listen, HttpListenResult will be called with a path and registeredPathForRequest value that the application won't expect. To prevent that, the HttpListen() must be called in opposite order. So in our example, at first HttpListen("/myapp/images") should be called before HttpListen("/myapp"). For passthrough (see below), that problem doesn't exist. Because To now more about the listen result function, see UWebserverPlugin.
The Webserver itself will resolve a request and redirects it in a prepared manner to the IWebsocketPlugin responsible for that request. So the App generally don't need to handle any HTTP protocol (as long as the IWebsocketPlugin is not used for passthrough, which gives full control over the protocol to the app). Generally, an incoming request will lead to an appropriate UWebserverPlugin::WebserverPlugin*ListenResult() (while * can be HTTP, WebSocket or Passthrough). The only exception is an incoming GET request. In that case, the IWebserverPlugin at first will look for static files linked to the app, that can fulfill the request. If found, the file will be send to the Client and therefore the request will be responded from the IWebserverPlugin internally. The application won't be notified. So if an app only wants to provide static files, there is no need to implement an UWebserverPlugin::WebserverPluginHttpListenResult().
A path can be registered to be password protected. This can be either an fixed user and password, that will not change during the applications running time, or in a dynamic way, which means that for each request the Webserver asks the application for the password of the user that tries to access. It is also possible to only password protect a subfolder, by calling a IWeberverPlugin::HttpListen() to the apps root without password information and calling it again for a subfolder, telling that subfolder needs authentication. Authentication is only supported for HTTP listen, not for WebSocket or pass through.
While all request will be handled by the Webserver itself, so that an application has no need to handle the HTTP protocol, it can be necessary some times to have control on what's going on. So an application can also call IWebserverPlugin::PassthroughListen(), which will end up in an UWebserverPlugin::WebserverPluginPassthroughListenResult() for each incoming request. The difference is, that the request will be passed through to the app, ans so the app needs to parse the HTTP header and build up a correct HTTP header for response (also handle WebSocket or whole authentication stuff, if needed). Parsing and creating a HTTP header can be done with the HTTPLib::HTTPHeader and HTTPLib::HTTPParser classes.

### Logging

To enable logging for IWebserverPlugin, the flag LOG_WEBSERVER_TRAFIC must be set in the managers diagnostic settings.

### Public functions

HttpListen (overloaded)
  Starts to listen to incoming HTTP requests. If an incoming request as a GET request and can be resolved with to the app linked static files, the request will be handled internally. Else the application will receive a callback to response or cancel the request. And application must call the function at least for the applications root (with path = nullptr), even if only want to provide static files.

  #### Parameters

  const char * path | (Default nullptr) The path to listen to. Note that path always will be under the applications web root, defined when creating the IWebserverPlugin. If this value is nullptr, the root will be used.
  UWebserverPlugin * user | (Default nullptr) The user to inform about an incoming request. This helps to have different UWebserverPlugin instances for different path to list. If set to nullptr, the same user as passed to IWebserverPluginProvider::Create() will be used (which however is the default user).
  const char * authUser | (Default nullptr) The user to use for authentication. If not is null, authentication for the given pass will be activated.
  const char * authPassword | (Default nullptr) The password to use for authentication.
  const char * staticFilePrefix | (Default nullptr) If not is nullptr, the value given will be used as prefix for static files. This can also include '/' to simulate an other path.

  #### Callbacks

  On success, an incoming HTTP request will lead to a callback of UWebserverPlugin::WebserverPluginHttpListenResult(), if the request is not a get request and, in that case, can't be resolved with an static file linked to the applications binary. If an error occurs, USocket::SocketShutdown() will be called. Details of that error can be found inside the log, if logging is activated. Reason can be one of the following values:

  WSP_REGISTER_PATH_INVALID | The path given to register is invalid.
  WSP_PATH_ALREADY_REGISTERD | An other application already is listening to that path.
  WSP_ADDRESS_INVALID | The address to connect to the Webserver is invalid.

  #### Remarks

  This function is overloaded (see below).
  Calling IWebserverPlugin::HttpListen() more than once to the same path will lead to an assertion. If tried to call it for a path already registered by an other application, the listen will be rejected by the Webserver.
  However, the connection to the connection will be established the fist time, one of the IWebserverPlugin::*Listen() functions. The listen calls will be cached, so if the connection get lost, the IWebserverPlugin will connect to the Webserver again and also makes the listen calls again, too.
HttpListen (overloaded)
  This overloaded version does the same as described above. The difference is, that this version will be used to activate dynamic authentication, which means that the Webserver asks the application for a password of a user that tries to connect. If the flag dynamicAuth is set to false, the function acts like calling the function above with authUser set to nullptr.

  #### Parameters

  const char * path | The path to listen to. Note that path always will be under the applications web root, defined when creating the IWebserverPlugin. If this value is nullptr, the applications root will be used.
  UWebserverPlugin * user | The user to inform about an incoming request. This helps to have different UWebserverPlugin instances for different path to list. If set to nullptr, the same user as passed to IWebserverPluginProvider::Create() will be used (which however is the default user).
  bool dynamicAuth | If true, dynamic authentication will be activated. That means, that the Webserver asks the application for the password for a user that tries to authenticate.
  const char * staticFilePrefix | (Default nullptr) If not is nullptr, the value given will be used as prefix for static files. This can also include '/' to simulate an other path.

  #### Callbacks

  On success, an incoming HTTP request will lead to a callback of UWebserverPlugin::WebserverPluginHttpListenResult(), if the request is not a get request and, in that case, can't be resolved with an static file linked to the applications binary. If a user tries to authenticate, the Webserver asks the app for the password of the user who tries to authenticate by calling UWebserverPlugin::WebserverPluginRequestUserPassword(). The password must be sent using IWebserverPlugin::RequestUserPasswordResult() (see below).
  If an error occurs, USocket::SocketShutdown() will be called. Details of that error can be found inside the log, if logging is activated. Reason can be one of the following values:

  WSP_REGISTER_PATH_INVALID | The path given to register is invalid.
  WSP_PATH_ALREADY_REGISTERD | An other application already is listening to that path.
  WSP_ADDRESS_INVALID | The address to connect to the Webserver is invalid.

  #### Remarks

  This function is overloaded (see below).
  Calling IWebserverPlugin::HttpListen() more than once to the same path will lead to an assertion. If tried to called it for a path already registered by an other application, the listen will be rejected by the Webserver.
  However, the connection to the connection will be established the fist time, one of the IWebserverPlugin::*Listen() functions. The listen calls will be cached, so if the connection get lost, the IWebserverPlugin will connect to the Webserver again and also makes the listen calls again, too.
PassthroughListen
  An application can register itself for passthrough. Any request to that path, whatever kind of request, will be completely redirected to the application. That means, that the application is responsible for handling the HTTP header (the incoming and outgoing) as well as all the other HTTP protocol related stuff. The Webserver itself does nothing than passing through the bytestream between the client and the application. This can be done with the help of the HTTPLib::HTTPHeader and HTTPLib::HTTPParser classes. PassthroughListen() only should be used if it is really necessary, generally it is recommended to let the Webserver itself handle all of the HTTP related stuff.

  #### Parameters

  const char * path | The path to listen to for passthrough. Note that path always will be under the applications web root, defined when creating the IWebserverPlugin. If this value is nullptr, the applications root will be used.
  UWebserverPlugin * user | The user to inform about an incoming request. This helps to have different UWebserverPlugin instances for different path to list. If set to nullptr, the same user as passed to IWebserverPluginProvider::Create() will be used (which however is the default user).

  #### Callbacks

  On success, an incoming request will lead to a callback of UWebserverPlugin::WebserverPluginPassthroughListenResult().
  If an error occurs, USocket::SocketShutdown() will be called. Details of that error can be found inside the log, if logging is activated. Reason can be one of the following values:

  WSP_WEBSOCKET_PATH_INVALID | The path given to listen to WebSocket connection is invalid.
  WSP_WEBSOCKET_PATH_ALREADY_LISTENING | An other application already is listening to that path.
  WSP_ADDRESS_INVALID | The address to connect to the Webserver is invalid.

  #### Remarks

  Passthrough always will be handled with priority. So if IWebserverPlugin::HttpListen() and IWebserverPlugin::PassthroughListen() will be called with the same path, only the passthrough will be handled.
WebsocketListen
  Listens for incoming WebSocket connection to the given path. WebsocketListen() can be called for a path that had been used for HTTPListen() before.

  #### Parameters

  const char * path | The path to listen to for WebSocket connections. Note that path always will be under the applications web root, defined when creating the IWebserverPlugin. If this value is nullptr, the applications root will be used.
  UWebserverPlugin * user | The user to inform about an incoming WebSocket request. This helps to have different UWebserverPlugin instances for different path to list. If set to nullptr, the same user as passed to IWebserverPluginProvider::Create() will be used (which however is the default user).

  #### Callbacks

  On success, an incoming WebSocket request will lead to a callback of UWebserverPlugin::WebserverPluginWebsocketListenResult().
  If a user tries to authenticate, the Webserver asks the app for the password of the user who tries to authenticate by calling UWebserverPlugin::WebserverPluginRequestUserPassword().
  If an error occurs, USocket::SocketShutdown() will be called. Details of that error can be found inside the log, if logging is activated. Reason can be one of the following values:

  WSP_WEBSOCKET_PATH_INVALID | The path given to listen to WebSocket connection is invalid.
  WSP_WEBSOCKET_PATH_ALREADY_LISTENING | An other application already is listening to that path.
  WSP_ADDRESS_INVALID | The address to connect to the Webserver is invalid.

  #### Remarks

  It is allowed to use the same path for IWebserverPlugin::WebsocketListen() as used for IWebserverPlugin::HttpListen().
SetAuthConfig (overloaded)
  Must be called if the configuration for authentication of a path should be changed. The changes will become active immediately. This overloaded version will be used to enable static authentication with the given username and password. So multiple calls to that function can be used to change the username or password, too. Setting them both to nullptr, will deactivate authentication for the given path, independent whether if static or dynamic authentication is currently active.

  #### Parameters

  const char * path | The path to listen to change the authentication configuration for (without the app web root). If this is nullptr, "/" or "", the app webroot will be used.
  const char * authUser | (Default: nullptr) The user name to use for authentication. If this value is not nullptr, the authentication will be enabled or changed to static authentication.
  const char * authPwd | (Default: nullptr) The password to use for authentication.

  #### Callbacks

  The call to that function will lead to a UWebserverPlugin::SetAuthConfigResult() callback. The result of the action will be reported with one of the ws_update_auth_result_t values.

  #### Remarks

  This version activates (or changes the parameters for) static authentication. It also only can be called for a path that had been passed to a previous HTTPListen() call.
SetAuthConfig (overloaded)
  Must be called if the configuration for authentication of a path should be changed. The changes will become active immediately. This overloaded version will be used to enable dynamic authentication. Passing false as enableDynAuth, will deactivate authentication for the given path, independent whether if static or dynamic authentication is currently active.

  #### Parameters

  const char * path | The path to listen to change the authentication configuration for (without the app web root). If this is nullptr, "/" or "", the app webroot will be used.
  bool enableDynAuth | True, to enable or change to dynamic authentication. If false, authentication will be deactivated.

  #### Callbacks

  The call to that function will lead to a UWebserverPlugin::SetAuthConfigResult() callback. The result of the action will be reported with one of the ws_update_auth_result_t values.

  #### Remarks

  SetAuthConfig() only can be called for a path that had been passed to a previous HTTPListen() call. However, it also can be used to switch from dynamic authentication to static authentication, if needed.
SendCertificate
  The Webserver supports TLS encrypted connections. This function let define the certificate to use. Generally there is no need for an application to call this function, because the certificate will be set by the Manager.

  #### Parameters

  const char * password | The password to use with the certificate.
  const byte * certBuf | The buffer with the certificate to send. Must not be nullptr.
  size_t certLen | The length of the certificate.
  const char * hostName | Reserved for later use, always should be set to nullptr.
  UWebserverPlugin * user | The user to inform the result. This helps to have different UWebserverPlugin instances. If set to nullptr, the same user as passed to IWebserverPluginProvider::Create() will be used (which hovewer is the default user).

  #### Callbacks

  On success, an incoming request will lead to a callback of UWebserverPlugin::WebserverPluginSendCertificateResult().
  If an error occurs, USocket::SocketShutdown() will be called. Details of that error can be found inside the log, if logging is activated. :

  WSP_ADDRESS_INVALID | The address to connect to the Webserver is invalid.

Accept
  If an incoming request should be accepted, one of the IWebserverPlugin::Accept() functions must be called. For each request an instance of one of the following users must be passed (depending on request type):
  - UWebserverGet
  - UWebserverPost
  - UWebserverPut
  - UWebserverPassthrough
  - UWebserverPropfind
  - UWebserverMove
  - UWebserverMkCol
  - UWebserverCopy
  - UWebserverDelete
  - UWebserverLock
  - UWebserverUnlock
  - UWebserverProppatch
  - UWebserverOptions
  The application must create a class derived from one of the users above and implement the necessary functions. If passing nullptr instead an instance of one of that classes, the request will be canceled (which will be the same behavior as calling cancel with WSP_CANCEL_NOT_FOUND).

  #### Parameters

  User instance * user | The instance of one the above users. That user will be responsible to handle the request. If nullptr, the request will be handled with reason WSP_CANCEL_NOT_FOUND.

  #### Callbacks

  After calling Accept() with a valid user instance, the *RequestAcceptComplete() callback of the given user will be called (e. G. UWebserverGet::WebserverGetRequestAcceptComplete()). See the documentation for that user classes for more details.

  #### Remarks

  IWebserverPlugin::Accept() must be called inside the UWebserverPlugin::WebserverPluginHttpListenResult() or UWebserverPlugin::WebserverPassthroughListenresult(). If the request should not be accepted, IWebserverPlugin::Cancel() must be called.
  To accept an incoming WebSocket request, IWebserverPlugin::WebsocketAccept() must be called.
  Calling IWebserverPlugin::Accept() with an instance of one of the user classes that not will correspond to the accept will lead to an assertion.
WebsocketAccept
  If a WebSocket request comes in, it can be accepted using the WebsocketAccept() function. (To deny, call Cancel()). When accepting, an instance of a class derived from UWebsocket must be passed. This instance will be responsible for the WebSocket connections. See UWebsocket for details. If nullptr will be passed to WebsocketAccept(), the request will be denied in the same way as calling IWebserverPlugin::Cancel().

  #### Parameters

  UWebsocketUser * user | The instance of one the users to handle the WebSocket communication, that will be responsible to handle the request. If nullptr, the request will be denied.

  #### Callbacks

  After calling Accept() with a valid user instance, the UWebsocket::WebsocketAcceptComplete callback of that user will be called.

  #### Remarks

  IWebserverPlugin::WebsocketAccept() must be called inside the UWebserverPlugin::WebserverPluginWebsocketListenResult(). If the request should denied, IWebserverPlugin::Cancel() must be called.
Cancel
  This function will be used to deny an incoming request.

  #### Parameters

  wsr_cancel_type_t reason | The reason why the request had been canceled. See wsr_cancel_type_t for more infos.

  #### Remarks

  This function must be called from inside of one of the *ListenResult() functions.
  Like Accept() (and WebsocketAccept()), Cancel() will be used to deny each type of request, including WebSocket.
Redirect
  An incoming request can not only be accepted or denied, it can also be redirected to an other location. Redirecting using this function is a temporary redirect. That means, that a HTTP conform client will automatically went to the new place, until the browser will be started again.

  #### Parameters

  const char * newDestination | The destination to redirect to. Can be a relative or absolute path. For an absolute path, the value must start with "http://".

  #### Remarks

  Like Accept() and Cancel(), this function must be called inside the *ListenResult() function (e. G. UWebserverPlugin::WebserverPluginHttpListenReuslt()).
  Redirection is not supported for WebSocket requests. Calling IWebserverPlugin::Redirect() for a WebSocket request will lead to an assertion.
RequestUserPasswordResult
  When dynamic authentication had been activated (see HttpListen() above) and the Webserver asks for a users password, IWebserverPlugin::RequestUserPasswordResult() must be called. This function can be called outside from UWebserverPlugin::WebserverPluginRequestUserPassword(), so reading the password from an other source like a database is possible. Note that the client needs to wait until the app calls RequestUserPasswordResult().

  #### Parameters

  dword connectionID | The ID of the connection authentication request comes from. Must be the same id as received in UWebserverPlugin::WebserverPluginRequestUserPassword(). If the password can not be send directly inside the request function, the application must save the connection id to response later.
  const char * user | The user that requested the authentication. Must be the same as received in UWebserverPlugin::WebserverPluginRequestUserPassword(). If the password can not be send directly inside the request function, the application must save the user name to response later. If the user is denied by the application, user can set to nullptr for the response.
  const char * password | The password for that user. If user is set to nullptr, the value given to password will be ignored. If password is set to nullptr, no password will be used for authentication.

  #### Remarks

  If the connection id and user name are not the same as passed to UWebserverPlugin::WebserverPluginRequestUserPassword(), the Webserver will deny the request (like setting user to nullptr).
Close
  Closes the IWebserverPlugin instance. The application must wait until UWebserverPlugin::WebserverPluginClose() had been closed with lastUser set to true, before freeing the IWebserverPlugin instance. See UWebserverPlugin for more details.

  #### Remarks

  After closed, each still active user passed to one of the functions that accept an additional UWebserverPlugin instance, will receive a UWebserverPlugin::WebserverPluginClose() callback. It is guaranteed, that the main user will be the last one informed. The lastUser flag helps to identify that case.

## UWebserverPlugin

    class UWebserverPlugin {
    public:
        virtual ~UWebserverPlugin() {}

        virtual void WebserverPluginClose(IWebserverPlugin * plugin, wsp_close_reason_t reason, bool lastUser)
        {
            if (lastUser) delete plugin;
        }

        virtual void WebserverPluginHttpListenResult(IWebserverPlugin * plugin, ws_request_type_t requestType, char * resourceName, const char * registeredPathForRequest, ulong64 dataSize)
        {
            plugin->Cancel(WSP_CANCEL_NOT_FOUND);
        }

        virtual void WebserverPluginPassthroughListenResult(IWebserverPlugin * plugin, char * resourceName, const char * registeredPathForRequest, ulong64 dataSize)
        {
            plugin->Cancel(WSP_CANCEL_NOT_FOUND);
        }

        virtual void WebserverPluginWebsocketListenResult(IWebserverPlugin * plugin, const char * path, const char * registeredPathForRequest, const char * host)
        {
            plugin->WebsocketAccept(nullptr);
        }

        virtual void WebserverPluginConnected() {}
        virtual void WebserverPluginConnected(IWebserverPlugin * plugin) { this->WebserverPluginConnected(); }
        virtual void WebserverPluginSendCertificateResult(IWebserverPlugin * plugin, byte * certBuffer) {}
        virtual void WebserverPluginRegisterPathResult(IWebserverPlugin * plugin, const char * pathName, wsp_path_type_t pathType) {}
        virtual void WebserverPluginRequestUserPassword(IWebserverPlugin * plugin, dword connectionID, char * resourceName, const char * registeredPathForRequest, const char * host, const char * user) { ASSERT(false, "UWebserverPlugin::WebserverPluginRequestUserPassword() not implemented!"); }
        virtual void SetAuthConfigResult(const char * path, ws_update_auth_result_t result) {}
    };

### Overview

Each action needed to be redirected to the application the IWebserverPlugin instance will call one of the UWebserverPlugin functions. So an application that is going to use the Webserver Plugin must provide a subclass of UWebserverPlugin and implement what is needed. UWebserverPlugin is used to handle incoming requests (if not a GET request handled by static files), accept requests and handle some other details.

### Public functions

WebserverPluginHttpListenResult
  Will be called after calling IWebserverPlugin::HttpListen() and receiving a HTTP request. The request must be canceled or accepted inside this function. If the function will return without accepting or canceling the request, an assertion will be thrown. To accept the request, IWebserverRequest::Accept() must be called, passing an UWebserver* handler instance combining with the request.

  #### Parameters

  IWebserverPlugin * plugin | The calling IWebserverPlugin instance
  ws_request_type_t requestType | The type of the request. See ws_request_type_t for details.
  char * resourceName | The resource requested. The resource can include a relative path, with the given registeredPathForRequest as root.
  char * registeredPathForRequest | The registered path for that request.
  ulong64 dataSize | The size of the data coming with the request, if the kind of request can deliver data (e. g. POST).

  #### Callbacks

  If the incoming request had been accepted, the WebserverPluginAcceptComplete of the user passed to accept will be called.

  #### Remarks

  Valid users for an HTTP request to pass to IWebserverPlugin::Accept() are:
  - UWebserverGet
  - UWebserverPost
  - UWebserverPut
  - UWebserverPassthrough
  - UWebserverPropfind
  - UWebserverMove
  - UWebserverMkCol
  - UWebserverCopy
  - UWebserverDelete
  - UWebserverLock
  - UWebserverUnlock
  - UWebserverProppatch
  - UWebserverOptions
WebserverPluginPassthroughListenResult
  Will be called after calling IWebserverPlugin::PassthroughListen() and receiving a passthrough request. The request must be canceled or accepted inside this function. If the function will return without accepting or canceling the request, an assertion will be thrown. To accept the request, IWebserverRequest::Accept() must be called, passing an UWebserverPassthrough instance. Note that if the application listens for passthrough, it will be responsible to handle the HTTP request by itself.

  #### Parameters

  IWebserverPlugin * plugin | The calling IWebserverPlugin instance
  char * resourceName | The resource requested. The resource can include a relative path, with the given registeredPathForRequest as root.
  char * registeredPathForRequest | The registered path for that request.
  ulong64 dataSize | The size of the data coming with the request. This data must be read with IWebserverPassthrough::Recv() and includes the whole HTTP header of the request.

  #### Callbacks

  If the incoming request had been accepted, the WebserverPluginAcceptComplete of the user passed to accept will be called.
WebserverPluginWebsocketListenResult
  Will be called after calling IWebserverPlugin::WebsocketListen() and receiving a WebSocket request. The request must be canceled or accepted inside this function. If the function will return without accepting or canceling the request, an assertion will be thrown. To accept the request, IWebserverRequest::Accept() must be called, passing an UWebsocket instance.

  #### Parameters

  IWebserverPlugin * plugin | The calling IWebserverPlugin instance
  const char * path | The path for the request. However, even if it is called "path", it can include a filename, too. Depending on what had been passed to IWebserver::WebsocketListen().
  const char * registeredPathForRequest | The registered path for that request.
  const char * host | The host of the request.

  #### Callbacks

  If the incoming request had been accepted, the WebserverPluginWebsocketAcceptComplete of the user passed to accept will be called.
WebserverPluginConnected
  Will be called after calling IWebserverPlugin::Connect() and after the connection had been established. It will be e good idea to call the IWebsocketPlugin::*Listen() after the connection had been established, but it can be called before receiving the WebserverPluginConnected() callback either.
WebserverPluginConnected
  Same as WebserverPluginConnected() but now with the plugin as parameter.

  #### Parameters

  IWebserverPlugin * plugin | The calling IWebserverPlugin instance

WebserverPluginClose
  Will be called after the IWebserverPlugin had been closed. Note that when the WebserverPlugin uses the connection (because the Webserver is down), it is going to reconnect until the connection can be established again. After closing, the IWebserverPlugin Instance should be released.

  #### Parameters

  IWebserverPlugin * plugin | The calling IWebserverPlugin instance
  wsp_close_reason_t reason | The reason why the plugin had been closed. See wsp_close_reason_t for more details.
  bool lastUser | If true, the user that receives that callback is the last user, so that the instance can be deleted.

  #### Remarks

  Because the IWebserverPlugin::*Listen() function can be called with multiple users, each user given to that functions will receive the WebserverPluginClose() callback with lastUser set to false. Except the last user which is the user given when creating the plugin. This user will receive the callback with lastUser set to true. In that case it is guaranteed, that all other users already had been informed and no more WebserverPluginClose() call will be made. So the IWebserverPlugin instance can be deleted. Never delete the instance while lastUser is false!
WebserverPluginSendCertificateResult
  The IWebserverPlugin can be used to send a certificate to the Webserver, that will be used for TLS connections. After successfully sent, this function will be called.

  #### Parameters

  IWebserverPlugin * plugin | The calling IWebserverPlugin instance
  byte * certBuffer | The buffer with the certificate sent.

  #### Remarks

  Normally, the AppPlatform Manager will send the certificate to the Webserver, so there is no need for an app to use the mechanism to set a certificate.
WebserverPluginRegisterPathResult
  When calling one of the Listen functions of IWebserverPlugin, the path given to that function will be registered inside the Webserver. This process will lead to the WebserverPlugin RegisterPathResult() call. An application can watch to the result of the registration process (if wanted) by implementing that callback function.

  #### Parameters

  IWebserverPlugin * plugin | The calling IWebserverPlugin instance
  const char * pathName | The registered path name, the same as given to one of the listen functions.
  wsp_path_type_t pathType | The type of the registered path. The value depends on the called listen function. See wsp_path_type_t for more details.

WebserverPluginRequestUserPassword
  The IWebserverPlugin supports two ways for authentication: the static authentication (that is giving the user name and password while listening to the a path), and the dynamic way where the Webserver asks the IWebserverPlugin for the user name and password for each request. This will be done with this callback. The user name an password must be returned to the Webserver by calling IWebserverPlugin::RequestUserPasswordResult().

  #### Parameters

  IWebserverPlugin * plugin | The calling IWebserverPlugin instance
  dword connectionID | The id of the connection that wants to authenticate. This ID must be given (together with the user name) to IWebserverPlugin::RequestUserPasswordResult() for answering the authentication request.
  char * resourceName | The resource the needs to authenticate. The resource can include a relative path, with the given registeredPathForRequest as root.
  const char * registeredPathForRequest | The registered path for the request.
  const char * host | The host that tries to access the resource.
  const char * user | The user that tries to authenticate. Must be given (together with the connection id) to IWebserverPlugin::RequestUserPasswordResult() for answering the authentication request.

  #### Remarks

  The authentication request can be responded outside of this function. This comes in handy if e. g. the user information must be read from the database, first. The application only need to take care of sending the correct connection id with the user name given for the request.
SetAuthConfigResult
  Will be called after the Webserver has changed the authentication configuration because of a previous call to IWebserverPlugin::SetAuthConfig().

  #### Parameters

  const char * path | The path the configuration needed to be changed for ("/" for the apps web root). Will always be the same path as used for the previous SetAuthConfig() call.
  ws_update_auth_result_t result | The result of the config change. See the ws_update_auth_result_t enum for details.

## IWebserverGet

    class IWebserverGet {
    public:
        virtual ~IWebserverGet() {}

        virtual const char * GetResourceName();
        virtual const char * GetRegisteredPathForRequest();
        virtual const char * GetETag();
        virtual ulong64 GetRangeCount();
        virtual IWebserverGetRange * GetRange(size_t idx);
        virtual bool IsSysClientAuthenticated();

        virtual void Cancel(wsr_cancel_type_t reason);
        virtual void SetTransferInfo(wsr_type_t resourceType, ulong64 dataSize, wsr_flags_t flags = WSP_FLAG_NONE, const char * etag = nullptr);
        virtual void SetTransferRange(ulong64 rangeStart, ulong64 rangeEnd);
        virtual void ForceDownloadResponse(const char * fileName = nullptr);
        virtual void Send(void * buffer, size_t len);
        virtual void Close();
    };

### Overview

After accepting an incoming GET request, UWebserverGet::WebserverGetRequestAcceptComplete() will be called with the IWebserverGet instance to use to answer the request. The IWebserverGet interface is all that is needed to response the GET request. The instance is only valid for one request, and each request has it's own IWeberverGet instance. After sending the response, the IWebserverGet instance must be closed to tell the Webserver, that the response had been completed.

### Public functions

GetResourceName
  Returns the name of the requested resource. That name includes the path below the registered path the request was for. So if the registered path is "/images" and the request goes to "/images/ui/buttons/ok.png", GetResourceName() will return "/ui/buttons/ok.png".

  #### Return value

  The resource requested as const string.
GetRegisteredPathForRequest
  Returns the registered path the request was for. So if the registered path is "/images" and the request goes to "/images/ui/buttons/ok.png", GetRegisteredPathForRequest() will return "/images".

  #### Return value

  The registered path of the request as const string.
GetETag
  Return the ETag, if there is any. ETag will be used for the caching mechanism of the HTTP clients. The static files will send an ETag (which is the MD5 checksum of the file) to help the browser to detect, whether a file had been changed or not. The This also can be done for a dynamic file by setting an ETag (which must not be a MD5 checksum) and comparing it with the one send by the browser on further requests.

  #### Return value

  The Etag as const string.

  #### Remarks

  The default validity for a file with browser caching enabled is 5 minutes.
GetRangeCount
  If the HTTP client only requests a part of a file, he will send ranges to define what part. GetRangeCount() returns the number of ranges available for that request. The ranges values will be returned by GetRange() (see below). The application must only return the data for the requested ranges.

  #### Return value

  The number of ranges for the request. If 0, there are no ranges for that request. In that case, the application must return the whole file.
GetRange
  Returns the range with teh given index. See IWebserverGetRange for details.

  #### Parameters

  size_t idx | The index of the range to get, zero based. Must not exceed IWebserverGet::GetRangeCount() - 1.

  #### Return value

  An IWebserverGetRange instance holding the range informations.

  #### Remarks

  The returned IWebserverGetRange instance is managed by the IWebserverGet instance. The data hold by IWebserverGetRange will be valid until the next time GetRange() will be called. If the range needed to be saved for later use, the application must store the data elsewhere.
  You must not free the IWebserverGetRange instance returned by IWebserverGet.
IsSysClientAuthenticated
  Returns the information, if a localhost connection between the AppManager and the Webserver is authenticated. Generally there is no need to use that function in your app.

  #### Return value

  True, if authenticated, else false.
Cancel
  Sometimes an application can not know if a request should be accepted or not at the moment, the request leads to a listen result. For that cases, the request can still be canceled inside the UWebserverGet instance by calling IWebserverGet::Cancel(). However, this function can also be used to cancel an already started byte transfer for the response. This comes in handy, when there is need to cancel a chunk encoded response or even a response with known content length.

  #### Parameters

  wsr_cancel_type_t reason | The reason for the cancel. See wsr_cancel_type_t for more details.

  #### Remarks

  Cancel() will call Close() after sending the informations to the Webserver.
SetTransferInfo
  Before responding for a GET request, the type of the request must set first by calling SetTransferInfo().

  #### Parameters

  wsr_type_t resourceType | The type of the resource the application is going to send. Dis should combine with the type of resource requested. The helper function GetResponseTypeForFileName can be used to get the right resource type depending on the resource suffix.
  ulong64 dataSize | The data size of the requests data. If unknown, the application must used chunked encoding by setting dataSize to WS_RESPONSE_CHUNKED.
  wsr_flags_t flags | (Default WSP_FLAG_NONE)Optional, additional flags. See wsr_flags_t for details.
  const char * etag | (Default nullptr) An optional ETag used for caching purposed of an HTTP client.

  #### Remarks

  When passing an ETag value, the HTTP clients caching mechanism will be activated. The default validity for a file with browser caching enabled is 5 minutes. So in that time, the HTTP client won't ask again for the file but loads it from it's local cache. The time period is fixed and cannot be changed.
SetTransferRange
  When the HTTP client requests a range only, the response must define the range sent.

  #### Parameters

  ulong64 rangeStart | The start of the range.
  ulong64 rangeEnd | The end of the range.

  #### Remarks

  The values of rangeStart and rangeEnd depends on the requested range. See IWebserverGetRange for details.
ForceDownloadResponse
  Generally, when requesting a file with the GET request, the HTTP client will save the file under the requested name. Sometimes there is need to save the file under an other name. This can be realized using ForeceDownloadResponse() to set the file name.

  #### Parameters

  const char * fileName | (Default nullptr) The filename the HTTP client should use. If set to nullptr, the same filename as requested will be used. That's practically the same as not calling ForceDownloadResponse().

Send
  Sends the given data. The number of bytes that will be send must be the same as given to SetTransferInfo() (unless WS_RESPONSE_CHUNKED has passed as dataSize to SetTransferInfo()). If the data the application will send exceeds WS_MAX_DATA_SIZE, multiple Send() calls must be used.

  #### Parameters

  void * buffer | A pointer to the buffer holding the data to send.
  size_t len | Then umber of bytes to send.

  #### Callbacks

  After the data had been sent, the UWebserverGet::WebserverGetSendResult() of the user passed to IWenserverPlugin::Accept() will be called.

  #### Remarks

  SendTransferInfo() must be called before calling Send() the first time!
  Trying to send more than WS_MAX_DATA_SIZE with one send call leads to an assertion.
  It is highly recommended send the next data part after receiving UWebserverGet::WebserverPluginSendResult().
Close
  Closes the IWebserverGet interface and with this also finalizes the response. It should be called after the number of bytes passed to SetTransferInfo() or after the last data part for chunked transfer had been sent. An HTTP client will not realize the end of the transfer and still wait for data, until Close() had been called. If the transfer of the response data should be canceled, IWebserverGet::Cancel() need to be called.

  #### Callbacks

  After closing, UWebserverGet::WebserverGetCloseComplete() will be called.

## IWebserverGetRange

    class IWebserverGetRange {
    public:
        IWebserverGetRange() {}
        virtual ~IWebserverGetRange() {}

        enum range_type_t {
            RANGE_NONE       = 0x00,
            RANGE_START_END  = 0x01,
            RANGE_START_ONLY = 0x02,
            RANGE_LAST_BYTES = 0x03
        } rangeType;

        ulong64 start;
        ulong64 end;
    };

### Overview

Sometimes, a HTTP client will request only a range of a resource. In that case, one or more range informations can be received from the IWebserverGet instance. That informations will be stored inside a IWebserverGetRange and returned to the app.

### Remarks

The application must not free an IWebserverGetRange instance received from UWebserverGet::GetRange().

### Public fields

start
  The start of the range in bytes. The value depends on the range type.
end
  The end of the range in bytes. The value depends on the range type.
rangeType
  There are different types of ranges defined by this type, which will be one of the following values:

  RANGE_NONE | No range defined. This generally is only for initializing purpose and will never show up in an IWebserverGetRange instance returned by IWebserverGet::GetRange().
  RANGE_START_END | The value of start and end are the byte positions where to start and end the transfer inside the resource. If end is out of range of the resource size, the real end position should be used.
  RANGE_START_ONLY | The value of start defines the byte position, where to start the transfer inside the resource. End will be the rest of data inside the resource.
  RANGE_LAST_BYTES | The number of the lst bytes of the resource to transfer. With this, the start position is resource end - number of last bytes.

## UWebserverGet

    class UWebserverGet {
    public:
        virtual ~UWebserverGet() {}

        virtual void WebserverGetRequestAcceptComplete(IWebserverGet * const webserverGet);
        virtual void WebserverGetSendResult(IWebserverGet * const webserverGet);
        virtual void WebserverGetCloseComplete(IWebserverGet * const webserverGet);
    };

### Overview

This is the user for a GET request handler. The application needs to implement the functions below.

### Remarks

The request can be responded asynchronously. But the application must take care sending the same number of bytes as defined before start sending data (if using streamed transfer) and closing the connection. Also the correct datatype and transfer info must be set before. If not, the browser (our whatever client) will wait for incoming data or at least recognize a transfer error. See IWebserverGet for more details.
Note that the application is responsible for releasing the UWebserverGet instance!

### Public functions

WebserverGetRequestAcceptComplete
  Will be called from the IWebserverPlugin Instance after the application accepts an incoming GET request. This will be the correct place to start answering the request. A derived class need to save the pointer of the given IWebserverGet instance for later use.

  #### Parameters

  IWebserverGet * const webserverGet | The calling IWebserverGet instance.

WebserverGetSendResult
  Will be called after a data package send by IWebserverGet::Send() had been send to the client by the Webserver itself.

  #### Parameters

  IWebserverGet * const webserverGet | The calling IWebserverGet instance.

WebserverGetCloseComplete
  Will be called after the connection had been called. This can be a result of calling IWebserverGet::Close() or because of a close initiated by the client. This function is the right place to clean up and release the UWebserverGet instance.

  #### Parameters

  IWebserverGet * const webserverGet | The calling IWebserverGet instance.

## IWebserverPost

    class IWebserverPost {
    public:
        virtual ~IWebserverPost() {}

        virtual const char * GetResourceName();
        virtual const char * GetRegisteredPathForRequest();
        virtual ulong64 GetDataSize();
        virtual bool DataIsChunkEncoded();
        virtual bool IsSysClientAuthenticated();

        virtual void SetTransferInfo(wsr_type_t resourceType, ulong64 dataSize, wsr_flags_t flags = WSP_FLAG_NONE, const char * etag = nullptr);
        virtual void ForceDownloadResponse(const char * fileName = nullptr);
        virtual void Cancel(wsr_cancel_type_t reason);
        virtual void Send(void * buffer, size_t len);
        virtual void Recv(void * buffer = nullptr, size_t len = 0);
        virtual void Close();
    };

### Overview

This handler is for handling POST requests. Note that for now the Webserver only supports POST requests which one set of data. If there is a form posted, the application itself need to divide the form data.

### Public functions

GetResourceName

  #### Return value

  The name of the resource for that request. The value returned is the same as passed to UWebserverPlugin::WebserverPluginHttpListenResult() as resourceName.
GetRegisteredPathForRequest

  #### Return value

  The name of the registered path for that request. The value returned is the same as passed to UWebserverPlugin::WebserverPluginHttpListenResult() as registeredPathForRequest.
GetDataSize

  #### Return value

  The number of bytes sent with the POST request. The data can be received by calling IWebserverPost::Recv(). If the data is chunk encoded, the size is unknown and 0 will be returned.
DataIsChunkEncoded

  #### Return value

  True if the data to receive is chunk encoded, else false.
IsSysClientAuthenticated
  Returns the information, if a localhost connection between the AppManager and the Webserver is authenticated. Generally there is no need to use that function in your app.

  #### Return value

  True, if authenticated, else false.
SetTransferInfo
  Before responding for a POST request, the type of the request must set first by calling SetTransferInfo().

  #### Parameters

  wsr_type_t resourceType | The type of the resource the application is going to send. Dis should combine with the type of resource requested. The helper function GetResponseTypeForFileName can be used to get the right resource type depending on the resource suffix.
  ulong64 dataSize | The data size of the requests data. If unknown, the application must used chunked encoding by setting dataSize to WS_RESPONSE_CHUNKED.
  wsr_flags_t flags | (Default WSP_FLAG_NONE)Optional, additional flags. See wsr_flags_t for details.
  const char * etag | (Default nullptr) An optional ETag used for caching purposed of an HTTP client.

  #### Remarks

  When passing an ETag value, the HTTP clients caching mechanism will be activated. The default validity for a file with browser caching enabled is 5 minutes. So in that time, the HTTP client won't ask again for the file but loads it from it's local cache. The time period is fixed and cannot be changed.
ForceDownloadResponse
  Generally, when requesting a file with the POST request, the HTTP client will save the file under the requested name. Sometimes there is need to save the file under an other name. This can be realized using ForeceDownloadResponse() to set the file name.

  #### Parameters

  const char * fileName | (Default nullptr) The filename the HTTP client should use. If set to nullptr, the same filename as requested will be used. That's practically the same as not calling ForceDownloadResponse().

Cancel
  Cancels the POST request. If the application already started to send data, the transfer will be canceled. If not, calling Cancel() will be the same as calling IWebserverPlugin::Cancel() when receiving the request.

  #### Parameters

  wsr_cancel_type_t reason | The reason for canceling the request. See wsr_cancel_type_t for more details.

  #### Callbacks

  Because Cancel() also closes the transfer, UWebserverPost::WebserverPostCloseComplete() of the user passed to IWebserverPlugin::Accept() will be called. This is the right place to delete the IWebserverPost instance, because it will no longer be used.

  #### Remarks

  Cancel will automatically close the request. So there is no need to call close, too.
  The reason only will be of interest if the application not already started to send a response. If already started, the reason will be ignored.
Send
  Sends the give data to the client. Before calling Send(), SetTransferInfo() must be called. And if not called to enabled chunk encoded transfer, the application had to send the number of bytes as given to SetTransferInfo().

  #### Parameters

  void * buffer | The pointer to the buffer with the data to send. Must hold at least len byte of data.
  size_t len | The number bytes to send.

  #### Callbacks

  After the data had been sent, UWebserverPost::WebserverPostSendResult() of the user passed to IWenserverPlugin::Accept() will be called.

  #### Remarks

  The number of bytes to send must not exceed WS_MAX_DATA_SIZE, or an assertion will be thrown. If more than WS_MAX_DATA_SIZE need to be send, the application must call Send() multiple times.
Recv
  Receives data sent with the request.

  #### Parameters

  void * buffer | (Default: nullptr) The buffer to store the data to. Must be big enough to be able to receive len bytes of data.
  size_t len | (Default: 0) The number of bytes to receive. If buffer is not nullptr, len must be > 0.

  #### Return value

  #### Callbacks

  After the data had been read, UWebserverPost::WebserverPostRecvResult() of the user passed to IWebserverPlugin::Accept() will be called. If all data had been read, the WebserverPostRecvResult() will be called with nullptr as buffer and 0 as len.
  If buffer is nullptr, UWebserverPost::WebserverPostRecvBuffer() will be called to request the buffer to store the data to.

  #### Remarks

  If buffer is nullptr, the IWebserverPost will ask the application for a buffer of a given size when reading the data. This will be realized by the WebserverPostRecvBuffer() callback.
  If the data to read is chunk encoded, Recv() should be called (recommended without passing a buffer), until RecvResult() will called with nullptr as buffer and 0 as len. However, this also works for non chunk encoded transfer.
  The maximum data to read per Recv() call is WS_MAX_DATA_SIZE.
Close
  Closes the request. This also finalizes a chunk encoded response, so that the client will receive the information that all data had been transfered.

  #### Callbacks

  After the connection had been closed, UWebserverPost::WebserverPostCloseComplete() of the user passed to IWebserverPlugin::Accept() will be called. This is the right place to delete the IWebserverPost instance, because it will no longer be used.

## UWebserverPost

    class UWebserverPost {
    public:
        virtual ~UWebserverPost() {}

        virtual void WebserverPostRequestAcceptComplete(IWebserverPost * const webserverPost);
        virtual void WebserverPostSendResult(IWebserverPost * const webserverPost) {}
        virtual void WebserverPostRecvResult(IWebserverPost * const webserverPost, void * buffer, size_t len);
        virtual void * WebserverPostRecvBuffer(size_t len) { return nullptr; }
        virtual void WebserverPostCloseComplete(IWebserverPost * const webserverPost);
    };

### Overview

This is the user for a POST request handler. The application needs to implement the functions below. The UWebserverPost instance must be used to read the data posted and to send a response, if needed.

### Remarks

If sending a response, it can (and should) be done asynchronously. But the application must take care sending the same number of bytes as defined before start sending data (if using streamed transfer) and closing the connection. Also the correct datatype and transfer info must be set before. If not, the browser (our whatever client) will wait for incoming data or at least recognize a transfer error. See IWebserverPost for more details.
Note that the application is responsible for releasing the UWebserverPost instance!

### Public functions

WebserverPostRequestAcceptComplete
  Will be called from the IWebserverPlugin Instance after the application accepts an incoming POST request. This will be the correct place to start answering the request. A derived class need to save the pointer of the given IWebserverPost instance for later use.

  #### Parameters

  IWebserverPost * const webserverPost | The calling IWebserverPost instance.

WebserverPostSendResult
  Will be called after a data package send by IWebserverPost::Send() had been send to the client by the Webserver itself.

  #### Parameters

  IWebserverPost * const webserverPost | The calling IWebserverPost instance.

WebserverPostRecvResult
  Will be called after receiving data, initiated through IWebserverPost::Recv().

  #### Parameters

  IWebserverPost * const webserverPost | The calling IWebserverPost instance.
  void * buffer | The buffer holding the received data. Will be the same as passed to IWebserverPost::Recv() or returned by UWebserverPost::WebserverPostRecvBuffer(). Will be nullptr if there is no more data to receive.
  size_t len | The number of bytes received.

  #### Remarks

  Because the number of bytes to receive will be unknown if the data to receive is chunk encoded, a WebserverPostRecvResult() callback will be called with buffer nullptr and len 0. This remarks the end of the transfer. It also works for streamed data transfer. So it isn't necessary to count the number of bytes received (except the application has further usage for that informations like realizing a progress bar).
WebserverPostRecvBuffer
  If IWebserverPost::Recv() will be called with buffer = nullptr, the IWebserverPost handler will call this function to request a buffer to store the data.

  #### Parameters

  size_t len | The number of bytes to transfer. The returned buffer must provide at least that size.

  #### Return value

  The buffer to store the data to. Must not be nullptr.
WebserverPostCloseComplete
  Will be called after the connection had been called. This can be a result of calling IWebserverPost::Close() or because of a close initiated by the client. This function is the right place to clean up and release the UWebserverPost instance.

  #### Parameters

  IWebserverPost * const webserverPost | The calling IWebserverPost instance.

## IWebserverPut

    class IWebserverPut {
    public:
        virtual ~IWebserverPut() {}

        virtual const char * GetResourceName();
        virtual const char * GetRegisteredPathForRequest();
        virtual ulong64 GetDataSize();
        virtual bool DataIsChunkEncoded();
        virtual const char * GetHeaderFieldValue(const char * fieldName);
        virtual bool IsSysClientAuthenticated();

        virtual void SetResultCode(ws_webdav_result_t result, ulong64 dataSize = 0);

        virtual void Cancel(wsr_cancel_type_t reason);
        virtual void Send(void * buffer, size_t len);
        virtual void Recv(void * buffer = nullptr, size_t len = 0);
        virtual void Close();
    };

### Overview

This handler is for handling PUT requests.

### Public functions

GetResourceName

  #### Return value

  The name of the resource for that request. The value returned is the same as passed to UWebserverPlugin::WebserverPluginHttpListenResult() as resourceName.
GetRegisteredPathForRequest

  #### Return value

  The name of the registered path for that request. The value returned is the same as passed to UWebserverPlugin::WebserverPluginHttpListenResult() as registeredPathForRequest.
GetDataSize

  #### Return value

  The number of bytes sent with the PUT request. The data can be received by calling IWebserverPut::Recv(). If the data is chunk encoded, the size is unknown and 0 will be returned.
DataIsChunkEncoded

  #### Return value

  True if the data to receive is chunk encoded, else false.
GetHeaderFieldValue
  Returns the value of the given header filed sent with the request.

  #### Parameters

  const char * fieldName | The name of the header field.

  #### Return value

  The value assigned to the header field or nullptr, if the requested header field doesn't exist.
IsSysClientAuthenticated
  Returns the information, if a localhost connection between the AppManager and the Webserver is authenticated. Generally there is no need to use that function in your app.

  #### Return value

  True, if authenticated, else false.
SetResultCode
  Set the result code and optionally the data size for the requests answer.

  #### Parameters

  ws_webdav_result_t result | The result code to set. See ws_webdav_result_t for details.
  ulong64 dataSize | The number of data that will be send. Pass WS_RESPONSE_CHUNKED to enabled chunk encoded transfer.

  #### Remarks

  SetResultCode() must be called before sending data or, in case that no data will be send, before closing the request.
  The application must send the exact number of bytes using Send(), as given to SetTransferInfo(). If not, the HTTP client may be waiting for ever or ending up in an HTTP parsing error.
  In chunk encoded mode, the application simply can send data as long as needed. When calling Close(), the chunk encoded transfer will be finalized.
Cancel
  Cancels the PUT request. If the application already started to send data, the transfer will be canceled. If not, calling Cancel() will be the same as calling IWebserverPlugin::Cancel() when receiving the request.

  #### Parameters

  wsr_cancel_type_t reason | The reason for canceling the request. See wsr_cancel_type_t for more details.

  #### Callbacks

  Because Cancel() also closes the transfer, UWebserverPut::WebserverPutCloseComplete() of the user passed to IWebserverPlugin::Accept() will be called. This is the right place to delete the IWebserverPut instance, because it will no longer be used.

  #### Remarks

  Cancel will automatically close the request. So there is no need to call close, too.
  The reason only will be of interest if the application not already started to send a response. If already started, the reason will be ignored.
Send
  Sends the give data to the client.

  #### Parameters

  void * buffer | The pointer to the buffer with the data to send. Must hold at least len byte of data.
  size_t len | The number bytes to send.

  #### Callbacks

  After the data had been sent, UWebserverPut::WebserverPutSendResult() of the user passed to IWebserverPlugin::Accept() will be called.

  #### Remarks

  Before calling Send(), SetResultCode() must be called. And, if not called to enabled chunk encoded transfer, the application had to send the number of bytes as given to SetResultCode(). The number of bytes to send must not exceed WS_MAX_DATA_SIZE, or an assertion will be thrown. If more than WS_MAX_DATA_SIZE need to be send, the application must call Send() multiple times.
Recv
  Receives data sent with the request.

  #### Parameters

  void * buffer | (Default: nullptr) The buffer to store the data to. Must be big enough to be able to receive len bytes of data.
  size_t len | (Default: 0) The number of bytes to receive. If buffer is not nullptr, len must be > 0.

  #### Return value

  #### Callbacks

  After the data had been read, UWebserverPut::WebserverPutRecvResult() of the user passed to IWebserverPlugin::Accept() will be called. If all data had been read, the WebserverPutRecvResult() will be called with nullptr as buffer and 0 as len.
  If buffer is nullptr, UWebserverPut::WebserverPutRecvBuffer() will be called to request the buffer to store the data to.

  #### Remarks

  If the data to read is chunk encoded, Recv() should be called (recommended without passing a buffer), until RecvResult() will called with nullptr as buffer and 0 as len. However, this also works for non chunk encoded transfer.
  The maximum data to read per Recv() call is WS_MAX_DATA_SIZE.
Close
  Closes the request. This also finalizes a chunk encoded response, so that the client will receive the information that all data had been transfered.

  #### Callbacks

  After the connection had been closed, UWebserverPut::WebserverPutCloseComplete() of the user passed to IWebserverPlugin::Accept() will be called. This is the right place to delete the IWebserverPut intance, because it will no longer be used.

## UWebserverPut

    class UWebserverPut {
    public:
        virtual ~UWebserverPut() {}

        virtual void WebserverPutRequestAcceptComplete(IWebserverPut * const webserverPut);
        virtual void WebserverPutSendResult(IWebserverPut * const webserverPut);
        virtual void WebserverPutRecvResult(IWebserverPut * const webserverPut, void * buffer, size_t len);
        virtual void * WebserverPutRecvBuffer(size_t len) { return nullptr; }
        virtual void WebserverPutCloseComplete(IWebserverPut * const webserverPut);
    };

### Overview

This is the user for a PUT request handler. The application needs to implement the functions below. The UWebserverPut instance must be used to read the data send with the request, if needed.

### Remarks

If sending a response, it can (and should) be done asynchronously. But the application must take care sending the same number of bytes as defined before start sending data (if using streamed transfer) and closing the connection. Also the correct datatype and transfer info must be set before. If not, the browser (our whatever client) will wait for incoming data or at least recognize a transfer error. See IWebserverPut for more details.
Note that the application is responsible for releasing the UWebserverPut instance!

### Public functions

WebserverPutRequestAcceptComplete
  Will be called from the IWebserverPlugin Instance after the application accepts an incoming PUT request. This will be the correct place to start answering the request. A derived class need to save the pointer of the given IWebserverPut instance for later use.

  #### Parameters

  IWebserverPut * const webserverPut | The calling IWebserverPut instance.

WebserverPutSendResult
  Will be called after a data package send by IWebserverPut::Send() had been send to the client by the Webserver itself.

  #### Parameters

  IWebserverPut * const webserverPut | The calling IWebserverPut instance.

WebserverPutRecvResult
  Will be called after receiving data, initiated through IWebserverPut::Recv().

  #### Parameters

  IWebserverPut * const webserverPut | The calling IWebserverPut instance.
  void * buffer | The buffer holding the received data. Will be the same as passed to IWebserverPut::Recv() or returned by UWebserverPut::WebserverPutRecvBuffer(). Will be nullptr if there is no more data to receive.
  size_t len | The number of bytes received.

  #### Remarks

  Because the number of bytes to receive will be unknown if the data to receive is chunk encoded, a WebserverPutRecvResult() callback will be called with buffer nullptr and len 0. This remarks the end of the transfer. It also works for streamed data transfer. So it isn't necessary to count the number of bytes received (except the application has further usage for that informations like realizing a progress bar).
WebserverPutRecvBuffer
  If IWebserverPut::Recv() will be called with buffer = nullptr, the IWebserverPut handler will call this function to request a buffer to store the data.

  #### Parameters

  size_t len | The number of bytes to transfer. The returned buffer must provide at least that size.

  #### Return value

  The buffer to store the data to. Must not be nullptr.
WebserverPutCloseComplete
  Will be called after the connection had been closed. This can be a result of calling IWebserverPut::Close() or because of a close initiated by the client. This function is the right place to clean up and release the UWebserverPut instance.

  #### Parameters

  IWebserverPut * const webserverPut | The calling IWebserverPut instance.

## IWebserverPropfind

    class IWebserverPropfind {
    public:
        virtual ~IWebserverPropfind() {}

        virtual const char * GetResourceName();
        virtual const char * GetRegisteredPathForRequest();
        virtual ulong64 GetDataSize();
        virtual bool DataIsChunkEncoded();
        virtual const char * GetHeaderFieldValue(const char * fieldName);

        virtual void SetResultCode(ws_webdav_result_t result, ulong64 dataSize = 0);
        virtual void Cancel(wsr_cancel_type_t reason);
        virtual void Recv(void * buffer = nullptr, size_t len = 0);
        virtual void Send(void * buffer, size_t len);
        virtual void Close();
    };

### Overview

This handler is for handling PROPFIND requests.

### Public functions

GetResourceName

  #### Return value

  The name of the resource for that request. The value returned is the same as passed to UWebserverPlugin::WebserverPluginHttpListenResult() as resourceName.
GetRegisteredPathForRequest

  #### Return value

  The name of the registered path for that request. The value returned is the same as passed to UWebserverPlugin::WebserverPluginHttpListenResult() as registeredPathForRequest.
GetDataSize

  #### Return value

  The number of bytes sent with the PROPFIND request. The data can be received by calling IWebserverPropfind::Recv(). If the data is chunk encoded, the size is unknown and 0 will be returned.
DataIsChunkEncoded

  #### Return value

  True if the data to receive is chunk encoded, else false.
GetHeaderFieldValue
  Returns the value of the given header filed sent with the request.

  #### Parameters

  const char * fieldName | The name of the header field.

  #### Return value

  The value assigned to the header field or nullptr, if the requested header field doesn't exist.
SetResultCode
  Set the result code and optionally the data size for the requests answer.

  #### Parameters

  ws_webdav_result_t result | The result code to set. See ws_webdav_result_t for details.
  ulong64 dataSize | The number of data that will be send. Pass WS_RESPONSE_CHUNKED to enabled chunk encoded transfer.

  #### Remarks

  SetResultCode() must be called before sending data or, in case that no data will be send, before closing the request.
  The application must send the exact number of bytes using Send(), as given to SetTransferInfo(). If not, the HTTP client may be waiting for ever or ending up in an HTTP parsing error.
  In chunk encoded mode, the application simply can send data as long as needed. When calling Close(), the chunk encoded transfer will be finalized.
Cancel
  Cancels the PROPFIND request. If the application already started to send data, the transfer will be canceled. If not, calling Cancel() will be the same as calling IWebserverPlugin::Cancel() when receiving the request.

  #### Parameters

  wsr_cancel_type_t reason | The reason for canceling the request. See wsr_cancel_type_t for more details.

  #### Callbacks

  Because Cancel() also closes the transfer, UWebserverPropfind::WebserverPropfindCloseComplete() of the user passed to IWebserverPlugin::Accept() will be called. This is the right place to delete the IWebserverPropfind instance, because it will no longer be used.

  #### Remarks

  Cancel will automatically close the request. So there is no need to call close, too.
  The reason only will be of interest if the application not already started to send a response. If already started, the reason will be ignored.
Send
  Sends the give data to the client.

  #### Parameters

  void * buffer | The pointer to the buffer with the data to send. Must hold at least len byte of data.
  size_t len | The number bytes to send.

  #### Callbacks

  After the data had been sent, UWebserverPropfind::WebserverPropfindSendResult() of the user passed to IWebserverPlugin::Accept() will be called.

  #### Remarks

  Before calling Send(), SetResultCode() must be called. And, if not called to enabled chunk encoded transfer, the application had to send the number of bytes as given to SetResultCode(). The number of bytes to send must not exceed WS_MAX_DATA_SIZE, or an assertion will be thrown. If more than WS_MAX_DATA_SIZE need to be send, the application must call Send() multiple times.
Recv
  Receives data sent with the request.

  #### Parameters

  void * buffer | (Default: nullptr) The buffer to store the data to. Must be big enough to be able to receive len bytes of data.
  size_t len | (Default: 0) The number of bytes to receive. If buffer is not nullptr, len must be > 0.

  #### Return value

  #### Callbacks

  After the data had been read, UWebserverPropfind::WebserverPropfindRecvResult() of the user passed to IWebserverPlugin::Accept() will be called. If all data had been read, the WebserverPropfindRecvResult() will be called with nullptr as buffer and 0 as len.
  If buffer is nullptr, UWebserverPropfind::WebserverPropfindRecvBuffer() will be called to request the buffer to store the data to.

  #### Remarks

  If the data to read is chunk encoded, Recv() should be called (recommended without passing a buffer), until RecvResult() will called with nullptr as buffer and 0 as len. However, this also works for non chunk encoded transfer.
  The maximum data to read per Recv() call is WS_MAX_DATA_SIZE.
Close
  Closes the request. This also finalizes a chunk encoded response, so that the client will receive the information that all data had been transfered.

  #### Callbacks

  After the connection had been closed, UWebserverPropfind::WebserverPropfindCloseComplete() of the user passed to IWebserverPlugin::Accept() will be called. This is the right place to delete the IWebserverPropfind instance, because it will no longer be used.

## UWebserverPropfind

    class UWebserverPropfind {
    public:
        virtual ~UWebserverPropfind() {};
        virtual void WebserverPropfindRequestAcceptComplete(IWebserverPropfind * const webserverPropfind);
        virtual void WebserverPropfindSendResult(IWebserverPropfind * const webserverPropfind);
        virtual void WebserverPropfindRecvResult(IWebserverPropfind * const webserverPropfind, void * buffer, size_t len);
        virtual void * WebserverPropfindRecvBuffer(size_t len)
        {
            return nullptr;
        }

        virtual void WebserverPropfindCloseComplete(IWebserverPropfind * const webserverPropfind);
    };

### Overview

This is the user for a PROPFIND request handler. The application needs to implement the functions below. The UWebserverPropfind instance must be used to read the data send with the request, if needed.

### Remarks

If sending a response, it can (and should) be done asynchronously. But the application must take care sending the same number of bytes as defined before start sending data (if using streamed transfer) and closing the connection. Also the correct datatype and transfer info must be set before. If not, the browser (our whatever client) will wait for incoming data or at least recognize a transfer error. See IWebserverPropfind for more details.
Note that the application is responsible for releasing the UWebserverPropfind instance!

### Public functions

WebserverPropfindRequestAcceptComplete
  Will be called from the IWebserverPlugin Instance after the application accepts an incoming PROPFIND request. This will be the correct place to start answering the request. A derived class need to save the pointer of the given IWebserverPropfind instance for later use.

  #### Parameters

  IWebserverPropfind * const webserverPropfind | The calling IWebserverPropfind instance.

WebserverPropfindSendResult
  Will be called after a data package send by IWebserverPropfind::Send() had been send to the client by the Webserver itself.

  #### Parameters

  IWebserverPropfind * const webserverPropfind | The calling IWebserverPropfind instance.

WebserverPropfindRecvResult
  Will be called after receiving data, initiated through IWebserverPropfind::Recv().

  #### Parameters

  IWebserverPropfind * const webserverPropfind | The calling IWebserverPropfind instance.
  void * buffer | The buffer holding the received data. Will be the same as passed to IWebserverPropfind::Recv() or returned by UWebserverPropfind::WebserverPropfindRecvBuffer(). Will be nullptr if there is no more data to receive.
  size_t len | The number of bytes received.

  #### Remarks

  Because the number of bytes to receive will be unknown if the data to receive is chunk encoded, a WebserverPropfindRecvResult() callback will be called with buffer nullptr and len 0. This remarks the end of the transfer. It also works for streamed data transfer. So it isn't necessary to count the number of bytes received (except the application has further usage for that informations like realizing a progress bar).
WebserverPropfindRecvBuffer
  If IWebserverPropfind::Recv() will be called with buffer = nullptr, the IWebserverPropfind handler will call this function to request a buffer to store the data.

  #### Parameters

  size_t len | The number of bytes to transfer. The returned buffer must provide at least that size.

  #### Return value

  The buffer to store the data to. Must not be nullptr.
WebserverPropfindCloseComplete
  Will be called after the connection had been closed. This can be a result of calling IWebserverPropfind::Close() or because of a close initiated by the client. This function is the right place to clean up and release the UWebserverPropfind instance.

  #### Parameters

  IWebserverPropfind * const webserverPropfind | The calling IWebserverPropfind instance.

## IWebserverMove

    class IWebserverMove {
    public:

        virtual const char * GetResourceName();
        virtual const char * GetRegisteredPathForRequest();
        virtual const char * GetHeaderFieldValue(const char * fieldName);

        virtual void SetResultCode(ws_webdav_result_t result, ulong64 dataSize = 0);
        virtual void SetLocation(const char * location);
        virtual void Cancel(wsr_cancel_type_t reason);
        virtual void Send(void * buffer, size_t len);
        virtual void Close();
    };

### Overview

This handler is for handling MOVE requests.

### Public functions

GetResourceName

  #### Return value

  The name of the resource for that request. The value returned is the same as passed to UWebserverPlugin::WebserverPluginHttpListenResult() as resourceName.
GetRegisteredPathForRequest

  #### Return value

  The name of the registered path for that request. The value returned is the same as passed to UWebserverPlugin::WebserverPluginHttpListenResult() as registeredPathForRequest.
GetHeaderFieldValue
  Returns the value of the given header filed sent with the request.

  #### Parameters

  const char * fieldName | The name of the header field.

  #### Return value

  The value assigned to the header field or nullptr, if the requested header field doesn't exist.
SetResultCode
  Set the result code and optionally the data size for the requests answer.

  #### Remarks

  Note that SetLocation() must be called before sending data or closing the request.

  #### Parameters

  ws_webdav_result_t result | The result code to set. See ws_webdav_result_t for details.
  ulong64 dataSize | The number of data that will be send. Pass WS_RESPONSE_CHUNKED to enabled chunk encoded transfer.

  #### Remarks

  SetResultCode() must be called before sending data or, in case that no data will be send, before closing the request.
  The application must send the exact number of bytes using Send(), as given to SetTransferInfo(). If not, the HTTP client may be waiting for ever or ending up in an HTTP parsing error.
  In chunk encoded mode, the application simply can send data as long as needed. When calling Close(), the chunk encoded transfer will be finalized.
SetLocation
  Set the location the data / file had been moved to.

  #### Parameters

  const char * location | The new location of the data / file.

  #### Remarks

  SetResultCode() must be called before sending data or, in case that no data will be send, before closing the request.
  The application must send the exact number of bytes using Send(), as given to SetTransferInfo(). If not, the HTTP client may be waiting for ever or ending up in an HTTP parsing error.
  In chunk encoded mode, the application simply can send data as long as needed. When calling Close(), the chunk encoded transfer will be finalized.
Cancel
  Cancels the MOVE request. If the application already started to send data, the transfer will be canceled. If not, calling Cancel() will be the same as calling IWebserverPlugin::Cancel() when receiving the request.

  #### Parameters

  wsr_cancel_type_t reason | The reason for canceling the request. See wsr_cancel_type_t for more details.

  #### Callbacks

  Because Cancel() also closes the transfer, UWebserverMove::WebserverMoveCloseComplete() of the user passed to IWebserverPlugin::Accept() will be called. This is the right place to delete the IWebserverMove instance, because it will no longer be used.

  #### Remarks

  Cancel will automatically close the request. So there is no need to call close, too.
  The reason only will be of interest if the application not already started to send a response. If already started, the reason will be ignored.
Send
  Sends the give data to the client.

  #### Parameters

  void * buffer | The pointer to the buffer with the data to send. Must hold at least len byte of data.
  size_t len | The number bytes to send.

  #### Callbacks

  After the data had been sent, UWebserverMove::WebserverMoveSendResult() of the user passed to IWebserverPlugin::Accept() will be called.

  #### Remarks

  Before calling Send(), SetResultCode() must be called. And, if not called to enabled chunk encoded transfer, the application had to send the number of bytes as given to SetResultCode(). The number of bytes to send must not exceed WS_MAX_DATA_SIZE, or an assertion will be thrown. If more than WS_MAX_DATA_SIZE need to be send, the application must call Send() multiple times.
Close
  Closes the request. This also finalizes a chunk encoded response, so that the client will receive the information that all data had been transfered.

  #### Callbacks

  After the connection had been closed, UWebserverMove::WebserverMoveCloseComplete() of the user passed to IWebserverPlugin::Accept() will be called. This is the right place to delete the IWebserverMove instance, because it will no longer be used.

## UWebserverMove

    class UWebserverMove {
    public:
        virtual ~UWebserverMove() {};
        virtual void WebserverMoveRequestAcceptComplete(IWebserverMove * const webserverMove);
        virtual void WebserverMoveSendResult(IWebserverMove * const webserverMove);
        virtual void WebserverMoveCloseComplete(IWebserverMove * const webserverMove);
    };

### Overview

This is the user for a MOVE request handler. The application needs to implement the functions below.

### Remarks

If sending a response, it can (and should) be done asynchronously. But the application must take care sending the same number of bytes as defined before start sending data (if using streamed transfer) and closing the connection. Also the correct datatype and transfer info must be set before. If not, the browser (our whatever client) will wait for incoming data or at least recognize a transfer error. See IWebserverMove for more details.
Note that the application is responsible for releasing the UWebserverMove instance!

### Public functions

WebserverMoveRequestAcceptComplete
  Will be called from the IWebserverPlugin Instance after the application accepts an incoming MOVE request. This will be the correct place to start answering the request. A derived class need to save the pointer of the given IWebserverMove instance for later use.

  #### Parameters

  IWebserverMove * const webserverMove | The calling IWebserverMove instance.

WebserverMoveSendResult
  Will be called after a data package send by IWebserverMove::Send() had been send to the client by the Webserver itself.

  #### Parameters

  IWebserverMove * const webserverMove | The calling IWebserverMove instance.

WebserverMoveCloseComplete
  Will be called after the connection had been closed. This can be a result of calling IWebserverMove::Close() or because of a close initiated by the client. This function is the right place to clean up and release the UWebserverMove instance.

  #### Parameters

  IWebserverMove * const webserverMove | The calling IWebserverMove instance.

## IWebserverMkCol

    class IWebserverMkCol {
    public:
        virtual ~IWebserverMkCol() {}

        virtual const char * GetResourceName();
        virtual const char * GetRegisteredPathForRequest();
        virtual const char * GetHeaderFieldValue(const char * fieldName);

        virtual void SetResultCode(ws_webdav_result_t result, ulong64 dataSize = 0);
        virtual void SetLocation(const char * location);
        virtual void Cancel(wsr_cancel_type_t reason);
        virtual void Send(void * buffer, size_t len);
        virtual void Close();
    };

### Overview

This handler is for handling MKCOL requests.

### Public functions

GetResourceName

  #### Return value

  The name of the resource for that request. The value returned is the same as passed to UWebserverPlugin::WebserverPluginHttpListenResult() as resourceName.
GetRegisteredPathForRequest

  #### Return value

  The name of the registered path for that request. The value returned is the same as passed to UWebserverPlugin::WebserverPluginHttpListenResult() as registeredPathForRequest.
GetHeaderFieldValue
  Returns the value of the given header filed sent with the request.

  #### Parameters

  const char * fieldName | The name of the header field.

  #### Return value

  The value assigned to the header field or nullptr, if the requested header field doesn't exist.
SetResultCode
  Set the result code and optionally the data size for the requests answer.

  #### Parameters

  ws_webdav_result_t result | The result code to set. See ws_webdav_result_t for details.
  ulong64 dataSize | The number of data that will be send. Pass WS_RESPONSE_CHUNKED to enabled chunk encoded transfer.

  #### Remarks

  SetResultCode() must be called before sending data or, in case that no data will be send, before closing the request.
  The application must send the exact number of bytes using Send(), as given to SetTransferInfo(). If not, the HTTP client may be waiting for ever or ending up in an HTTP parsing error.
  In chunk encoded mode, the application simply can send data as long as needed. When calling Close(), the chunk encoded transfer will be finalized.
SetLocation
  Set the location the created collection.

  #### Remarks

  Note that SetLocation() must be called before sending data or closing the request.

  #### Parameters

  const char * location | The location of the created collection.

  #### Remarks

  SetResultCode() must be called before sending data or, in case that no data will be send, before closing the request.
  The application must send the exact number of bytes using Send(), as given to SetTransferInfo(). If not, the HTTP client may be waiting for ever or ending up in an HTTP parsing error.
  In chunk encoded mode, the application simply can send data as long as needed. When calling Close(), the chunk encoded transfer will be finalized.
Cancel
  Cancels the MKCOL request. If the application already started to send data, the transfer will be canceled. If not, calling Cancel() will be the same as calling IWebserverPlugin::Cancel() when receiving the request.

  #### Parameters

  wsr_cancel_type_t reason | The reason for canceling the request. See wsr_cancel_type_t for more details.

  #### Callbacks

  Because Cancel() also closes the transfer, UWebserverMkCol::WebserverMkColCloseComplete() of the user passed to IWebserverPlugin::Accept() will be called. This is the right place to delete the IWebserverMkCol instance, because it will no longer be used.

  #### Remarks

  Cancel will automatically close the request. So there is no need to call close, too.
  The reason only will be of interest if the application not already started to send a response. If already started, the reason will be ignored.
Send
  Sends the give data to the client.

  #### Parameters

  void * buffer | The pointer to the buffer with the data to send. Must hold at least len byte of data.
  size_t len | The number bytes to send.

  #### Callbacks

  After the data had been sent, UWebserverMkCol::WebserverMkColSendResult() of the user passed to IWebserverPlugin::Accept() will be called.

  #### Remarks

  Before calling Send(), SetResultCode() must be called. And, if not called to enabled chunk encoded transfer, the application had to send the number of bytes as given to SetResultCode(). The number of bytes to send must not exceed WS_MAX_DATA_SIZE, or an assertion will be thrown. If more than WS_MAX_DATA_SIZE need to be send, the application must call Send() multiple times.
Close
  Closes the request. This also finalizes a chunk encoded response, so that the client will receive the information that all data had been transfered.

  #### Callbacks

  After the connection had been closed, UWebserverMkCol::WebserverMkColCloseComplete() of the user passed to IWebserverPlugin::Accept() will be called. This is the right place to delete the IWebserverMkCol intance, because it will no longer be used.

## UWebserverMkCol

    class UWebserverMkCol {
    public:
        virtual ~UWebserverMkCol() {};
        virtual void WebserverMkColRequestAcceptComplete(IWebserverMkCol * const webserverMkCol);
        virtual void WebserverMkColSendResult(IWebserverMkCol * const webserverMkCol);
        virtual void WebserverMkColCloseComplete(IWebserverMkCol * const webserverMkCol);
    };

### Overview

This is the user for a MKCOL request handler. The application needs to implement the functions below.

### Remarks

If sending a response, it can (and should) be done asynchronously. But the application must take care sending the same number of bytes as defined before start sending data (if using streamed transfer) and closing the connection. Also the correct datatype and transfer info must be set before. If not, the browser (our whatever client) will wait for incoming data or at least recognize a transfer error. See IWebserverMkCol for more details.
Note that the application is responsible for releasing the UWebserverMkCol instance!

### Public functions

WebserverMkColRequestAcceptComplete
  Will be called from the IWebserverPlugin Instance after the application accepts an incoming MKCOL request. This will be the correct place to start answering the request. A derived class need to save the pointer of the given IWebserverMkCol instance for later use.

  #### Parameters

  IWebserverMkCol * const webserverMkCol | The calling IWebserverMkCol instance.

WebserverMkColSendResult
  Will be called after a data package send by IWebserverMkCol::Send() had been send to the client by the Webserver itself.

  #### Parameters

  IWebserverMkCol * const webserverMkCol | The calling IWebserverMkCol instance.

WebserverMkColCloseComplete
  Will be called after the connection had been closed. This can be a result of calling IWebserverMkCol::Close() or because of a close initiated by the client. This function is the right place to clean up and release the UWebserverMkCol instance.

  #### Parameters

  IWebserverMkCol * const webserverMkCol | The calling IWebserverMkCol instance.

## IWebserverCopy

    class IWebserverCopy {
    public:
        virtual ~IWebserverCopy() {}

        virtual const char * GetResourceName();
        virtual const char * GetRegisteredPathForRequest();
        virtual const char * GetHeaderFieldValue(const char * fieldName);

        virtual void Cancel(wsr_cancel_type_t reason);
        virtual void SetResultCode(ws_webdav_result_t result, ulong64 dataSize = 0);
        virtual void Send(void * buffer, size_t len);
        virtual void Close();
    };

### Overview

This handler is for handling COPY requests.

### Public functions

GetResourceName

  #### Return value

  The name of the resource for that request. The value returned is the same as passed to UWebserverPlugin::WebserverPluginHttpListenResult() as resourceName.
GetRegisteredPathForRequest

  #### Return value

  The name of the registered path for that request. The value returned is the same as passed to UWebserverPlugin::WebserverPluginHttpListenResult() as registeredPathForRequest.
GetHeaderFieldValue
  Returns the value of the given header filed sent with the request.

  #### Parameters

  const char * fieldName | The name of the header field.

  #### Return value

  The value assigned to the header field or nullptr, if the requested header field doesn't exist.
SetResultCode
  Set the result code and optionally the data size for the requests answer.

  #### Parameters

  ws_webdav_result_t result | The result code to set. See ws_webdav_result_t for details.
  ulong64 dataSize | The number of data that will be send. Pass WS_RESPONSE_CHUNKED to enabled chunk encoded transfer.

  #### Remarks

  SetResultCode() must be called before sending data or, in case that no data will be send, before closing the request.
  The application must send the exact number of bytes using Send(), as given to SetTransferInfo(). If not, the HTTP client may be waiting for ever or ending up in an HTTP parsing error.
  In chunk encoded mode, the application simply can send data as long as needed. When calling Close(), the chunk encoded transfer will be finalized.
Cancel
  Cancels the COPY request. If the application already started to send data, the transfer will be canceled. If not, calling Cancel() will be the same as calling IWebserverPlugin::Cancel() when receiving the request.

  #### Parameters

  wsr_cancel_type_t reason | The reason for canceling the request. See wsr_cancel_type_t for more details.

  #### Callbacks

  Because Cancel() also closes the transfer, UWebserverCopy::WebserverCopyCloseComplete() of the user passed to IWebserverPlugin::Accept() will be called. This is the right place to delete the IWebserverCopy instance, because it will no longer be used.

  #### Remarks

  Cancel will automatically close the request. So there is no need to call close, too.
  The reason only will be of interest if the application not already started to send a response. If already started, the reason will be ignored.
Send
  Sends the give data to the client.

  #### Parameters

  void * buffer | The pointer to the buffer with the data to send. Must hold at least len byte of data.
  size_t len | The number bytes to send.

  #### Callbacks

  After the data had been sent, UWebserverCopy::WebserverCopySendResult() of the user passed to IWebserverPlugin::Accept() will be called.

  #### Remarks

  Before calling Send(), SetResultCode() must be called. And, if not called to enabled chunk encoded transfer, the application had to send the number of bytes as given to SetResultCode(). The number of bytes to send must not exceed WS_MAX_DATA_SIZE, or an assertion will be thrown. If more than WS_MAX_DATA_SIZE need to be send, the application must call Send() multiple times.
Close
  Closes the request. This also finalizes a chunk encoded response, so that the client will receive the information that all data had been transfered.

  #### Callbacks

  After the connection had been closed, UWebserverCopy::WebserverCopyCloseComplete() of the user passed to IWebserverPlugin::Accept() will be called. This is the right place to delete the IWebserverCopy instance, because it will no longer be used.

## UWebserverCopy

    class UWebserverCopy {
    public:
        virtual ~UWebserverCopy() {};
        virtual void WebserverCopyRequestAcceptComplete(IWebserverCopy * const webserverCopy);
        virtual void WebserverCopySendResult(IWebserverCopy * const webserverCopy);
        virtual void WebserverCopyCloseComplete(IWebserverCopy * const webserverCopy);
    };

### Overview

This is the user for a COPY request handler. The application needs to implement the functions below.

### Remarks

If sending a response, it can (and should) be done asynchronously. But the application must take care sending the same number of bytes as defined before start sending data (if using streamed transfer) and closing the connection. Also the correct datatype and transfer info must be set before. If not, the browser (our whatever client) will wait for incoming data or at least recognize a transfer error. See IWebserverCopy for more details.
Note that the application is responsible for releasing the UWebserverCopy instance!

### Public functions

WebserverCopyRequestAcceptComplete
  Will be called from the IWebserverPlugin Instance after the application accepts an incoming COPY request. This will be the correct place to start answering the request. A derived class need to save the pointer of the given IWebserverCopy instance for later use.

  #### Parameters

  IWebserverCopy * const webserverCopy | The calling IWebserverCopy instance.

WebserverCopySendResult
  Will be called after a data package send by IWebserverCopy::Send() had been send to the client by the Webserver itself.

  #### Parameters

  IWebserverCopy * const webserverCopy | The calling IWebserverCopy instance.

WebserverCopyCloseComplete
  Will be called after the connection had been closed. This can be a result of calling IWebserverCopy::Close() or because of a close initiated by the client. This function is the right place to clean up and release the UWebserverCopy instance.

  #### Parameters

  IWebserverCopy * const webserverCopy | The calling IWebserverCopy instance.

## IWebserverDelete

    class IWebserverDelete {
    public:
        virtual ~IWebserverDelete() {}

        virtual const char * GetResourceName();
        virtual const char * GetRegisteredPathForRequest();
        virtual const char * GetHeaderFieldValue(const char * fieldName);

        virtual void Cancel(wsr_cancel_type_t reason);
        virtual void SetResultCode(ws_webdav_result_t result, ulong64 dataSize = 0);
        virtual void Send(void * buffer, size_t len);
        virtual void Close();
    };

### Overview

This handler is for handling DELETE requests.

### Public functions

GetResourceName

  #### Return value

  The name of the resource for that request. The value returned is the same as passed to UWebserverPlugin::WebserverPluginHttpListenResult() as resourceName.
GetRegisteredPathForRequest

  #### Return value

  The name of the registered path for that request. The value returned is the same as passed to UWebserverPlugin::WebserverPluginHttpListenResult() as registeredPathForRequest.
GetHeaderFieldValue
  Returns the value of the given header filed sent with the request.

  #### Parameters

  const char * fieldName | The name of the header field.

  #### Return value

  The value assigned to the header field or nullptr, if the requested header field doesn't exist.
SetResultCode
  Set the result code and optionally the data size for the requests answer.

  #### Parameters

  ws_webdav_result_t result | The result code to set. See ws_webdav_result_t for details.
  ulong64 dataSize | The number of data that will be send. Pass WS_RESPONSE_CHUNKED to enabled chunk encoded transfer.

  #### Remarks

  SetResultCode() must be called before sending data or, in case that no data will be send, before closing the request.
  The application must send the exact number of bytes using Send(), as given to SetTransferInfo(). If not, the HTTP client may be waiting for ever or ending up in an HTTP parsing error.
  In chunk encoded mode, the application simply can send data as long as needed. When calling Close(), the chunk encoded transfer will be finalized.
Cancel
  Cancels the DELETE request. If the application already started to send data, the transfer will be canceled. If not, calling Cancel() will be the same as calling IWebserverPlugin::Cancel() when receiving the request.

  #### Parameters

  wsr_cancel_type_t reason | The reason for canceling the request. See wsr_cancel_type_t for more details.

  #### Callbacks

  Because Cancel() also closes the transfer, UWebserverDelete::WebserverDeleteCloseComplete() of the user passed to IWebserverPlugin::Accept() will be called. This is the right place to delete the IWebserverDelete instance, because it will no longer be used.

  #### Remarks

  Cancel will automatically close the request. So there is no need to call close, too.
  The reason only will be of interest if the application not already started to send a response. If already started, the reason will be ignored.
Send
  Sends the give data to the client.

  #### Parameters

  void * buffer | The pointer to the buffer with the data to send. Must hold at least len byte of data.
  size_t len | The number bytes to send.

  #### Callbacks

  After the data had been sent, UWebserverDelete::WebserverDeleteSendResult() of the user passed to IWebserverPlugin::Accept() will be called.

  #### Remarks

  Before calling Send(), SetResultCode() must be called. And, if not called to enabled chunk encoded transfer, the application had to send the number of bytes as given to SetResultCode(). The number of bytes to send must not exceed WS_MAX_DATA_SIZE, or an assertion will be thrown. If more than WS_MAX_DATA_SIZE need to be send, the application must call Send() multiple times.
Close
  Closes the request. This also finalizes a chunk encoded response, so that the client will receive the information that all data had been transfered.

  #### Callbacks

  After the connection had been closed, UWebserverDelete::WebserverDeleteCloseComplete() of the user passed to IWebserverPlugin::Accept() will be called. This is the right place to delete the IWebserverDelete intance, because it will no longer be used.

## UWebserverDelete

    class UWebserverDelete {
    public:
        virtual ~UWebserverDelete() {};
        virtual void WebserverDeleteRequestAcceptComplete(IWebserverDelete * const webserverDelete);
        virtual void WebserverDeleteSendResult(IWebserverDelete * const webserverDelete);
        virtual void WebserverDeleteCloseComplete(IWebserverDelete * const webserverDelete);
    };

### Overview

This is the user for a DELETE request handler. The application needs to implement the functions below.

### Remarks

If sending a response, it can (and should) be done asynchronously. But the application must take care sending the same number of bytes as defined before start sending data (if using streamed transfer) and closing the connection. Also the correct datatype and transfer info must be set before. If not, the browser (our whatever client) will wait for incoming data or at least recognize a transfer error. See IWebserverDelete for more details.
Note that the application is responsible for releasing the UWebserverDelete instance!

### Public functions

WebserverDeleteRequestAcceptComplete
  Will be called from the IWebserverPlugin Instance after the application accepts an incoming DELETE request. This will be the correct place to start answering the request. A derived class need to save the pointer of the given IWebserverDelete instance for later use.

  #### Parameters

  IWebserverDelete * const webserverDelete | The calling IWebserverDelete instance.

WebserverDeleteSendResult
  Will be called after a data package send by IWebserverDelete::Send() had been send to the client by the Webserver itself.

  #### Parameters

  IWebserverDelete * const webserverDelete | The calling IWebserverDelete instance.

WebserverDeleteCloseComplete
  Will be called after the connection had been closed. This can be a result of calling IWebserverDelete::Close() or because of a close initiated by the client. This function is the right place to clean up and release the UWebserverDelete instance.

  #### Parameters

  IWebserverDelete * const webserverDelete | The calling IWebserverDelete instance.

## IWebserverLock

    class IWebserverLock {
    public:
        virtual ~IWebserverLock() {}

        virtual const char * GetResourceName();
        virtual const char * GetRegisteredPathForRequest();
        virtual const char * GetHeaderFieldValue(const char * fieldName);

        virtual void Cancel(wsr_cancel_type_t reason);
        virtual void SetResultCode(ws_webdav_result_t result, size_t dataSize = 0);
        virtual void Recv(void * buffer = nullptr, size_t len = 0);
        virtual void Send(void * buffer, size_t len);
        virtual void Close();
    };

### Overview

This handler is for handling LOCK requests.

### Public functions

GetResourceName

  #### Return value

  The name of the resource for that request. The value returned is the same as passed to UWebserverPlugin::WebserverPluginHttpListenResult() as resourceName.
GetRegisteredPathForRequest

  #### Return value

  The name of the registered path for that request. The value returned is the same as passed to UWebserverPlugin::WebserverPluginHttpListenResult() as registeredPathForRequest.
GetHeaderFieldValue
  Returns the value of the given header filed sent with the request.

  #### Parameters

  const char * fieldName | The name of the header field.

  #### Return value

  The value assigned to the header field or nullptr, if the requested header field doesn't exist.
SetResultCode
  Set the result code and optionally the data size for the requests answer.

  #### Parameters

  ws_webdav_result_t result | The result code to set. See ws_webdav_result_t for details.
  ulong64 dataSize | The number of data that will be send. Pass WS_RESPONSE_CHUNKED to enabled chunk encoded transfer.

  #### Remarks

  SetResultCode() must be called before sending data or, in case that no data will be send, before closing the request.
  The application must send the exact number of bytes using Send(), as given to SetTransferInfo(). If not, the HTTP client may be waiting for ever or ending up in an HTTP parsing error.
  In chunk encoded mode, the application simply can send data as long as needed. When calling Close(), the chunk encoded transfer will be finalized.
Cancel
  Cancels the LOCK request. If the application already started to send data, the transfer will be canceled. If not, calling Cancel() will be the same as calling IWebserverPlugin::Cancel() when receiving the request.

  #### Parameters

  wsr_cancel_type_t reason | The reason for canceling the request. See wsr_cancel_type_t for more details.

  #### Callbacks

  Because Cancel() also closes the transfer, UWebserverLock::WebserverLockCloseComplete() of the user passed to IWebserverPlugin::Accept() will be called. This is the right place to delete the IWebserverLock instance, because it will no longer be used.

  #### Remarks

  Cancel will automatically close the request. So there is no need to call close, too.
  The reason only will be of interest if the application not already started to send a response. If already started, the reason will be ignored.
Send
  Sends the give data to the client.

  #### Parameters

  void * buffer | The pointer to the buffer with the data to send. Must hold at least len byte of data.
  size_t len | The number bytes to send.

  #### Callbacks

  After the data had been sent, UWebserverLock::WebserverLockSendResult() of the user passed to IWebserverPlugin::Accept() will be called.

  #### Remarks

  Before calling Send(), SetResultCode() must be called. And, if not called to enabled chunk encoded transfer, the application had to send the number of bytes as given to SetResultCode(). The number of bytes to send must not exceed WS_MAX_DATA_SIZE, or an assertion will be thrown. If more than WS_MAX_DATA_SIZE need to be send, the application must call Send() multiple times.
Recv
  Receives data sent with the request.

  #### Parameters

  void * buffer | (Default: nullptr) The buffer to store the data to. Must be big enough to be able to receive len bytes of data.
  size_t len | (Default: 0) The number of bytes to receive. If buffer is not nullptr, len must be > 0.

  #### Return value

  #### Callbacks

  After the data had been read, UWebserverLock::WebserverLockRecvResult() of the user passed to IWebserverPlugin::Accept() will be called. If all data had been read, the WebserverLockRecvResult() will be called with nullptr as buffer and 0 as len.
  If buffer is nullptr, UWebserverLock::WebserverLockRecvBuffer() will be called to request the buffer to store the data to.

  #### Remarks

  If the data to read is chunk encoded, Recv() should be called (recommended without passing a buffer), until RecvResult() will called with nullptr as buffer and 0 as len. However, this also works for non chunk encoded transfer.
  The maximum data to read per Recv() call is WS_MAX_DATA_SIZE.
Close
  Closes the request. This also finalizes a chunk encoded response, so that the client will receive the information that all data had been transfered.

  #### Callbacks

  After the connection had been closed, UWebserverLock::WebserverLockCloseComplete() of the user passed to IWebserverPlugin::Accept() will be called. This is the right place to delete the IWebserverLock instance, because it will no longer be used.

## UWebserverLock

    class UWebserverLock {
    public:
        virtual ~UWebserverLock() {};
        virtual void WebserverLockRequestAcceptComplete(IWebserverLock * const webserverLock);
        virtual void WebserverLockSendResult(IWebserverLock * const webserverLock);
        virtual void WebserverLockRecvResult(IWebserverLock * const webserverLock, void * buffer, size_t len);
        virtual void * WebserverLockRecvBuffer(size_t len)
        {
            return nullptr;
        }
        virtual void WebserverLockCloseComplete(IWebserverLock * const webserverLock);
    };

### Overview

This is the user for a LOCK request handler. The application needs to implement the functions below. The UWebserverLock instance must be used to read the data send with the request, if needed.

### Remarks

If sending a response, it can (and should) be done asynchronously. But the application must take care sending the same number of bytes as defined before start sending data (if using streamed transfer) and closing the connection. Also the correct datatype and transfer info must be set before. If not, the browser (our whatever client) will wait for incoming data or at least recognize a transfer error. See IWebserverLock for more details.
Note that the application is responsible for releasing the UWebserverLock instance!

### Public functions

WebserverLockRequestAcceptComplete
  Will be called from the IWebserverPlugin Instance after the application accepts an incoming LOCK request. This will be the correct place to start answering the request. A derived class need to save the pointer of the given IWebserverLock instance for later use.

  #### Parameters

  IWebserverLock * const webserverLock | The calling IWebserverLock instance.

WebserverLockSendResult
  Will be called after a data package send by IWebserverLock::Send() had been send to the client by the Webserver itself.

  #### Parameters

  IWebserverLock * const webserverLock | The calling IWebserverLock instance.

WebserverLockRecvResult
  Will be called after receiving data, initiated through IWebserverLock::Recv().

  #### Parameters

  IWebserverLock * const webserverLock | The calling IWebserverLock instance.
  void * buffer | The buffer holding the received data. Will be the same as passed to IWebserverLock::Recv() or returned by UWebserverLock::WebserverLockRecvBuffer(). Will be nullptr if there is no more data to receive.
  size_t len | The number of bytes received.

  #### Remarks

  Because the number of bytes to receive will be unknown if the data to receive is chunk encoded, a WebserverLockRecvResult() callback will be called with buffer nullptr and len 0. This remarks the end of the transfer. It also works for streamed data transfer. So it isn't necessary to count the number of bytes received (except the application has further usage for that informations like realizing a progress bar).
WebserverLockRecvBuffer
  If IWebserverLock::Recv() will be called with buffer = nullptr, the IWebserverLock handler will call this function to request a buffer to store the data.

  #### Parameters

  size_t len | The number of bytes to transfer. The returned buffer must provide at least that size.

  #### Return value

  The buffer to store the data to. Must not be nullptr.
WebserverLockCloseComplete
  Will be called after the connection had been closed. This can be a result of calling IWebserverLock::Close() or because of a close initiated by the client. This function is the right place to clean up and release the UWebserverLock instance.

  #### Parameters

  IWebserverLock * const webserverLock | The calling IWebserverLock instance.

## IWebserverUnlock

    class IWebserverUnlock {
    public:
        virtual ~IWebserverUnlock() {}

        virtual const char * GetResourceName();
        virtual const char * GetRegisteredPathForRequest();
        virtual const char * GetHeaderFieldValue(const char * fieldName);

        virtual void Cancel(wsr_cancel_type_t reason);
        virtual void SetResultCode(ws_webdav_result_t result, ulong64 dataSize = 0);
        virtual void Send(void * buffer, size_t len);
        virtual void Close();
    };

### Overview

This handler is for handling UNLOCK requests.

### Public functions

GetResourceName

  #### Return value

  The name of the resource for that request. The value returned is the same as passed to UWebserverPlugin::WebserverPluginHttpListenResult() as resourceName.
GetRegisteredPathForRequest

  #### Return value

  The name of the registered path for that request. The value returned is the same as passed to UWebserverPlugin::WebserverPluginHttpListenResult() as registeredPathForRequest.
GetHeaderFieldValue
  Returns the value of the given header filed sent with the request.

  #### Parameters

  const char * fieldName | The name of the header field.

  #### Return value

  The value assigned to the header field or nullptr, if the requested header field doesn't exist.
SetResultCode
  Set the result code and optionally the data size for the requests answer.

  #### Parameters

  ws_webdav_result_t result | The result code to set. See ws_webdav_result_t for details.
  ulong64 dataSize | The number of data that will be send. Pass WS_RESPONSE_CHUNKED to enabled chunk encoded transfer.

  #### Remarks

  SetResultCode() must be called before sending data or, in case that no data will be send, before closing the request.
  The application must send the exact number of bytes using Send(), as given to SetTransferInfo(). If not, the HTTP client may be waiting for ever or ending up in an HTTP parsing error.
  In chunk encoded mode, the application simply can send data as long as needed. When calling Close(), the chunk encoded transfer will be finalized.
Cancel
  Cancels the UNLOCK request. If the application already started to send data, the transfer will be canceled. If not, calling Cancel() will be the same as calling IWebserverPlugin::Cancel() when receiving the request.

  #### Parameters

  wsr_cancel_type_t reason | The reason for canceling the request. See wsr_cancel_type_t for more details.

  #### Callbacks

  Because Cancel() also closes the transfer, UWebserverUnlock::WebserverUnlockCloseComplete() of the user passed to IWebserverPlugin::Accept() will be called. This is the right place to delete the IWebserverUnlock instance, because it will no longer be used.

  #### Remarks

  Cancel will automatically close the request. So there is no need to call close, too.
  The reason only will be of interest if the application not already started to send a response. If already started, the reason will be ignored.
Send
  Sends the give data to the client.

  #### Parameters

  void * buffer | The pointer to the buffer with the data to send. Must hold at least len byte of data.
  size_t len | The number bytes to send.

  #### Callbacks

  After the data had been sent, UWebserverUnlock::WebserverUnlockSendResult() of the user passed to IWebserverPlugin::Accept() will be called.

  #### Remarks

  Before calling Send(), SetResultCode() must be called. And, if not called to enabled chunk encoded transfer, the application had to send the number of bytes as given to SetResultCode(). The number of bytes to send must not exceed WS_MAX_DATA_SIZE, or an assertion will be thrown. If more than WS_MAX_DATA_SIZE need to be send, the application must call Send() multiple times.
Close
  Closes the request. This also finalizes a chunk encoded response, so that the client will receive the information that all data had been transfered.

  #### Callbacks

  After the connection had been closed, UWebserverUnlock::WebserverUnlockCloseComplete() of the user passed to IWebserverPlugin::Accept() will be called. This is the right place to delete the IWebserverUnlock instance, because it will no longer be used.

## UWebserverUnlock

    class UWebserverUnlock {
    public:
        virtual ~UWebserverUnlock() {};
        virtual void WebserverUnlockRequestAcceptComplete(IWebserverUnlock * const webserverUnlock);
        virtual void WebserverUnlockSendResult(IWebserverUnlock * const webserverUnlock);
        virtual void WebserverUnlockCloseComplete(IWebserverUnlock * const webserverUnlock);
    };

### Overview

This is the user for a UNLOCK request handler. The application needs to implement the functions below.

### Remarks

If sending a response, it can (and should) be done asynchronously. But the application must take care sending the same number of bytes as defined before start sending data (if using streamed transfer) and closing the connection. Also the correct datatype and transfer info must be set before. If not, the browser (our whatever client) will wait for incoming data or at least recognize a transfer error. See IWebserverUnlock for more details.
Note that the application is responsible for releasing the UWebserverUnlock instance!

### Public functions

WebserverUnlockRequestAcceptComplete
  Will be called from the IWebserverPlugin Instance after the application accepts an incoming UNLOCK request. This will be the correct place to start answering the request. A derived class need to save the pointer of the given IWebserverUnlock instance for later use.

  #### Parameters

  IWebserverUnlock * const webserverUnlock | The calling IWebserverUnlock instance.

WebserverUnlockSendResult
  Will be called after a data package send by IWebserverUnlock::Send() had been send to the client by the Webserver itself.

  #### Parameters

  IWebserverUnlock * const webserverUnlock | The calling IWebserverUnlock instance.

WebserverUnlockCloseComplete
  Will be called after the connection had been closed. This can be a result of calling IWebserverUnlock::Close() or because of a close initiated by the client. This function is the right place to clean up and release the UWebserverUnlock instance.

  #### Parameters

  IWebserverUnlock * const webserverUnlock | The calling IWebserverUnlock instance.

## IWebserverProppatch

    class IWebserverProppatch {
    public:
        virtual ~IWebserverProppatch() {}

        virtual const char * GetResourceName();
        virtual const char * GetRegisteredPathForRequest();
        virtual const char * GetHeaderFieldValue(const char * fieldName);

        virtual void Cancel(wsr_cancel_type_t reason);
        virtual void SetResultCode(ws_webdav_result_t result, ulong64 dataSize = 0);
        virtual void Recv(void * buffer = nullptr, size_t len = 0);
        virtual void Send(void * buffer, size_t len);
        virtual void Close();
    };

### Overview

This handler is for handling PROPPATCH requests.

### Public functions

GetResourceName

  #### Return value

  The name of the resource for that request. The value returned is the same as passed to UWebserverPlugin::WebserverPluginHttpListenResult() as resourceName.
GetRegisteredPathForRequest

  #### Return value

  The name of the registered path for that request. The value returned is the same as passed to UWebserverPlugin::WebserverPluginHttpListenResult() as registeredPathForRequest.
GetHeaderFieldValue
  Returns the value of the given header filed sent with the request.

  #### Parameters

  const char * fieldName | The name of the header field.

  #### Return value

  The value assigned to the header field or nullptr, if the requested header field doesn't exist.
SetResultCode
  Set the result code and optionally the data size for the requests answer.

  #### Parameters

  ws_webdav_result_t result | The result code to set. See ws_webdav_result_t for details.
  ulong64 dataSize | The number of data that will be send. Pass WS_RESPONSE_CHUNKED to enabled chunk encoded transfer.

  #### Remarks

  SetResultCode() must be called before sending data or, in case that no data will be send, before closing the request.
  The application must send the exact number of bytes using Send(), as given to SetTransferInfo(). If not, the HTTP client may be waiting for ever or ending up in an HTTP parsing error.
  In chunk encoded mode, the application simply can send data as long as needed. When calling Close(), the chunk encoded transfer will be finalized.
Cancel
  Cancels the PROPPATCH request. If the application already started to send data, the transfer will be canceled. If not, calling Cancel() will be the same as calling IWebserverPlugin::Cancel() when receiving the request.

  #### Parameters

  wsr_cancel_type_t reason | The reason for canceling the request. See wsr_cancel_type_t for more details.

  #### Callbacks

  Because Cancel() also closes the transfer, UWebserverProppatch::WebserverProppatchCloseComplete() of the user passed to IWebserverPlugin::Accept() will be called. This is the right place to delete the IWebserverProppatch instance, because it will no longer be used.

  #### Remarks

  Cancel will automatically close the request. So there is no need to call close, too.
  The reason only will be of interest if the application not already started to send a response. If already started, the reason will be ignored.
Send
  Sends the give data to the client.

  #### Parameters

  void * buffer | The pointer to the buffer with the data to send. Must hold at least len byte of data.
  size_t len | The number bytes to send.

  #### Callbacks

  After the data had been sent, UWebserverProppatch::WebserverProppatchSendResult() of the user passed to IWebserverPlugin::Accept() will be called.

  #### Remarks

  Before calling Send(), SetResultCode() must be called. And, if not called to enabled chunk encoded transfer, the application had to send the number of bytes as given to SetResultCode(). The number of bytes to send must not exceed WS_MAX_DATA_SIZE, or an assertion will be thrown. If more than WS_MAX_DATA_SIZE need to be send, the application must call Send() multiple times.
Recv
  Receives data sent with the request.

  #### Parameters

  void * buffer | (Default: nullptr) The buffer to store the data to. Must be big enough to be able to receive len bytes of data.
  size_t len | (Default: 0) The number of bytes to receive. If buffer is not nullptr, len must be > 0.

  #### Return value

  #### Callbacks

  After the data had been read, UWebserverProppatch::WebserverProppatchRecvResult() of the user passed to IWebserverPlugin::Accept() will be called. If all data had been read, the WebserverProppatchRecvResult() will be called with nullptr as buffer and 0 as len.
  If buffer is nullptr, UWebserverProppatch::WebserverProppatchRecvBuffer() will be called to request the buffer to store the data to.

  #### Remarks

  If the data to read is chunk encoded, Recv() should be called (recommended without passing a buffer), until RecvResult() will called with nullptr as buffer and 0 as len. However, this also works for non chunk encoded transfer.
  The maximum data to read per Recv() call is WS_MAX_DATA_SIZE.
Close
  Closes the request. This also finalizes a chunk encoded response, so that the client will receive the information that all data had been transfered.

  #### Callbacks

  After the connection had been closed, UWebserverProppatch::WebserverProppatchCloseComplete() of the user passed to IWebserverPlugin::Accept() will be called. This is the right place to delete the IWebserverProppatch instance, because it will no longer be used.

## UWebserverProppatch

    class UWebserverProppatch {
    public:
        virtual ~UWebserverProppatch() {};
        virtual void WebserverProppatchRequestAcceptComplete(IWebserverProppatch * const webserverProppatch);
        virtual void WebserverProppatchSendResult(IWebserverProppatch * const webserverProppatch);
        virtual void WebserverProppatchRecvResult(IWebserverProppatch * const webserverProppatch, void * buffer, size_t len);
        virtual void * WebserverProppatchRecvBuffer(size_t len)
        {
            return nullptr;
        }
        virtual void WebserverProppatchCloseComplete(IWebserverProppatch * const webserverProppatch);
    };

### Overview

This is the user for a PROPPATCH request handler. The application needs to implement the functions below. The UWebserverProppatch instance must be used to read the data send with the request, if needed.

### Remarks

If sending a response, it can (and should) be done asynchronously. But the application must take care sending the same number of bytes as defined before start sending data (if using streamed transfer) and closing the connection. Also the correct datatype and transfer info must be set before. If not, the browser (our whatever client) will wait for incoming data or at least recognize a transfer error. See IWebserverProppatch for more details.
Note that the application is responsible for releasing the UWebserverProppatch instance!

### Public functions

WebserverProppatchRequestAcceptComplete
  Will be called from the IWebserverPlugin Instance after the application accepts an incoming PROPPATCH request. This will be the correct place to start answering the request. A derived class need to save the pointer of the given IWebserverProppatch instance for later use.

  #### Parameters

  IWebserverProppatch * const webserverProppatch | The calling IWebserverProppatch instance.

WebserverProppatchSendResult
  Will be called after a data package send by IWebserverProppatch::Send() had been send to the client by the Webserver itself.

  #### Parameters

  IWebserverProppatch * const webserverProppatch | The calling IWebserverProppatch instance.

WebserverProppatchRecvResult
  Will be called after receiving data, initiated through IWebserverProppatch::Recv().

  #### Parameters

  IWebserverProppatch * const webserverProppatch | The calling IWebserverProppatch instance.
  void * buffer | The buffer holding the received data. Will be the same as passed to IWebserverProppatch::Recv() or returned by UWebserverProppatch::WebserverProppatchRecvBuffer(). Will be nullptr if there is no more data to receive.
  size_t len | The number of bytes received.

  #### Remarks

  Because the number of bytes to receive will be unknown if the data to receive is chunk encoded, a WebserverProppatchRecvResult() callback will be called with buffer nullptr and len 0. This remarks the end of the transfer. It also works for streamed data transfer. So it isn't necessary to count the number of bytes received (except the application has further usage for that informations like realizing a progress bar).
WebserverProppatchRecvBuffer
  If IWebserverProppatch::Recv() will be called with buffer = nullptr, the IWebserverProppatch handler will call this function to request a buffer to store the data.

  #### Parameters

  size_t len | The number of bytes to transfer. The returned buffer must provide at least that size.

  #### Return value

  The buffer to store the data to. Must not be nullptr.
WebserverProppatchCloseComplete
  Will be called after the connection had been closed. This can be a result of calling IWebserverProppatch::Close() or because of a close initiated by the client. This function is the right place to clean up and release the UWebserverProppatch instance.

  #### Parameters

  IWebserverProppatch * const webserverProppatch | The calling IWebserverProppatch instance.

## IWebserverOptions

    class IWebserverOptions {
    public:
        virtual ~IWebserverOptions() {}

        virtual const char * GetResourceName();
        virtual const char * GetRegisteredPathForRequest();

        virtual void SetSupportedRequests(dword requestList);
        virtual void Close();
    };

### Overview

This handler is for handling OPTIONS requests.

### Public functions

GetResourceName

  #### Return value

  The name of the resource for that request. The value returned is the same as passed to UWebserverPlugin::WebserverPluginHttpListenResult() as resourceName.
GetRegisteredPathForRequest

  #### Return value

  The name of the registered path for that request. The value returned is the same as passed to UWebserverPlugin::WebserverPluginHttpListenResult() as registeredPathForRequest.
SetSupportedRequests
  Set the bitfield of supported requests.

  #### Parameters

  dword requestList | Bitfield as dword with the supported webdav options. You should use the ws_request_type_t constants to build up the list.

  #### Remarks

  SetSupportedRequests() must be called before closing the request.
Close
  Closes the request. This also finalizes a chunk encoded response, so that the client will receive the information that all data had been transfered.

  #### Callbacks

  After the connection had been closed, UWebserverOptions::WebserverOptionsCloseComplete() of the user passed to IWebserverPlugin::Accept() will be called. This is the right place to delete the IWebserverOptions instance, because it will no longer be used.

## UWebserverOptions

    class UWebserverOptions {
    public:
        virtual ~UWebserverOptions() {}
        virtual void WebserverOptionsRequestAcceptComplete(IWebserverOptions * const webserverOptions)
        {
            webserverOptions->SetSupportedRequests(WS_REQUEST_GET | WS_REQUEST_POST | WS_REQUEST_PUT |
                                                   WS_REQUEST_PROPFIND | WS_REQUEST_MOVE | WS_REQUEST_COPY |
                                                   WS_REQUEST_MKCOL | WS_REQUEST_DELETE | WS_REQUEST_OPTIONS |
                                                   WS_REQUEST_LOCK | WS_REQUEST_UNLOCK | WS_REQUEST_PROPPATCH);
            webserverOptions->Close();
        }

        virtual void WebserverOptionsCloseComplete(IWebserverOptions * const webserverOptions);
    };

### Overview

This is the user for a OPTIONS request handler. The application needs to implement the functions below.

### Remarks

If sending a response, it can (and should) be done asynchronously. But the application must take care sending the same number of bytes as defined before start sending data (if using streamed transfer) and closing the connection. Also the correct datatype and transfer info must be set before. If not, the browser (our whatever client) will wait for incoming data or at least recognize a transfer error. See IWebserverOptions for more details.
Note that the application is responsible for releasing the UWebserverOptions instance!

### Public functions

WebserverOptionsRequestAcceptComplete
  Will be called from the IWebserverPlugin Instance after the application accepts an incoming OPTIONS request. This will be the correct place to start answering the request. A derived class need to save the pointer of the given IWebserverOptions instance for later use.

  #### remarks

  Note that the default implementation accepts all webdav request supported by the IWebserverPlugin and closes the request.

  #### Parameters

  IWebserverOptions * const webserverOptions | The calling IWebserverOptions instance.

WebserverOptionsCloseComplete
  Will be called after the connection had been closed. This can be a result of calling IWebserverOptions::Close() or because of a close initiated by the client. This function is the right place to clean up and release the UWebserverOptions instance.

  #### Parameters

  IWebserverOptions * const webserverOptions | The calling IWebserverOptions instance.

## IWebsocket

    class IWebsocket {
    public:
        virtual ~IWebsocket() {}

        virtual const char * GetHost();
        virtual const char * GetPath();
        virtual const char * GetHeaderFieldValue(const char * fieldName);
        virtual bool IsSysClientAuthenticated();
        virtual bool IsLocalHost();

        virtual void Send(const void * buffer, size_t len, bool text = true);
        virtual void Recv(void * buf = nullptr, size_t len = 0);
        virtual void Close();
    };

### Overview

This handler is for handling WebSocket requests. To get WebSocket requests the app must call IWebserverPlugin::WebsocketListen() must be called. An incoming WebSocket request will lead to the UWebserverPlugin::WebserverPluginWebsocketListenResult() callback. See IWebserverPlugin and UWebserverPlugin for details.

### Public functions

GetHost

  #### Remarks

  For WebSocket each request comes with the host that sends the request. Because that is a header value that can be manipulated, this information should not be used for security relevant things.

  #### Return value

  The host of the request.
GetPath

  #### Return value

  The requested WebSocket path relative to the root passed to IWebserverPlugin::WebsocketListen().
GetHeaderFieldValue
  Returns the value of the given header filed sent with the request.

  #### Parameters

  const char * fieldName | The name of the header field.

  #### Return value

  The value assigned to the header field or nullptr, if the requested header field doesn't exist.
IsSysClientAuthenticated
  Returns the information, if a localhost connection between the AppManager and the Webserver is authenticated. Generally there is no need to use that function in your app.

  #### Return value

  True, if authenticated, else false.
IsLocalHost
  Can be called if the app needs to know if the connection is a local host connection or not.

  #### Return value

  True if localhost, else false.
Send
  Sends the give data to the client.

  #### Parameters

  void * buffer | The pointer to the buffer with the data to send. Must hold at least len byte of data.
  size_t len | The number bytes to send.
  bool text | (Default true)If true, the type of the send data is text, else it is binary data.

  #### Callbacks

  After the data had been sent, UWebsocket::WebsocketSendResult() of the user passed to IWebserverPlugin::Accept() will be called.

  #### Remarks

  The IWebserverPlugin and the Webserver of the AppPlatform won't make a difference between binary or text data. But a calling Webserver client maybe will do it. So it will be a good idea to set the text flag to false if sending binary data.
  The maximum size of data that can be send at once is WS_MAX_DATA_SIZE.
Recv
  Receives data sent with the request.

  #### Parameters

  void * buffer | (Default: nullptr) The buffer to store the data to. Must be big enough to be able to receive len bytes of data.
  size_t len | (Default: 0) The number of bytes to receive. If buffer is not nullptr, len must be > 0.

  #### Callbacks

  After the data had been read, UWebsocket::WebsocketRecvResult() of the user passed to IWebserverPlugin::Accept() will be called.

  #### Remarks

  If called with a buffer an length, the callback will be called after receiving the amount of bytes given to Recv(). If the amount of bytes is unknown, Recv() should be called without a length and buffer.
  The maximum size of data that can be received at once is WS_MAX_DATA_SIZE.
Close
  Closes the WebSocket connection.

  #### Callbacks

  After the connection had been closed, UWebsocket::WebsocketCloseComplete() of the user passed to IWebserverPlugin::Accept() will be called. This is the right place to delete the IWebsocket instance, because it will no longer be used.

## UWebsocket

    class UWebsocket {
    public:
        virtual ~UWebsocket() {}
        virtual void WebsocketAcceptComplete(class IWebsocket * websocket);
        virtual void WebsocketSendResult(class IWebsocket * websocket);
        virtual void WebsocketRecvResult(class IWebsocket * websocket, void * buffer, size_t len, bool text, bool isFragmented);
        virtual void * WebsocketRecvBuffer(size_t len) { return nullptr; }
        virtual void WebsocketCloseComplete(class IWebsocket * websocket, ws_close_reason_t reason);
    };

### Overview

This is the user for a WebSocket request handler. The application needs to implement the functions below to realize WebSocket communication.

### Public functions

WebsocketRequestAcceptComplete
  Will be called from the IWebserverPlugin Instance after the application accepts an incoming WebSocket request. A derived class need to save the pointer of the given IWebsocket instance for later use.

  #### Parameters

  IWebsocket * const websocket | The calling IWebsocket instance.

WebsocketSendResult
  Will be called after a data package send by IWebsocket::Send() had been send to the client by the Webserver itself.

  #### Parameters

  IWebsocket * const websocket | The calling IWebsocket instance.

WebsocketRecvResult
  Will be called after receiving data, initiated through IWebsocket::Recv().

  #### Parameters

  IWebsocket * const websocket | The calling IWebsocket instance.
  void * buffer | The buffer holding the received data. Will be the same as passed to IWebsocket::Recv() or returned by UWebsocket::WebsocketRecvBuffer().
  size_t len | The number of bytes received.

WebsocketRecvBuffer
  If IWebsocket::Recv() will be called with buffer = nullptr, the IWebsocket handler will call this function to request a buffer to store the data.

  #### Parameters

  size_t len | The number of bytes to transfer. The returned buffer must provide at least that size.

  #### Return value

  The buffer to store the data to. Must not be nullptr.
WebsocketCloseComplete
  Will be called after the connection had been closed. This can be a result of calling IWebsocket::Close() or because of a close initiated by the client. This function is the right place to clean up and release the UWebsocket instance.

  #### Parameters

  IWebsocket * const websocket | The calling IWebsocket instance.

## IWebserverPassthrough

    class IWebserverPassthrough {
        public:
            virtual ~IWebserverPassthrough() {}

            virtual const char * GetResourceName();
            virtual const char * GetRegisteredPathForRequest();
            virtual bool IsEncryptedConnection();

            virtual void Send(void * buffer, size_t size);
            virtual void Recv(void * buffer = nullptr, size_t len = 0);
            virtual void Close();
        };

### Overview

This handler is for handling Passthrough requests.

### Remarks

The passthrough handler has a special role. Instead of the others, the Webserver doesn't make anything for passthrough requests. Like the name suggests, the raw communication will be passed through to the application. That means, that the application is responsible for handling the HTML protocol, which includes parsing and creating of a correct header. So generally there is no need to implement passthrough functionality to our application. On the other hand it can help to create apps with proxy functionality.
To receive passthrough requests, the application must call IWebserverPlugin::PassthroughListen(). An incoming request will call the UWebserverPlugin::WebserverPassthroughListenResult(). See IWebserverPlugin and UWebserverPlugin for details.

### Public functions

GetResourceName

  #### Return value

  The name of the resource for that request. The value returned is the same as passed to UWebserverPlugin::WebserverPluginPassthroughListenResult() as resourceName.
GetRegisteredPathForRequest

  #### Return value

  The name of the registered path for that request. The value returned is the same as passed to UWebserverPlugin::WebserverPluginPassthroughListenResult() as registeredPathForRequest.
IsEncryptedConnection
  Can be called to determine, if the connection is encrypted or not (which is the case if the client uses https://).

  #### Return value

  True, if the connection is encrypted, else false.

  #### Remarks

  The encryption is the only thing that still will be handled by the Webserver. So even if IsEncryptedConnection() returns true, the application don't need to decrypt the data or encrypt the response.
Send
  Sends the give data to the client.

  #### Parameters

  void * buffer | The pointer to the buffer with the data to send. Must hold at least len byte of data.
  size_t len | The number bytes to send.

  #### Callbacks

  After the data had been sent, UWebserverPassthrough::WebserverPassthroughSendResult() of the user passed to IWenserverPlugin::Accept() will be called.

  #### Remarks

  Because of the responsibility the application has of handling the HTTP protocol, the first part sent must be a valid HTTP header.
  The number of bytes to send must not exceed WS_MAX_DATA_SIZE, or an assertion will be thrown. If more than WS_MAX_DATA_SIZE need to be send, the application must call Send() multiple times.
Recv
  Receives data sent with the request.

  #### Parameters

  void * buffer | (Default: nullptr) The buffer to store the data to. Must be big enough to be able to receive len bytes of data.
  size_t len | (Default: 0) The number of bytes to receive. If buffer is not nullptr, len must be > 0.

  #### Callbacks

  After the data had been read, UWebserverPassthrough::WebserverPassthroughRecvResult() of the user passed to IWebserverPlugin::Accept() will be called. If all data had been read, the WebserverPassthroughRecvResult() will be called with nullptr as buffer and 0 as len.
  If buffer is nullptr, UWebserverPassthrough::WebserverPassthroughRecvBuffer() will be called to request the buffer to store the data to.

  #### Remarks

  If buffer is nullptr, the IWebserverPassthrough will ask the application for a buffer of a given size when reading the data. This will be realized by the WebserverPassthroughRecvBuffer() callback.
  Because of the nature of passthrough, the number of bytes to receive is unknown (at least until the HTML header had been read completely and the data will not be send chunk encoded). So it will be a good idea, to call Recv() without parameters to have some kind of partial read.
  The maximum data to read per Recv() call is WS_MAX_DATA_SIZE.
Close
  Closes the request. This tells the Webserver to close the socket connection, too.

  #### Callbacks

  After the connection had been closed, UWebserverPassthrough::WebserverPassthroughCloseComplete() of the user passed to IWebserverPlugin::Accept() will be called. This is the right place to delete the IWebserverPassthrough instance, because it will no longer be used.

## UWebserverPassthrough

    class UWebserverPassthrough {
    public:
        virtual ~UWebserverPassthrough() {}

        virtual void WebserverPassthroughRequestAcceptComplete(IWebserverPassthrough * const webserverPassthrough);
        virtual void WebserverPassthroughSendResult(IWebserverPassthrough * const webserverPassthrough);
        virtual void WebserverPassthroughRecvResult(IWebserverPassthrough * const webserverPassthrough, void * buffer, size_t len);
        virtual void * WebserverPassthroughRecvBuffer(size_t len) { return nullptr; }
        virtual void WebserverPassthroughCloseComplete(IWebserverPassthrough * const webserverPassthrough);
    };

### Overview

This is the user for a Passthrough request handler. The application needs to implement the functions below.

### Remarks

Note that the application is responsible for releasing the UWebserverPassthrough instance!

### Public functions

WebserverPassthroughRequestAcceptComplete
  Will be called from the IWebserverPlugin Instance after the application accepts an incoming Passthrough request. A derived class need to save the pointer of the given IWebserverPassthrough instance for later use.

  #### Parameters

  IWebserverPassthrough * const webserverPassthrough | The calling IWebserverPassthrough instance.

WebserverPassthroughSendResult
  Will be called after a data package send by IWebserverPassthrough::Send() had been send to the client by the Webserver itself.

  #### Parameters

  IWebserverPassthrough * const webserverPassthrough | The calling IWebserverPassthrough instance.

WebserverPassthroughRecvResult
  Will be called after receiving data, initiated through IWebserverPassthrough::Recv().

  #### Parameters

  IWebserverPassthrough * const webserverPassthrough | The calling IWebserverPassthrough instance.
  void * buffer | The buffer holding the received data. Will be the same as passed to IWebserverPassthrough::Recv() or returned by UWebserverPassthrough::WebserverPassthroughRecvBuffer().
  size_t len | The number of bytes received.

WebserverPassthroughRecvBuffer
  If IWebserverPassthrough::Recv() will be called with buffer = nullptr, the IWebserverPassthrough handler will call this function to request a buffer to store the data.

  #### Parameters

  size_t len | The number of bytes to transfer. The returned buffer must provide at least that size.

  #### Return value

  The buffer to store the data to. Must not be nullptr.
WebserverPassthroughCloseComplete
  Will be called after the connection had been called. This can be a result of calling IWebserverPassthrough::Close() or because of a close initiated by the client. This function is the right place to clean up and release the UWebserverPassthrough instance.

  #### Parameters

  IWebserverPassthrough * const webserverPassthrough | The calling IWebserverPassthrough instance.

# Data types

## Defines / Statics

WS_MAX_PATH_LENGTH | The maximum length for a path to register using one of the listen functions of IWebserverPlugin.
WS_MAX_DATA_SIZE | The maximum data size one Send() or Recv() call can transfer.
WS_RESPONSE_CHUNKED | Flag to define that a response should be sent to the client chunk encoded.

## wsr_cancel_type_t

    typedef enum {
        // Everything from 0 to 15 will be internal types
        WSP_CANCEL_NOT_FOUND = 0x10,
        WSP_CANCEL_BAD_REQUEST,
        WSP_CANCEL_UNAVAILABLE,
        WSP_CANCEL_MISSING_LENGTH,
        WSP_CANCEL_STREAM,
        WSP_CANCEL_ACCESS_DENIED,
        WSP_CANCEL_INTERNAL_ERROR
    } wsr_cancel_type_t;

### Overview

These types will be used to cancel a request. The request can be canceled anytime from the moment the request comes in until the request will be closed. Canceling a request will also close the request and let the Webserver close the connection to the client. The response the Webserver sends to the client depends on the values below passed to the Cancel() function of IWebserverPlugin (to cancel the incoming request) or of the request handler itself (to cancel an accepted request).

### Values

WSP_CANCEL_NOT_FOUND | The requested resource could not be found. Will send a HTTP 404 response to the client.
WSP_CANCEL_BAD_REQUEST | For some reason the request was malformed. Will send a HTTP 400 response to the client.
WSP_CANCEL_UNAVAILABLE | The requested resource is unavailable. Will send a HTTP 451 response to the client.
WSP_CANCEL_MISSING_LENGTH | The request comes without a content length field. Will send a HTTP 411 response to the client.
WSP_CANCEL_STREAM | Cancels an already started response stream. This is the only valid value to pass to cancel after the app started sending a response. Because canceling a stream normally means, that an error occurs, the Webserver will send a HTTP 500 response to the client, as long as the app has not send response data yet. If sending data (as stream or chunk encoded), the connection just will be closed by the Webserver.
WSP_CANCEL_ACCESS_DENIED | Access to the requested resource is denied. Will send a HTTP 402 response to the client.
WSP_CANCEL_INTERNAL_ERROR | An internal error occurred. Will send a HTTP 500 response to the client.

## wsp_path_type_t

    typedef enum {
        WSP_PATH_TYPE_HTTP,
        WSP_PATH_TYPE_WEBSOCKET,
        WSP_PATH_TYPE_PASSTHROUGH
    } wsp_path_type_t;

### Overview

This values will be passed to UWebserverPlugin::WebserverPluginRegisterPathResult() to tell for which listen call the callback had been called.

### Values

WSP_PATH_TYPE_HTTP | The result for a HttpListen() call.
WSP_PATH_TYPE_WEBSOCKET | The result for a WebsocketListen() call.
WSP_PATH_TYPE_PASSTHROUGH | The result for a PassthroughListen() call.

## ws_webdav_result_t

    typedef enum {
        WEBDAV_RESULT_OK = 0x100,
        WEBDAV_RESULT_CREATED,
        WEBDAV_RESULT_NO_CONTENT,
        WEBDAV_RESULT_MULTIPLE_STATUS,
        WEBDAV_RESULT_FORBIDDEN,
        WEBDAV_RESULT_METHOD_NOT_ALLOWED,
        WEBDAV_RESULT_CONFLICT,
        WEBDAV_RESULT_PRECONDITION_FAILED,
        WEBDAV_RESULT_LOCKED,
        WEBDAV_RESULT_BAD_GATEWAY,
        WEBDAV_RESULT_INSUFFICIENT_STORAGE
    } ws_webdav_result_t;

### Overview

This constants need to be send as result for each webdav handler. Sometimes the meaning of the values differ, depending what kind of WebDAV request needs to be answered.

### Values

WEBDAV_RESULT_OK | OPTIONS, LOCK, DELETE, POLL: The was successful. Will send a HTTP 200 response to the client.
WEBDAV_RESULT_CREATED | PUT, MKCOL: The resource was created successfully. MOVE: The resource was moved successfully. LOCK: The lock was done successfully. Will send a HTTP 201 response to the client.
WEBDAV_RESULT_NO_CONTENT | PUT, DELETE, UNLOCK, COPY, MOVE: A standard success status code, when no additional data need to been sent. Will send a HTTP 204 response to the client.
WEBDAV_RESULT_MULTIPLE_STATUS | PROPFIND, PROPPATCH, MKCOL, COPY, MOVE: Multiple status will be send with the response. Will send a HTTP 207 response to the client.
WEBDAV_RESULT_FORBIDDEN | All: The client does not have permission for the requested WebDAV method. Will send a HTTP 404 response to the client.
WEBDAV_RESULT_METHOD_NOT_ALLOWED | All: The method is not allowed for the resource. MKCOL: Can be used to tell the client, that the collection already exists an cannot be created. Will send a HTTP 405 response to the client.
WEBDAV_RESULT_CONFLICT | MKCOL, PROPPATCH, PUT: The WebDAV method could not be executed because of a conflict. Will send a HTTP 409 response to the client.
WEBDAV_RESULT_PRECONDITION_FAILED | COPY, MOVE: The server was unable to maintain the availability of the properties listed in the property behavior XML element. LOCK: The lock token could not be enforced. COPY, PUT: Evaluation of request header fields failed. Will send a HTTP 412 response to the client.
WEBDAV_RESULT_LOCKED | PROPPATCH, DELETE, MOVE: The method can not change the properties. LOCK: The resource is already locked. COPY: The resource was locked. Will send a HTTP 423 response to the client.
WEBDAV_RESULT_BAD_GATEWAY | All: The server (acting as gateway or proxy) received an invalid response from the upstream server. Will send a HTTP 502 response to the client.
WEBDAV_RESULT_INSUFFICIENT_STORAGE | PROPPATCH, MKCOL, COPY: The resource doesn't have enough space to execute the method. Will send a HTTP 507 response ot the client.

## wsr_type_t

    typedef enum {
        // Start of resource file types
        WSP_RESPONSE_NO_TYPE = 0x100,
        WSP_RESPONSE_BINARY,
        WSP_RESPONSE_JAVA,
        WSP_RESPONSE_WAV,
        WSP_RESPONSE_OGG,
        WSP_RESPONSE_MP3,
        WSP_RESPONSE_GIF,
        WSP_RESPONSE_PNG,
        WSP_RESPONSE_BMP,
        WSP_RESPONSE_ICON,
        WSP_RESPONSE_TTF,
        WSP_RESPONSE_EOT,
        WSP_RESPONSE_PDF,
        WSP_RESPONSE_TEXT,
        WSP_RESPONSE_XML,
        WSP_RESPONSE_CSS,
        WSP_RESPONSE_JAVASCRIPT,
        WSP_RESPONSE_JSON,
        WSP_RESPONSE_HTML,
        WSP_RESPONSE_SVG,
        WSP_RESPONSE_WOFF,
        WSP_RESPONSE_G711,
        WSP_RESPONSE_G722,
        WSP_RESPONSE_G729,
        WSP_RESPONSE_JPEG,
        WSP_RESPONSE_MP4,
        WSP_RESPONSE_WEBM,
        WSP_RESPONSE_PEM,
        WSP_RESPONSE_MOBILECONFIG,
        WSP_RESPONSE_CACHE_MANIFEST,
        WSP_RESPONSE_OPUS,
        WSP_RESPONSE_CSV,
    } wsr_type_t;

### Overview

When sending data for a GET request, the type of the resource send must be set in the response header. So the application must define the type of the data to send passing of the wsr_type_t values to IWebserverGet::SetTransferInfo(). The Webserver will set the appropriate MIME type for the Content-Type header field.
The names of that values are self-explanatory, except for WSP_RESPONSE_NO_TYPE (means that no MIME type will be set in the response header) and WSP_RESPONSE_BINARY (a general binary data stream with MIME type application/octet-stream).
An application can use the GetResponseTypeForFileName() function to determine the correct wsr_type_t value according to the filename suffix.

## wsp_close_reason_t

    typedef enum {
        WSP_NORMAL_CLOSE,                // The app itself initiated the shutdown
        WSP_REGISTER_PATH_INVALID,       // The given path is invalid
        WSP_WEBSOCKET_PATH_INVALID,      // The given WebSocket listen path is invalid.
        WSP_WEBSOCKET_PATH_ALREADY_LISTENING, // Someone already is listening to that path for WebSocket connections
        WSP_PATH_ALREADY_REGISTERD,      // A data provider already registered to that resource
        WSP_ADDRESS_INVALID,             // The address the application tried to connect to was invalid
        WSP_CONNECTION_ERROR             // An connection error occurred (see log, if exists),
    } wsp_close_reason_t;

### Overview

One of these values will be passed to UWebserverPlugin::WebserverPluginShutdownComplete() to determine the reason of the shutdown. This close reasons here are for the WebserverPlugin itself.

### Values

WSP_NORMAL_CLOSE | A normal shutdown, initiated by the application itself.
WSP_REGISTER_PATH_INVALID | The path given als applications root or passed to IWebserverPlugin::HttpListen() or IWebserverPlugin::PassthroughListen() is invalid.
WSP_WEBSOCKET_PATH_INVALID | The path als applications root or passed to IWebserverPlugin::WebsocketListen() is invalid.
WSP_WEBSOCKET_PATH_ALREADY_LISTENING | The application called IWebserverPlugin::WebsocketListen() for a path someone already is listening to.
WSP_PATH_ALREADY_REGISTERD | The application called IWebserverPlugin::HttpListen() or IWebserverPlugin::PassthroughListen() for a path someone already is registered to..
WSP_ADDRESS_INVALID | The address the application try to connect to communicate with the Webserver was invalid.
WSP_CONNECTION_ERROR | A connection error occurred (see log for details).

## ws_close_reason_t

    typedef enum {
        WSCR_NORMAL_CLOSE,
        WSCR_BUFFER_OVERFLOW,
        WSCR_SOCKET_LOST,
        WSCR_ERROR,
    } ws_close_reason_t;

### Overview

One of these values will be passed to UWebsocket::WebsocketCloseComplete() to determine the reason why the WebSocket connection had been closed. This values are for WebSocket only.

### Values

WSCR_NORMAL_CLOSE | A normal close, initialed by th application or the client.
WSCR_BUFFER_OVERFLOW | The connection had been closed because of an buffer overflow error.
WSCR_SOCKET_LOST | The socket used for the connection had been lost.
WSCR_ERROR | An error occurred. See log for details.

## ws_request_type_t

    typedef enum {
        WS_REQUEST_GET          = 0x0001,
        WS_REQUEST_POST         = 0x0002,
        WS_REQUEST_PUT          = 0x0004,
        WS_REQUEST_PASSTHROUGH  = 0x0008,
        WS_REQUEST_PROPFIND     = 0x0010,
        WS_REQUEST_MOVE         = 0x0020,
        WS_REQUEST_COPY         = 0x0040,
        WS_REQUEST_MKCOL        = 0x0080,
        WS_REQUEST_DELETE       = 0x0100,
        WS_REQUEST_OPTIONS      = 0x0200,
        WS_REQUEST_LOCK         = 0x0400,
        WS_REQUEST_UNLOCK       = 0x0800,
        WS_REQUEST_PROPPATCH    = 0x1000
    } ws_request_type_t;

### Overview

These values will be passed to UWebserverPlugin::WebserverPluginHttpListenResult() to define the type of th request. When accepting, the application must call IWebserverPlugin::Accept() with an appropriate request handler instance for that request.
Note: A request for a path the application is listening to buy calling IWebserverPlugin::PassthroughListen() before will lead to an UWebserverPlugin::WebserverPluginPassthroughListenResult() callback. The WS_REQUEST_PASSTHROUGH enum type will only be used internally and because of this never be passed to UWebserverPlugin::WebserverPluginHttpListenResult().

### Values

WS_REQUEST_GET | A GET request. Must be accepted with an UWebserverGet instance.
WS_REQUEST_POST | A POST request. Must be accepted with an UWebserverPost instance.
WS_REQUEST_PUT | A WebDAV PUT request. Must be accepted with an UWebserverPut instance.
WS_REQUEST_PASSTHROUGH | Used internally only by IWebserverPlugin. A passthrough request reaches the application through UWebserverPlugin::WebserverPluginPassthroughListenResult() and must be accepted with an UWebserverPassthrough instance.
WS_REQUEST_PROPFIND | A WebDAV PROPFIND request. Must be accepted with an UWebserverPropfind instance.
WS_REQUEST_MOVE | A WebDAV MOVE request. Must be accepted with an UWebserverMove instance.
WS_REQUEST_COPY | A WebDAV COPY request. Must be accepted with an UWebserverCopy instance.
WS_REQUEST_MKCOL | A WebDAV MKCOL request. Must be accepted with an UWebserverMkCol instance.
WS_REQUEST_DELETE | A WebDAV DELETE request. Must be accepted with an UWebserverDelete instance.
WS_REQUEST_OPTIONS | A WebDAV OPTIONS request. Must be accepted with an UWebserverOptions instance.
WS_REQUEST_LOCK | A WebDAV LOCK request. Must be accepted with an UWebserverLock instance.
WS_REQUEST_UNLOCK | A WebDAV UNLOCK request. Must be accepted with an UWebserverUnlock instance.
WS_REQUEST_PROPPATCH | A WebDAV PROPPATCH request. Must be accepted with an UWebserverProppatch instance.

## ws_update_auth_result_t

    typedef enum {
        WS_AUTH_DECACTIVATED,
        WS_AUTH_DYNAMIC,
        WS_AUTH_STATIC,
        WS_AUTH_ERR_PATH_NOT_LISTENING,
        WS_AUTH_ERR_PATH_INVALID
    } ws_update_auth_result_t;

### Overview

This are the results received by the Webserver when changing the configuration for authentication by using IWebserverPlugin::SetAuthConfig().

### Values

WS_AUTH_DECACTIVATED | The authentication for the given path had been deactivated.
WS_AUTH_DYNAMIC | The given path now uses dynamic authentication, which means that the Webserver will ask the app for username / password.
WS_AUTH_STATIC | The given path now uses static authentication with the username / password passed to the previous SetAuthConfig() call.
WS_AUTH_ERR_PATH_NOT_LISTENING | SetAuthConfig() had been called for a path without calling IWebserverPlugin::HTTPListen() first.
WS_AUTH_ERR_PATH_INVALID | SetAuthConfig() had been called for a path which doesn't belong to the IWebserverPlugin instance.

## IWebserverGetRange::range_type_t

    class IWebserverGetRange {
    public:
        enum range_type_t {
            RANGE_NONE       = 0x00,
            RANGE_START_END  = 0x01,
            RANGE_START_ONLY = 0x02,
            RANGE_LAST_BYTES = 0x03
        } rangeType;
    };

### Overview

This are values to define the type of the range received with a GET request.

### Values

RANGE_NONE | There is no range sent with the request. This value is only used internally.
RANGE_START_END | The range request defines the start and end bytes of the requested resource.
RANGE_START_ONLY | The range request defines the start byte inside the resource. The application must send the data starting from this byte on the rest of the resource.
RANGE_LAST_BYTES | The request defines the last bytes of the resource the application needs to send.

# Structures

## ws_type_sfx_t

    typedef struct {
        const char * sfx;
        wsr_type_t type;
    } ws_type_sfx_t;

    static const ws_type_sfx_t suffixes[] = {
        { "html", WSP_RESPONSE_HTML },
        { "htm", WSP_RESPONSE_HTML },
        { "css", WSP_RESPONSE_CSS },
        { "xml", WSP_RESPONSE_XML },
        { "xsl", WSP_RESPONSE_XML },
        { "js", WSP_RESPONSE_JAVASCRIPT },
        { "json", WSP_RESPONSE_JSON },
        { "ico", WSP_RESPONSE_ICON },
        { "bin", WSP_RESPONSE_BINARY },
        { "jar", WSP_RESPONSE_JAVA },
        { "png", WSP_RESPONSE_PNG },
        { "gif", WSP_RESPONSE_GIF },
        { "bmp", WSP_RESPONSE_BMP },
        { "pdf", WSP_RESPONSE_PDF },
        { "wav", WSP_RESPONSE_WAV },
        { "ogg", WSP_RESPONSE_OGG },
        { "mp3", WSP_RESPONSE_MP3 },
        { "txt", WSP_RESPONSE_TEXT },
        { "soap", WSP_RESPONSE_XML },
        { "svg", WSP_RESPONSE_SVG },
        { "ttf", WSP_RESPONSE_TTF },
        { "eot", WSP_RESPONSE_EOT },
        { "woff", WSP_RESPONSE_WOFF },
        { "woff2", WSP_RESPONSE_WOFF },
        { "g711a", WSP_RESPONSE_G711 },
        { "g711u", WSP_RESPONSE_G711 },
        { "g722", WSP_RESPONSE_G722 },
        { "g729", WSP_RESPONSE_G729 },
        { "jpeg", WSP_RESPONSE_JPEG },
        { "mp4", WSP_RESPONSE_MP4 },
        { "webm", WSP_RESPONSE_WEBM },
        { "pem", WSP_RESPONSE_PEM },
        { "mobileconfig", WSP_RESPONSE_MOBILECONFIG },
        { "appcache", WSP_RESPONSE_CACHE_MANIFEST },
        { "opus-nb", WSP_RESPONSE_OPUS },
        { "opus-wb", WSP_RESPONSE_OPUS },
        { "csv", WSP_RESPONSE_CSV },
    };

### Overview

This structure, in conjunction with the suffixes[] array, is used by GetResponseTypeForFileName() function to determine the correct wsr_type_t value depending on the suffix of a filename.

### Values

const char * sfx | The filename suffix.
wsr_type_t type | The wsr_type_t value for that suffix.

# Code Example

## IWebserverPlugin - IWebserverGet

    app::app(IIoMux * iomux)
        : iomux(iomux)
    {
        this->webserverPlugin = IWebserverPlugin::Create(iomux, this);
        this->webserverPlugin->RegisterForPath("/path/to/webserver", "/demoapp/main");
    }

    void app::WebserverPluginWebRequest(IWebserverPlugin * plugin, ws_request_type_t requestType, char * resourceName, ulong64 dataSize)
    {
        if (requestType != WS_REQUEST_GET || strcmp(resourceName, "myresource.png") != 0)
            plugin->Cancel(WSP_CANCEL_NOT_FOUND);
        else {
            plugin->Accept(new MyGetHandler);
        }
    }

    // ==== MyGetHandler

    class MyGetHandler {
    protected:
        char * dataBuffer;
        ulong64 dataSize;
        ulong64 dataSend;

    public:
        MyGetHandler() {}
        ~MyGetHandler() {}

        void WebserverGetRequestAcceptComplete(IWebserverGet * const webserverGet)
        {
            // We assume that there is a function that returns the HTTP file instance...
            httpfile * myFile = GetFileForName(webserverGet->GetResourceName());

            dataBuffer = myFile->GetData();
            dataSize = myFile->GetSize();
            dataSend = 0;

            webserverGet->SetTransferInfo(wsr_type_t(myFile->GetResourceType()),
                                          myFile->GetSize(),
                                          wsr_flags_t(myFile->GetFlags()));

            this->SendNextPart(webserverGet);

        }

        void WebserverGetSendResult(IWebserverGet * const webserverGet)
        {
            this->SendNextPart(webserverGet);
        }

        void SendNextPart(IWebserverGet * const webserverGet)
        {
            ulong64 dataSize = staticFile->GetSize();

            if (bytesSend < dataSize) {
                ulong64 dataSizeDiff = dataSize - bytesSend;
                ulong64 sendSize = dataSizeDiff > WS_MAX_DATA_SIZE ? WS_MAX_DATA_SIZE : dataSizeDiff;
                webserverGet->Send((void *)(dataBuffer + bytesSend), sendSize);
                bytesSend += sendSize;
                if (bytesSend == dataSize)
                    webserverGet->Close();
            }
        }

        void WebserverGetCloseComplete(IWebserverGet * const webserverGet)
        {
            delete webserverGet;
            delete this;
        }
    };

## IWebserverGet - IWebsocket

    app::app(IIoMux * iomux)
        : iomux(iomux)
    {
        this->webserverPlugin = IWebserverPlugin::Create(iomux, this);
        this->webserverPlugin->RegisterForPath("/path/to/webserver", "/demoapp/main");
        this->webserverPlugin->WebsocketListen();
    }

    void app::WebserverWebsocketListenResult(IWebserverPlugin * plugin, const char * path, const char * host)
    {
        if (strcmp(host, "some-bad-host.de") == 0)
            this->webserverPlugin->Accept(nullptr); // Deny connection.
        else
            this->webserverPlugin->Accept(new appWebsocket());
    }

    // appWebsocket - user for IWebsocket

    void appWebsocket::WebsocketAcceptComplete(class IWebsocket * websocket)
    {
        this->websocketInst = websocket;
    }

    void appWebsocket::WebsocketSendResult(class IWebsocket * websocket)
    {
        printf("Websocket data sent\n");
        this->websocketInst->Close();
    }

    void appWebsocket::WebsocketRecvResult(class IWebsocket * websocket, const void * buffer, size_t len, bool text)
    {
        printf("Websocket - received data (text = %s)\n", (text ? "true" : "false"));
        debug->HexDump(buffer, len);
        this->websocketInst->Send(buffer, len, text);
    }

    void appWebsocket::WebsocketCloseComplete(class IWebsocket * websocket, ws_close_reason_t reason)
    {
        delete this->websocketInst;
        delete this;
    }