= nng_http_handler_alloc(3http)
//
// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech>
// Copyright 2018 Capitar IT Group BV <info@capitar.com>
//
// This document is supplied under the terms of the MIT License, a
// copy of which should be located in the distribution where this
// file was obtained (LICENSE.txt).  A copy of the license may also be
// found online at https://opensource.org/licenses/MIT.
//

== NAME

nng_http_handler_alloc - allocate HTTP server handler

== SYNOPSIS

[source, c]
----
#include <nng/nng.h>
#include <nng/supplemental/http/http.h>

typedef struct nng_http_handler nng_http_handler;

int nng_http_handler_alloc(nng_http_handler **hp, const char *path,
    void (*func)(nng_aio *);

int nng_http_handler_alloc_directory(nng_http_handler **hp, const char *path,
    const char *dirname);

int nng_http_handler_alloc_file(nng_http_handler **hp, const char *path,
    const char *filename);

int nng_http_handler_alloc_redirect(nng_http_handler **hp, const char *path,
    uint16_t status, const char *location);

int nng_http_handler_alloc_static(nng_http_handler **hp, const char *path,
    const void *data, size_t size, const char *content_type);
----

== DESCRIPTION

The `nng_http_handler_alloc()` family of functions allocate a handler
which will be used to process requests coming into an HTTP server.
On success, a pointer to the handler is stored at the located pointed to
by _hp_.

Every handler has a Request-URI to which it refers, which is determined
by the _path_ argument.
Only the path component of the Request URI is
considered when determining whether the handler should be called.

Additionally each handler has a method it is registered to handle
(the default is `GET`, see
xref:nng_http_handler_set_method.3http.adoc[`nng_http_handler_set_method()`]), and
optionally a 'Host' header it can be matched against (see
xref:nng_http_handler_set_host.3http.adoc[`nng_http_handler_set_host()`]).

In some cases, a handler may reference a logical tree rather (directory)
rather than just a single element.
(See xref:nng_http_handler_set_tree.3http.adoc[`nng_http_handler_set_tree()`]).

=== Custom Handler

The generic (first) form of this creates a handler that uses a user-supplied
function to process HTTP requests.
This function uses the asynchronous I/O framework.
The function takes a pointer to an xref:nng_aio.5.adoc[`nng_aio`] structure.

The _aio_ will be passed with the following input values (retrieved with
xref:nng_aio_get_input.3.adoc[`nng_aio_get_input()`]):

   0: `nng_http_req *` __request__:: The client's HTTP request.
   1: `nng_http_handler *` __handler__:: Pointer to the handler object.
   2: `nng_http_conn *` __conn__:: The underlying HTTP connection.

The handler should create an `nng_http_res *` response (such as via
xref:nng_http_res_alloc.3http.adoc[`nng_http_res_alloc()`] or
xref:nng_http_res_alloc_error.3http.adoc[`nng_http_res_alloc_error()`]) and store that
in as the first output (index 0) with
xref:nng_aio_set_output.3.adoc[`nng_aio_set_output()`].

Alternatively, the handler may send the HTTP response (and any associated
body data) itself using the connection.
In that case the output at index 0 of the _aio_ should be NULL.

Finally, using the xref:nng_aio_finish.3.adoc[`nng_aio_finish()`] function, the
_aio_ should be completed successfully.
If any non-zero status is returned back to the caller instead,
then a generic 500 response will be created and
sent, if possible, and the connection will be closed.

The _aio_ may be scheduled for deferred completion using the
xref:nng_aio_defer.3.adoc[`nng_aio_defer()`] function.

NOTE: The callback function should *NOT* call
xref:nng_aio_begin.3.adoc[`nng_aio_begin()`],
as that will already have been done by the server framework.

=== Directory Handler

The second member of this family, `nng_http_handler_alloc_directory()`, creates
a handler configured to serve a directory tree.
The _uri_ is taken as the root, and files are served from the directory
tree rooted at _path_.

When the client Request-URI resolves to a directory in the file system,
the handler looks first for a file named `index.html` or `index.htm`.
If one is found, then that file is returned back to the client.
If no such index file exists, then an `NNG_HTTP_STATUS_NOT_FOUND` (404) error is
sent back to the client.

The `Content-Type` will be set automatically based upon the extension
of the requested file name.
If a content type cannot be determined from
the extension, then `application/octet-stream` is used.

=== File Handler

The third member of this family, `nng_http_handler_alloc_file()`, creates
a handler to serve up a single file; it does not traverse directories
or search for `index.html` or `index.htm` files.

The `Content-Type` will be set automatically based upon the extension
of the requested file name.
If a content type cannot be determined from
the extension, then `application/octet-stream` is used.

=== Redirect Handler

The fourth member is used to arrange for a server redirect from one
URL to another.
The reply will be with status code __status__, which should be a 3XX
code such as 301, and a `Location:` header will contain the URL
referenced by __location__, with any residual suffix from the request
URI appended.

TIP: Use xref:nng_http_handler_set_tree.3http.adoc[`nng_http_handler_set_tree()`]
to redirect an entire tree.
For example, it is possible to redirect an entire HTTP site to another
HTTPS site by specifying `/` as the path and then using the base
of the new site, such as `https://newsite.example.com` as the
new location.

TIP: Be sure to use the appropriate value for __status__.
Permanent redirection should use 301 and temporary redirections should use 307.
In REST APIs, using a redirection to supply the new location of an object
created with `POST` should use 303.

=== Static Handler

The fifth member of this family, `nng_http_handler_alloc_static()`, creates
a handler to serve up fixed content located in program data.
The client is
sent the _data_, with `Content-Length` of _size_ bytes, and `Content-Type` of
__content_type__.

== RETURN VALUES

These functions return 0 on success, and non-zero otherwise.

== ERRORS

[horizontal]
`NNG_EINVAL`:: An invalid _path_ was specified.
`NNG_ENOMEM`:: Insufficient free memory exists to allocate a message.
`NNG_ENOTSUP`:: No support for HTTP in the library.

== SEE ALSO

[.text-left]
xref:nng_aio_defer.3.adoc[nng_aio_defer(3)],
xref:nng_aio_finish.3.adoc[nng_aio_finish(3)],
xref:nng_aio_get_input.3.adoc[nng_aio_get_input(3)],
xref:nng_aio_set_output.3.adoc[nng_aio_set_output(3)],
xref:nng_http_handler_collect_body.3http.adoc[nng_http_handler_collect_body(3http)],
xref:nng_http_handler_free.3http.adoc[nng_http_handler_free(3http)],
xref:nng_http_handler_set_host.3http.adoc[nng_http_handler_set_host(3http)],
xref:nng_http_handler_set_method.3http.adoc[nng_http_handler_set_method(3http)],
xref:nng_http_handler_set_tree.3http.adoc[nng_http_handler_set_tree(3http)],
xref:nng_http_res_alloc.3http.adoc[nng_http_res_alloc(3http)],
xref:nng_http_res_alloc_error.3http.adoc[nng_http_res_alloc_error(3http)],
xref:nng_http_server_add_handler.3http.adoc[nng_http_server_add_handler(3http)],
xref:nng_strerror.3.adoc[nng_strerror(3)],
xref:nng_aio.5.adoc[nng_aio(5)],
xref:nng.7.adoc[nng(7)]
