From 131726d96414aa1a35e8319db0785221e1230566 Mon Sep 17 00:00:00 2001
From: gdamore nng/nng.h header file like so:
nng_fini function. Each call to nng_fi
After calling nng_fini, the consuming application must not make any other calls to NNG functions,
except that it may use nng_init to initialize the application for further use.
+
@@ -1058,6 +1060,7 @@ while ((val64 = next_datum()) != 0) P
}
+
@@ -1589,6 +1592,7 @@ int main(int argc, char **argv) {
}
+
@@ -1889,6 +1893,7 @@ start_echo_service(nng_socket rep_socket)
}
+
@@ -2009,6 +2014,7 @@ one (for the NUL terminating byte).
can be used to deallocate strings allocated with nng_strdup.
It is effectively the same as nng_free(strlen(str) + 1).
More information about Universal Resource Locators can be found in RFC 3986.
+ @@ -2686,6 +2694,7 @@ and if necessary resubmit the operation with a suitably updated vector of
Streams,
Time
+
@@ -2895,6 +2904,7 @@ nng_mtx_unlock(m);
Time,
Asynchronous I/O
+
@@ -3040,6 +3050,7 @@ in debuggers. Not all platforms support setting the thread name.
Synchronization,
Asynchronous Operations
+
@@ -3493,6 +3504,7 @@ here is the same reference time used for See Also
+
@@ -3629,6 +3641,7 @@ as in diagnostic messages or log entries.
NNG_ETRANERR0x20000000 - 0x2FFFFFFF An unidentified transport error occurred.
+
@@ -4026,6 +4039,570 @@ They will return a pointer to the nng_tls_config<
both configuring a different TLS configuration object, as well as mutating the existing nng_tls_config object.
+
+
+
+
+
+
+HTTP Support
+NNG offers support for creation of HTTP clients, and servers. NNG supports HTTP/1.1 at present, and supports
+a subset of functionality, but the support should be sufficient for simple clients, REST API servers, static content servers,
+and gateways between HTTP and and other protocols. It also provides support for WebSocket based connections.
+HTTP follows a request/reply model, where a client issues a request, and the server is expected to reply.
+Every request is answered with a single reply.
+Header File
+#include <nng/http.h>
+
+Unlike the rest of NNG, the HTTP API in NNG requires including nng/http.h. It is not necessary to include
+the main nng/nng.h header, it will be included transitively by nng/http.h.
+Connection Object
+typedef struct nng_http nng_http;
+
+The nng_http object represents a single logical HTTP connection to the server.
+For HTTP/1.1 and earlier, this will correspond to a single TCP connection, but the object
+also contains state relating to the transaction, such as the hostname used, HTTP method used,
+request headers, response status, response headers, and so forth.
+An nng_http object can be reused, unless closed, so that additional transactions can be
+performed after the first transaction is complete.
+At any given point in time, an nng_http object can only refer to a single HTTP transaction.
+In NNG, these nng_http objects are used in both the client and server APIs.
+The nng_http object is created by either nng_http_client_connect or by an HTTP server
+object which then passes it to an [nng_http_handler] callback function.
+HTTP Method
+void nng_http_set_method(nng_http *conn, const char *method);
+const char *nng_http_get_method(nng_http *conn);
+
+Each HTTP transaction has a single verb, or method, that is used. The most common methods are “GET”, “HEAD”, and “POST”,
+but a number of others are possible.
+The nng_http_set_method function specifies the HTTP method to use for the transaction.
+The default is “GET”. HTTP methods are case sensitive, and generally upper-case, such as “GET”, “POST”, “HEAD”,
+and so forth. This function silently truncates any method to 32-characters. (There are no defined methods longer than this.)
+The nng_http_get_method function is used, typically on a server, to retrieve the method the client
+set when issuing the transaction.
+HTTP URI
+int nng_http_set_uri(nng_http *conn, const char *uri, const char *query);
+const char *nng_http_get_uri(nng_http *conn);
+
+The nng_http_set_uri function sets the URI, which normally appears like a path such as “/docs/index.html”,
+for the next transaction on conn. It sets the URI to uri, and, if query is not NULL, also appends the
+contents of query, separated by either the ‘?’ or ‘&’ character, depending on whether uri already
+contains a query string. It may return NNG_ENOMEM, or NNG_EMSGSIZE if the the result is too long,
+or NNG_EINVAL if there is some other problem with the URI.
+
+
+
+ note
+
+The uri and query must be already percent-encoded if necessary.
+
+The nni_http_get_uri function is used to obtain the URI that was previously set by nng_http_set_uri.
+If the URI is unset (such as for a freshly created connection), then it returns NULL. The returned value
+will have any query concentated, for example “/api/get_user.cgi?name=garrett”.
+HTTP Version
+int nng_http_set_version(nng_http *conn, const char *version);
+const char *nng_http_get_version(nng_http *conn);
+
+The nng_http_set_version function is used to select the HTTP protocol version to use for the
+exchange. At present, only the values NNG_HTTP_VERSION_1_0 and NNG_HTTP_VERSION_1_1 (corresponding to
+“HTTP/1.0” and “HTTP/1.1”) are supported. NNG will default to using “HTTP/1.1” if this function is not called.
+If an unsupported version is supplied, NNG_ENOTSUP will be returned, otherwise zero.
+The nng_http_get_version function is used to determine the version the client selected. Normally
+there is little need to use this, but there are some subtle semantic differences between HTTP/1.0 and HTTP/1.1.
+
+
+
+ tip
+
+There are few, if any, remaining HTTP/1.0 implementations that are not also capable of HTTP/1.1.
+It might be easiest to just fail any request coming in that is not HTTP/1.1.
+
+
+
+
+ note
+
+NNG does not support HTTP/2 or HTTP/3 at this time.
+
+HTTP Status
+uint16_t nng_http_get_status(nng_http *conn);
+const char *nng_http_get_reason(nng_http_conn *conn);
+void nng_http_set_status(nng_http *conn, uint16_t status, const char *reason);
+
+The nng_http_get_status function obtains the numeric code (typipcally numbered from 100 through 599) returned
+by the server in the last exchange on conn. (If no exchange has been performed yet, the result is undefined.)
+A descriptive message matching the status code is returned by nng_http_get_reason.
+The nng_http_set_status function is used on a server in a handler callback to set the status codethat will be
+reported to the client to status, and the associated text (reason) to reason. If reason is NULL,
+then a built in reason based on the status will be used instead.
+
+
+
+ tip
+
+Callbacks used on the server may wish to use nng_http_server_set_error or nng_http_server_set_redirect instead of
+nng_http_set_status, because those functions will also set the response body to a suitable HTML document
+for display to users.
+
+Status codes are defined by the IETF. Here are defininitions that NNG provides for convenience:
+
+Retrieving Headers
+const char *nng_http_get_header(nng_http *conn, const char *key);
+bool nng_next_header(nng_http *conn, const char **keyp, const char **valuep, void **next);
+
+The nng_http_get_header returns the header value matching key that was received over conn,
+or NULL if no such header exists.
+Thus, if conn is a client connection, then this function returns the the header value
+sent by the server as part of a response, whereas if it is a server connection, it returns
+the header value sent by the client as part of the request.
+If multiple headers are present with the same key, they may be returned as a combined value,
+with individual values separated by commas, but this behavior is not guaranteed.
+The nng_http_next_header function iterates over all the headers, using the same list
+that nng_http_get_header uses. To start, it is called with next initialized to NULL.
+If a header was found, then it returns true, and sets keyp and valuep to values containing
+the header name and value. It also updates next, which should be used for the next iteration.
+Once nng_http_next_header returns false, further calls with the same parameters will continue to do so.
+The scan can be rest by setting next to NULL.
+Modifying Headers
+int nng_http_add_header(nng_http *conn, const char *key, const char *val);
+int nng_http_set_header(nng_http *conn, const char *key, const char *val);
+void nng_http_del_header(nng_http *conn, const char *key);
+
+The nng_http_add_header, nng_http_set_header, and nng_http_del_header functions are
+used to add a modify either the request or response headers for conn prior to sending to the connected peer on conn.
+Thus, if the conn is a client connection created by nng_http_client_connect, then the request headers are modified.
+Conversely, if it is a connection created by an HTTP server and used in a callback function, then the response headers are modified.
+The nng_http_add_header function adds a header with the name key, and the value val, to the list of headers.
+In so doing, it may bring collapse multiple headers with the same name into a comma separated list, following
+the syntax specified in RFC 9110. The function may return NNG_ENOMEM, NNG_EMSGSIZE, or NNG_EINVAL.
+The nng_http_set_header function adds the header if it does not already exist, but replaces any and all previously existing
+headers with the same name key, if they exist. In all other respects it behaves similarly to nng_http_add_header.
+The nng_http_del_header removes all headers with name key.
+
+
+
+ note
+
+Some HTTP headers have special semantics, such as the “Host”, “Content-Length”, and “Content-Type” headers.
+This implementation may apply those semantics, in order to conform to the specifications for HTTP, such
+as by guaranting that only a single instance of one of these headers is present.
+
+Retrieving Body Content
+void nng_http_get_body(nng_http_conn *conn, void **datap, size_t *sizep);
+
+The nng_http_get_data obtains the most recently received request or
+response body. This will be NULL if the content has not been retrieved
+properly yet, or if the peer did not any content. (Some requests are defined
+to never have body content, such as “HEAD”.)
+Storing Body Content
+void nng_http_set_body(nng_http_conn *conn, void *data, size_t size);
+void nng_http_copy_body(nng_http_conn *conn, const void *data, size_t size);
+
+The nng_http_set_data function sets the outgoing body content to data,
+which must be size bytes long. The caller must ensure that data remains
+valid for the duration of the transaction.
+The nng_http_copy_data function makes a copy of data, which
+will be freed automatically when the transaction is finished, but otherwise
+behaves like nng_http_set_data.
+On client conn objects, these functions update the request object, but on server
+conn objects, they update the response object.
+These functions also update the relevant “Content-Length” header.
+
+
+
+ note
+
+The current framework does not support sending data via chunked
+transfer-encoding.
+
+
+
+
+ tip
+
+It is a good idea to also set the Content-Type header.
+
+Closing the Connection
+void nng_http_close(nng_http *conn);
+
+The nng_http_close function closes the supplied HTTP connection conn,
+including any disposing of any underlying file descriptors or related resources.
+Once this function, no further access to the conn structure may be made.
+Reset Connection State
+void nng_http_reset(nng_http *conn);
+
+The nng_http_reset function resets the request and response state of the
+the connection conn, so that it is just as if it had been freshly created with
+nng_http_client_connect or passed into a handler function for a server callback.
+The intended purpose of this function is to clear the object state before reusing the conn for
+subsequent transactions.
+Direct Read and Write
+void nng_http_read(nng_http *conn, nng_aio *aio);
+void nng_http_write(nng_http *conn, nng_aio *aio);
+void nng_http_read_all(nng_http *conn, nng_aio *aio);
+void nng_http_write_all(nng_http *conn, nng_aio *aio);
+
+The nng_http_read and nng_http_write functions read or write data asynchronously from or to the
+connection conn, using the nng_iov that is set in aio with nng_aio_set_iov.
+These functions will complete as soon as any data is transferred.
+Use nng_aio_count to determine how much data was actually transferred.
+The nng_http_read_all and nng_http_write_all functions perform the same task, but will keep resubmitting
+operations until the the entire amount of data requested by the nng_iov is transferred.
+
+
+
+ note
+
+These functions perform no special handling for chunked transfers.
+
+These functions are most likely to be useful after hijacking the connection with nng_http_hijack.
+They can be used to transfer request or response body data as well.
+Hijacking Connections
+void nng_http_hijack(nng_http_conn *conn);
+
+TODO: This API will change to convert the conn into a stream object.
+The nng_http_hijack function hijacks the connection conn, causing it
+to be disassociated from the HTTP server where it was created.
+The purpose of this function is the creation of HTTP upgraders (such as
+WebSocket), where the underlying HTTP connection will be taken over for
+some other purpose, and should not be used any further by the server.
+This function is most useful when called from a handler function.
+(See [nng_http_handler_alloc].)
+
+
+
+ note
+
+It is the responsibility of the caller to dispose of the underlying connection when it is no longer needed.
+Furthermore, the HTTP server will no longer send any responses to the hijacked connection, so the caller should do that as well if appropriate.
+(See [nng_http_write_response].)
+
+
+
+
+ tip
+
+This function is intended to facilitate uses cases that involve changing the protocol from HTTP, such as WebSocket.
+Most applications will never need to use this function.
+
+Client API
+The NNG client API consists of an API for creating connections, and an API for performing
+transactions on those connections.
+Client Object
+typedef struct nng_http_client nng_http_client;
+
+The nng_http_client object is the client side creator for nng_http objects.
+It is analogous to a dialer object used elsewhere in NNG, but it specifically is only for HTTP.
+Create a Client
+void nng_http_client_alloc(nng_http_client *clientp, const nng_url *url);
+
+The nng_http_client_alloc allocates an HTTP client suitable for
+connecting to the server identified by url and stores a pointer to
+it in the location referenced by clientp.
+Destroy a Client
+void nng_http_client_free(nng_http_client *client);
+
+The nng_http_client_free connection destroys the client object and any
+of its resources.
+
+
+
+ note
+
+Any connections created by nng_http_client_connect are not affected by this function,
+and must be closed explicitly as needed.
+
+Client TLS
+int nng_http_client_get_tls(nng_http_client *client, nng_tls_config **tlsp);
+int nng_http_client_set_tls(nng_http_client *client, nng_tls_config *tls);
+
+The nng_http_client_get_tls and nng_http_client_set_tls functions are used to
+retrieve or change the TLS configuration used when making outbound connections, enabling
+TLS as a result.
+If TLS has not been previously configured on client, then nng_http_client_get_tls will return NNG_EINVAL.
+Both functions will return NNG_ENOTSUP if either HTTP or TLS is not supported.
+Calling nng_http_client_set_tls invalidates any client previously obtained with
+nng_http_client_get_tls, unless a separate hold on the object was obtained.
+Once TLS is enabled for an nng_http_client, it is not possible to disable TLS.
+
+
+
+ note
+
+The TLS configuration itself cannnot be changed once it has been used to create a connection,
+such as by calling nng_http_client_connect, but a new one can be installed in the client.
+Existing connections will use the TLS configuration that there were created with.
+
+Creating Connections
+#include <nng/http.h>
+
+void nng_http_client_connect(nng_http_client *client, nng_aio *aio);
+
+The nng_http_client_connect function makes an outgoing connection to the
+server configured for client, and creates an nng_http object for the connection.
+This is done asynchronously, and when the operation succeseds the connection may be
+retried from the aio using nng_aio_get_output with index 0.
+Example 1: Connecting to Google
+nng_aio *aio;
+nng_url *url;
+nng_http_client *client;
+nng_http *conn;
+int rv;
+
+// Error checks elided for clarity.
+nng_url_parse(&url, "http://www.google.com");
+nng_aio_alloc(&aio, NULL, NULL);
+nng_http_client_alloc(&client, url);
+
+nng_http_client_connect(client, aio);
+
+// Wait for connection to establish (or attempt to fail).
+nng_aio_wait(aio);
+
+if ((rv = nng_aio_result(aio)) != 0) {
+ printf("Connection failed: %s\n", nng_strerror(rv));
+} else {
+ // Connection established, get it.
+ conn = nng_aio_get_output(aio, 0);
+
+ // ... do something with it here
+
+ // Close the connection when done to avoid leaking it.
+ nng_http_close(conn);
+}
+
+Preparing a Transaction
+int nng_http_set_version(nng_http *conn, const char *version);
+int nng_http_set_uri(nng_http *conn, const char *uri);
+
+The nng_http_set_uri function provides a URI for the transaction. This will be used to
+set the URI for the request. The URI typically appears like a path, starting with “/”, although
+it may also contain a query string.
+Request Body
+Sending the Request
+void nng_http_write_request(nng_http *conn, nng_aio *aio);
+
+The nng_http_write_request function starts an asynchronous write of
+the HTTP request associated with conn.
+The entire request is sent,
+including headers, and if present, the request body data.
+(The request body can be set with
+[nng_http_set_data] or [nng_http_copy_data].)
+This function returns immediately, with no return value.
+Completion of the operation is signaled via the aio, and the final result
+may be obtained via nng_aio_result.
+
+
+
+ tip
+
+Consider using the [nng_http_transact] function,
+which provides a simpler interface for performing a complete HTTP client transaction.
+
+Obtaining the Response
+void nng_http_read_response(nng_http *conn, nng_aio *aio);
+
+The nng_http_read_response function starts an asynchronous read from the
+HTTP connection conn, reading an HTTP response into the response associated with conn, including all
+of the related headers.
+It does not transfer any response body. To do that, use nng_http_read_all or nng_http_read.
+
+
+
+ note
+
+At this time we have no API support for reading chunked transfers directly. Applications that
+need to do so may use the direct read functions.
+
+
+
+
+ tip
+
+An easier one-shot method for many use cases might be [nng_http_transact].
+
+Submitting the Transaction
+int nng_http_transact(nng_http *conn, nng_aio *aio);
+
+The HTTP request is issued, and the response processed, asynchronously by the nng_http_transact function.
+When the function is complete, the aio will be notified.
+The nng_http_transact function is used to perform a complete
+HTTP exchange over the connection conn, sending the request
+and attached body data to the remote server, and reading the response.
+The entire response is read, including any associated body, which can
+subsequently be obtained using [nng_http_get_data].
+This function is intended to make creation of client applications easier,
+by performing multiple asynchronous operations required to complete an
+entire HTTP transaction.
+If an error occurs, the caller should close conn with nng_http_close, as it may not
+necessarily be usable with other transactions.
+
+
+
+ warning
+
+If the remote server tries to send an extremely large buffer,
+then a corresponding allocation will be made, which can lead to denial
+of service attacks.
+Client applications should take care to use this only with reasonably
+trust-worthy servers.
+
+
+
+
+ note
+
+A given connection conn should be used with only one
+operation or transaction at a time as HTTP/1.1 has no support for
+request interleaving.
+
+This function returns immediately, with no return value.
+Completion of the operation is signaled via the aio, and the final result
+may be obtained via [nng_aio_result()].
+Response Body
+Server API
+Handlers
+Sending the Response
+void nng_http_write_response(nng_http *conn, nng_aio *aio);
+
+Normally the server will send any attached response, but there are circumstances where
+a response must be sent manually, such as when hijacking a connection.
+In such a case, nng_http_write_response can be called, which will send the response and any attached data, asynchronously
+using the nng_aio aio.
+By default, for HTTP/1.1 connections, the connection is kept open, and
+will be reused to receive new requests. For HTTP/1.0, or if the client has requested
+explicitly by setting the “Connection: close” header, the connection will be closed after the
+response is fully sent.
+
+
@@ -4145,6 +4722,7 @@ the version numbers reported refer to both the API and the library itself.
library and the application is controlled in a similar, but different
manner depending upon the link options and how the library is built.)
+
@@ -4332,6 +4910,7 @@ iteration is undefined; entries may be repeated or omitted during such an iterat
The caller must not attempt to derive any value of the cursor as it refers to internal
table indices.
+
@@ -4582,6 +5161,7 @@ unambiguously (meaning it must not match any other option specification.)
}
+
@@ -6148,6 +6728,7 @@ the inproc transport to communicate across this boundary.
This limitation also extends to using different instances of the NNG
library within the same process.
+
@@ -6310,6 +6891,7 @@ where supported by the underlying platform.
which can be used to control access, can be set using the function
nng_listener_set_security_descriptor.
+
@@ -6437,6 +7019,7 @@ There are no further socket details available.
These behave in exactly the same fashion as for the ipc transport.
+
@@ -6610,6 +7193,7 @@ In order to ensure that resources are reclaimed when a peer vanishes unexpectedl
keep-alive mechanism is implemented.
TODO: Document the tunables for this.
+
@@ -6866,10 +7450,6 @@ can be simply removed from your application:
Additionally, the header files containing these functions have been removed, such as
nng/transport/ipc/ipc.h. Simply remove #include references to those files.
-The NNG_OPT_WSS_REQUEST_HEADERS and NNG_OPT_WSS_RESPONSE_HEADERS aliases for
-NNG_OPT_WS_OPT_WS_REQUEST_HEADERS and NNG_OPT_WS_RESPONSE_HEADERS have been removed.
-Just convert any use of them to NNG_OPT_WS_REQUEST_HEADERS or
-NNG_OPT_WS_RESPONSE_HEADERS as appropriate.
TLS Configuration
The support for configuring TLS via NNG_OPT_TLS_CONFIG, NNG_TLS_AUTH_MODE, NNG_OPT_TLS_CA_FILE,
NNG_OPT_TLS_SERVER_NAME, and similar has been removed.
@@ -7032,6 +7612,8 @@ accessors functions are provided:
u_rawurl is removed - a “cooked” URL can be obtained from the new nng_url_sprintf function.
HTTP API
+The entire HTTP API has been refactored and should be much simpler to use and more efficient.
+Applications directly using the HTTP API will need to be fully modified.
A few limits on string lengths of certain values are now applied, which allows us to preallocate values
and eliminate certain unreasonable error paths. If values longer than these are supplied in certain APIs
they may be silently truncated to the limit:
@@ -7055,6 +7637,15 @@ They may silently truncate data.
The HTTP handler objects may not be modified once in use. Previously this would fail with NNG_EBUSY.
These checks are removed now, but debug builds will assert if an application tries to do so.
+WebSocket API
+The NNG_OPT_WSS_REQUEST_HEADERS, NNG_OPT_WSS_RESPONSE_HEADERS and
+NNG_OPT_WS_OPT_WS_REQUEST_HEADERS, NNG_OPT_WS_RESPONSE_HEADERS have been removed.
+The NNG_OPT_WS_REQUEST_HEADER and NNG_OPT_WS_RESPONSE_HEADER option prefixes have been
+collapsed into just NNG_OPT_WS_HEADER, with slightly different semantics. It still is
+a prefix (append the name of the header of interest), but setting it can only affect
+outbound headers (request header for dialers, response header for listeners), and when
+reading it on a pipe, the value returned is the header sent by the remote peer.
+The undocumented hook function signature has changed to reflect changes in the HTTP API.
Security Descriptors (Windows Only)
The NNG_OPT_IPC_SECURITY_DESCRIPTOR option is removed, and replaced
with the functions [nng_listener_get_security_descriptor] and
@@ -7072,6 +7663,7 @@ See nng_args
It is possible to use NNG with ZeroTier using TCP/IP, and a future update
is planned to provided coexistence between ZeroTier & the native stack’s TCP/IP using lwIP.
+
@@ -7254,6 +7846,7 @@ using nn_dial inside the URL is not present in NNG. The correct
way to specify the local address is using the NNG_OPT_LOCADDR option on the
dialer before starting to dial.
+
@@ -7358,6 +7951,40 @@ named pipes, 1
nng_fini, 1
NNG_FLAG_NONBLOCK, 1, 2
nng_free, 1
+nng_http, 1
+nng_http_add_header, 1
+nng_http_client, 1
+nng_http_client_alloc, 1
+nng_http_client_connect, 1
+nng_http_client_free, 1
+nng_http_client_get_tls, 1
+nng_http_client_set_tls, 1
+nng_http_close, 1
+nng_http_copy_data, 1
+nng_http_del_header, 1
+nng_http_get_data, 1
+nng_http_get_header, 1
+nng_http_get_method, 1
+nng_http_get_reason, 1
+nng_http_get_status, 1
+nng_http_get_version, 1
+nng_http_hijack, 1
+nng_http_next_header, 1
+nng_http_read, 1
+nng_http_read_all, 1
+nng_http_read_response, 1
+nng_http_reset, 1
+nng_http_set_data, 1
+nng_http_set_header, 1
+nng_http_set_method, 1
+nng_http_set_status, 1
+nng_http_set_uri, 1, 2
+nng_http_set_version, 1
+nng_http_transact, 1, 2
+nng_http_write, 1
+nng_http_write_all, 1
+nng_http_write_request, 1
+nng_http_write_response, 1
nng_id_alloc, 1
nng_id_get, 1
nng_id_map, 1
@@ -7559,6 +8186,7 @@ named pipes, 1
nng_url_sprintf, 1
nng_url_userinfo, 1
nng_version, 1
+nni_http_get_uri, 1
PAIR, 1
PAIR protocol, 1
pipeline pattern, 1, 2, 3
@@ -7603,13 +8231,14 @@ synchronization primitives, 1
threads, 1
thundering herd, 1
timeout, 1
-TLS, 1
+TLS, 1, 2
UDP, 1
udp transport, 1
udp://, 1
Universal Resource Locator, 1
UNIX domain sockets, 1
unix://, 1
+URI, 1
URL, 1, 2
version number, 1
voting, 1
--
cgit v1.2.3-70-g09d2