zhangmeng
2024-04-22 16935f4aebffdd1b6580b844391a0aa0f4f3012b
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
= nng_http_handler_alloc(3http)
//
// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech>
// Copyright 2018 Capitar IT Group BV <info@capitar.com>
// Copyright 2020 Dirac Research <robert.bielik@dirac.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.
 
The directory handler is created as a tree handler initially in exclusive mode (see
xref:nng_http_handler_set_tree.3http.adoc[nng_http_handler_set_tree_exclusive]).
This can be changed by calling
xref:nng_http_handler_set_tree.3http.adoc[nng_http_handler_set_tree(3http)]
after creating the directory handler.
 
=== 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_handler_set_tree.3http.adoc[nng_http_handler_set_tree_exclusive(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)]