diff options
| author | gdamore <gdamore@users.noreply.github.com> | 2025-01-10 07:46:01 +0000 |
|---|---|---|
| committer | gdamore <gdamore@users.noreply.github.com> | 2025-01-10 07:46:01 +0000 |
| commit | 131726d96414aa1a35e8319db0785221e1230566 (patch) | |
| tree | 80c278b5d5b96ef52e8130664b73305bfc6029ba /ref/print.html | |
| parent | e4a3b9b9ac50424003baaf1c9014651b525bde2f (diff) | |
| download | nng-131726d96414aa1a35e8319db0785221e1230566.tar.gz nng-131726d96414aa1a35e8319db0785221e1230566.tar.bz2 nng-131726d96414aa1a35e8319db0785221e1230566.zip | |
deploy: 73f50e2679525e7df8734c875a3c12732565f953
Diffstat (limited to 'ref/print.html')
| -rw-r--r-- | ref/print.html | 639 |
1 files changed, 634 insertions, 5 deletions
diff --git a/ref/print.html b/ref/print.html index 00a5ad95..9751dd67 100644 --- a/ref/print.html +++ b/ref/print.html @@ -611,6 +611,7 @@ include the <code>nng/nng.h</code> header file like so:</p> <li><a href="api/thr.html">Threads</a></li> <li><a href="api/logging.html">Logging</a></li> <li><a href="api/stats.html">Statistics</a></li> +<li><a href="api/http.html">HTTP</a></li> <li><a href="api/misc.html">Miscellaneous</a></li> <li><a href="api/errors.html">Errors</a></li> <li><a href="api/id_map.html">ID Map</a></li> @@ -756,6 +757,7 @@ the <a name="a002"></a><code>nng_fini</code> function. Each call to <code>nng_fi <p>After calling <code>nng_fini</code>, the consuming application must not make any other calls to NNG functions, except that it may use <code>nng_init</code> to initialize the application for further use.</p> <!-- Symbol cross reference --> +<!-- HTTP --> <!-- Macros --> <!-- Protocols --> <!-- Transports --> @@ -1058,6 +1060,7 @@ while ((val64 = next_datum()) != 0) P } </code></pre> <!-- Symbol cross reference --> +<!-- HTTP --> <!-- Macros --> <!-- Protocols --> <!-- Transports --> @@ -1589,6 +1592,7 @@ int main(int argc, char **argv) { } </code></pre> <!-- Symbol cross reference --> +<!-- HTTP --> <!-- Macros --> <!-- Protocols --> <!-- Transports --> @@ -1889,6 +1893,7 @@ start_echo_service(nng_socket rep_socket) } </code></pre> <!-- Symbol cross reference --> +<!-- HTTP --> <!-- Macros --> <!-- Protocols --> <!-- Transports --> @@ -2009,6 +2014,7 @@ one (for the <code>NUL</code> terminating byte).</p> can be used to deallocate strings allocated with <a href="api//api/memory.html#duplicate-string"><code>nng_strdup</code></a>.</p> <p>It is effectively the same as <code>nng_free(strlen(str) + 1)</code>.</p> <!-- Symbol cross reference --> +<!-- HTTP --> <!-- Macros --> <!-- Protocols --> <!-- Transports --> @@ -2161,6 +2167,7 @@ then the sleep will wake up early, with a result code of <a href="api//api/error <p><a href="api//api/aio.html">Asynchronous Operations</a>, <a href="api//api/synch.html">Synchronization</a></p> <!-- Symbol cross reference --> +<!-- HTTP --> <!-- Macros --> <!-- Protocols --> <!-- Transports --> @@ -2335,6 +2342,7 @@ a URL with a new port. This will have no effect if the URL already has a non-zer <p>More information about Universal Resource Locators can be found in <a href="https://tools.ietf.org/html/rfc3986">RFC 3986</a>.</p> <!-- Symbol cross reference --> +<!-- HTTP --> <!-- Macros --> <!-- Protocols --> <!-- Transports --> @@ -2686,6 +2694,7 @@ and if necessary resubmit the operation with a suitably updated vector of <code> <a href="api//api/stream.html">Streams</a>, <a href="api//api/time.html">Time</a></p> <!-- Symbol cross reference --> +<!-- HTTP --> <!-- Macros --> <!-- Protocols --> <!-- Transports --> @@ -2895,6 +2904,7 @@ nng_mtx_unlock(m); <a href="api//api/time.html">Time</a>, <a href="api//api/aio.html">Asynchronous I/O</a></p> <!-- Symbol cross reference --> +<!-- HTTP --> <!-- Macros --> <!-- Protocols --> <!-- Transports --> @@ -3040,6 +3050,7 @@ in debuggers. Not all platforms support setting the thread name.</p> <p><a href="api//api/synch.html">Synchronization</a>, <a href="api//api/aio.html">Asynchronous Operations</a></p> <!-- Symbol cross reference --> +<!-- HTTP --> <!-- Macros --> <!-- Protocols --> <!-- Transports --> @@ -3493,6 +3504,7 @@ here is the same reference time used for <a href="api//api/time.html#get-the-cur <h2 id="see-also-6"><a class="header" href="#see-also-6">See Also</a></h2> <p><a href="api//api/time.html#get-the-current-time"><code>nng_clock</code></a></p> <!-- Symbol cross reference --> +<!-- HTTP --> <!-- Macros --> <!-- Protocols --> <!-- Transports --> @@ -3629,6 +3641,7 @@ as in diagnostic messages or log entries.</p> <tr><td><code>NNG_ETRANERR</code><a name="NNG_ETRANERR"></a></td><td>0x20000000 - 0x2FFFFFFF</td><td>An unidentified transport error occurred.</td></tr> </tbody></table> </div><!-- Symbol cross reference --> +<!-- HTTP --> <!-- Macros --> <!-- Protocols --> <!-- Transports --> @@ -4026,6 +4039,570 @@ They will return a pointer to the <a href="api//TODO.html"><code>nng_tls_config< both configuring a different TLS configuration object, as well as mutating the existing <a href="api//TODO.html"><code>nng_tls_config</code></a> object.</p> </div> <!-- Symbol cross reference --> +<!-- HTTP --> +<!-- Macros --> +<!-- Protocols --> +<!-- Transports --> +<!-- Concept index --> +<div style="break-before: page; page-break-before: always;"></div><style> +.mdbook-alerts { + padding: 8px 16px; + margin-bottom: 16px; + border-left: 0.25em solid var(--mdbook-alerts-color); +} + +.mdbook-alerts > *:first-child { + margin-top: 0; +} + +.mdbook-alerts > *:last-child { + margin-bottom: 0; +} + +.mdbook-alerts-title { + display: flex; + font-weight: 600; + align-items: center; + line-height: 1; + color: var(--mdbook-alerts-color); + text-transform: capitalize; +} + +.mdbook-alerts-icon { + display: inline-block; + width: 1em; + height: 1em; + margin-right: 0.2em; + background-color: currentColor; + -webkit-mask: no-repeat center / 100%; + mask: no-repeat center / 100%; + -webkit-mask-image: var(--mdbook-alerts-icon); + mask-image: var(--mdbook-alerts-icon); +} + +.mdbook-alerts-note { + --mdbook-alerts-color: rgb(9, 105, 218); + /* https://icon-sets.iconify.design/material-symbols/info-outline-rounded/ */ + --mdbook-alerts-icon: url('data:image/svg+xml,%3Csvg xmlns="http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg" width="24" height="24" viewBox="0 0 24 24"%3E%3Cpath fill="currentColor" d="M12 17q.425 0 .713-.288T13 16v-4q0-.425-.288-.712T12 11q-.425 0-.712.288T11 12v4q0 .425.288.713T12 17m0-8q.425 0 .713-.288T13 8q0-.425-.288-.712T12 7q-.425 0-.712.288T11 8q0 .425.288.713T12 9m0 13q-2.075 0-3.9-.788t-3.175-2.137q-1.35-1.35-2.137-3.175T2 12q0-2.075.788-3.9t2.137-3.175q1.35-1.35 3.175-2.137T12 2q2.075 0 3.9.788t3.175 2.137q1.35 1.35 2.138 3.175T22 12q0 2.075-.788 3.9t-2.137 3.175q-1.35 1.35-3.175 2.138T12 22m0-2q3.35 0 5.675-2.325T20 12q0-3.35-2.325-5.675T12 4Q8.65 4 6.325 6.325T4 12q0 3.35 2.325 5.675T12 20m0-8"%2F%3E%3C%2Fsvg%3E'); +} + +.mdbook-alerts-tip { + --mdbook-alerts-color: rgb(26, 127, 55); + /* https://icon-sets.iconify.design/material-symbols/lightbulb-outline-rounded/ */ + --mdbook-alerts-icon: url('data:image/svg+xml,%3Csvg xmlns="http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg" width="24" height="24" viewBox="0 0 24 24"%3E%3Cpath fill="currentColor" d="M12 22q-.825 0-1.412-.587T10 20h4q0 .825-.587 1.413T12 22m-3-3q-.425 0-.712-.288T8 18q0-.425.288-.712T9 17h6q.425 0 .713.288T16 18q0 .425-.288.713T15 19zm-.75-3q-1.725-1.025-2.738-2.75T4.5 9.5q0-3.125 2.188-5.312T12 2q3.125 0 5.313 2.188T19.5 9.5q0 2.025-1.012 3.75T15.75 16zm.6-2h6.3q1.125-.8 1.738-1.975T17.5 9.5q0-2.3-1.6-3.9T12 4Q9.7 4 8.1 5.6T6.5 9.5q0 1.35.613 2.525T8.85 14M12 14"%2F%3E%3C%2Fsvg%3E'); +} + +.mdbook-alerts-important { + --mdbook-alerts-color: rgb(130, 80, 223); + /* https://icon-sets.iconify.design/material-symbols/chat-info-outline-rounded/ */ + --mdbook-alerts-icon: url('data:image/svg+xml,%3Csvg xmlns="http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg" width="24" height="24" viewBox="0 0 24 24"%3E%3Cpath fill="currentColor" d="M12 7q.425 0 .713-.288T13 6q0-.425-.288-.712T12 5q-.425 0-.712.288T11 6q0 .425.288.713T12 7m0 8q.425 0 .713-.288T13 14v-4q0-.425-.288-.712T12 9q-.425 0-.712.288T11 10v4q0 .425.288.713T12 15m-6 3l-2.3 2.3q-.475.475-1.088.213T2 19.575V4q0-.825.588-1.412T4 2h16q.825 0 1.413.588T22 4v12q0 .825-.587 1.413T20 18zm-.85-2H20V4H4v13.125zM4 16V4z"%2F%3E%3C%2Fsvg%3E'); +} + +.mdbook-alerts-warning { + --mdbook-alerts-color: rgb(154, 103, 0); + /* https://icon-sets.iconify.design/material-symbols/warning-outline-rounded/ */ + --mdbook-alerts-icon: url('data:image/svg+xml,%3Csvg xmlns="http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg" width="24" height="24" viewBox="0 0 24 24"%3E%3Cpath fill="currentColor" d="M2.725 21q-.275 0-.5-.137t-.35-.363q-.125-.225-.137-.488t.137-.512l9.25-16q.15-.25.388-.375T12 3q.25 0 .488.125t.387.375l9.25 16q.15.25.138.513t-.138.487q-.125.225-.35.363t-.5.137zm1.725-2h15.1L12 6zM12 18q.425 0 .713-.288T13 17q0-.425-.288-.712T12 16q-.425 0-.712.288T11 17q0 .425.288.713T12 18m0-3q.425 0 .713-.288T13 14v-3q0-.425-.288-.712T12 10q-.425 0-.712.288T11 11v3q0 .425.288.713T12 15m0-2.5"%2F%3E%3C%2Fsvg%3E'); +} + +.mdbook-alerts-caution { + --mdbook-alerts-color: rgb(207, 34, 46); + /* https://icon-sets.iconify.design/material-symbols/brightness-alert-outline-rounded/ */ + --mdbook-alerts-icon: url('data:image/svg+xml,%3Csvg xmlns="http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg" width="24" height="24" viewBox="0 0 24 24"%3E%3Cpath fill="currentColor" d="M12 17q.425 0 .713-.288T13 16q0-.425-.288-.712T12 15q-.425 0-.712.288T11 16q0 .425.288.713T12 17m0-4q.425 0 .713-.288T13 12V8q0-.425-.288-.712T12 7q-.425 0-.712.288T11 8v4q0 .425.288.713T12 13m-3.35 7H6q-.825 0-1.412-.587T4 18v-2.65L2.075 13.4q-.275-.3-.425-.662T1.5 12q0-.375.15-.737t.425-.663L4 8.65V6q0-.825.588-1.412T6 4h2.65l1.95-1.925q.3-.275.663-.425T12 1.5q.375 0 .738.15t.662.425L15.35 4H18q.825 0 1.413.588T20 6v2.65l1.925 1.95q.275.3.425.663t.15.737q0 .375-.15.738t-.425.662L20 15.35V18q0 .825-.587 1.413T18 20h-2.65l-1.95 1.925q-.3.275-.662.425T12 22.5q-.375 0-.737-.15t-.663-.425zm.85-2l2.5 2.5l2.5-2.5H18v-3.5l2.5-2.5L18 9.5V6h-3.5L12 3.5L9.5 6H6v3.5L3.5 12L6 14.5V18zm2.5-6"%2F%3E%3C%2Fsvg%3E'); +} + +</style> +<h1 id="http-support"><a class="header" href="#http-support">HTTP Support</a></h1> +<p>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.</p> +<p>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.</p> +<h2 id="header-file"><a class="header" href="#header-file">Header File</a></h2> +<pre><code class="language-c">#include <nng/http.h> +</code></pre> +<p>Unlike the rest of NNG, the HTTP API in NNG requires including <code>nng/http.h</code>. It is not necessary to include +the main <code>nng/nng.h</code> header, it will be included transitively by <code>nng/http.h</code>.</p> +<h2 id="connection-object"><a class="header" href="#connection-object">Connection Object</a></h2> +<pre><code class="language-c">typedef struct nng_http nng_http; +</code></pre> +<p>The <a name="a001"></a><code>nng_http</code> 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.</p> +<p>An <code>nng_http</code> object can be reused, unless closed, so that additional transactions can be +performed after the first transaction is complete.</p> +<p>At any given point in time, an <code>nng_http</code> object can only refer to a single HTTP transaction. +In NNG, these <code>nng_http</code> objects are used in both the client and server APIs.</p> +<p>The <code>nng_http</code> object is created by either <a href="api//api/http.html#creating-connections"><code>nng_http_client_connect</code></a> or by an HTTP server +object which then passes it to an [<code>nng_http_handler</code>] callback function.</p> +<h3 id="http-method"><a class="header" href="#http-method">HTTP Method</a></h3> +<pre><code class="language-c">void nng_http_set_method(nng_http *conn, const char *method); +const char *nng_http_get_method(nng_http *conn); +</code></pre> +<p>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.</p> +<p>The <a name="a002"></a><code>nng_http_set_method</code> 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.)</p> +<p>The <a name="a003"></a><code>nng_http_get_method</code> function is used, typically on a server, to retrieve the method the client +set when issuing the transaction.</p> +<h3 id="http-uri"><a class="header" href="#http-uri">HTTP URI</a></h3> +<pre><code class="language-c">int nng_http_set_uri(nng_http *conn, const char *uri, const char *query); +const char *nng_http_get_uri(nng_http *conn); +</code></pre> +<p>The <a name="a004"></a><code>nng_http_set_uri</code> function sets the <a name="a005"></a>URI, which normally appears like a path such as “/docs/index.html”, +for the next transaction on <em>conn</em>. It sets the URI to <em>uri</em>, and, if <em>query</em> is not <code>NULL</code>, also appends the +contents of <em>query</em>, separated by either the ‘?’ or ‘&’ character, depending on whether <em>uri</em> already +contains a query string. It may return <a href="api//api/errors.html#NNG_ENOMEM"><code>NNG_ENOMEM</code></a>, or <a href="api//api/errors.html#NNG_EMSGSIZE"><code>NNG_EMSGSIZE</code></a> if the the result is too long, +or <a href="api//api/errors.html#NNG_EINVAL"><code>NNG_EINVAL</code></a> if there is some other problem with the URI.</p> +<div class="mdbook-alerts mdbook-alerts-note"> +<p class="mdbook-alerts-title"> + <span class="mdbook-alerts-icon"></span> + note +</p> +<p>The <em>uri</em> and <em>query</em> must be already percent-encoded if necessary.</p> +</div> +<p>The <a name="a006"></a><code>nni_http_get_uri</code> function is used to obtain the URI that was previously set by <code>nng_http_set_uri</code>. +If the URI is unset (such as for a freshly created connection), then it returns <code>NULL</code>. The returned value +will have any query concentated, for example “/api/get_user.cgi?name=garrett”.</p> +<h3 id="http-version"><a class="header" href="#http-version">HTTP Version</a></h3> +<pre><code class="language-c">int nng_http_set_version(nng_http *conn, const char *version); +const char *nng_http_get_version(nng_http *conn); +</code></pre> +<p>The <a name="a007"></a><code>nng_http_set_version</code> function is used to select the HTTP protocol version to use for the +exchange. At present, only the values <code>NNG_HTTP_VERSION_1_0</code> and <code>NNG_HTTP_VERSION_1_1</code> (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, <a href="api//api/errors.html#NNG_ENOTSUP"><code>NNG_ENOTSUP</code></a> will be returned, otherwise zero.</p> +<p>The <a name="a008"></a><code>nng_http_get_version</code> 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.</p> +<div class="mdbook-alerts mdbook-alerts-tip"> +<p class="mdbook-alerts-title"> + <span class="mdbook-alerts-icon"></span> + tip +</p> +<p>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.</p> +</div> +<div class="mdbook-alerts mdbook-alerts-note"> +<p class="mdbook-alerts-title"> + <span class="mdbook-alerts-icon"></span> + note +</p> +<p>NNG does not support HTTP/2 or HTTP/3 at this time.</p> +</div> +<h3 id="http-status"><a class="header" href="#http-status">HTTP Status</a></h3> +<pre><code class="language-c">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); +</code></pre> +<p>The <a name="a009"></a><code>nng_http_get_status</code> function obtains the numeric code (typipcally numbered from 100 through 599) returned +by the server in the last exchange on <em>conn</em>. (If no exchange has been performed yet, the result is undefined.)</p> +<p>A descriptive message matching the status code is returned by <a name="a010"></a><code>nng_http_get_reason</code>.</p> +<p>The <a name="a011"></a><code>nng_http_set_status</code> function is used on a server in a handler callback to set the status codethat will be +reported to the client to <em>status</em>, and the associated text (reason) to <em>reason</em>. If <em>reason</em> is <code>NULL</code>, +then a built in reason based on the <em>status</em> will be used instead.</p> +<div class="mdbook-alerts mdbook-alerts-tip"> +<p class="mdbook-alerts-title"> + <span class="mdbook-alerts-icon"></span> + tip +</p> +<p>Callbacks used on the server may wish to use <a href="api//TODO.html"><code>nng_http_server_set_error</code></a> or <a href="api//TODO.html"><code>nng_http_server_set_redirect</code></a> instead of +<code>nng_http_set_status</code>, because those functions will also set the response body to a suitable HTML document +for display to users.</p> +</div> +<p>Status codes are defined by the IETF. Here are defininitions that NNG provides for convenience:</p> +<div class="table-wrapper"><table><thead><tr><th>Name</th><th>Code</th><th>Reason Text</th><th>Notes</th></tr></thead><tbody> +<tr><td><code>NNG_HTTP_STATUS_CONTINUE</code><a name="#NNG_HTTP_STATUS_CONTINUE"></a></td><td>100</td><td>Continue</td><td>Partial transfer, client may send body.</td></tr> +<tr><td><code>NNG_HTTP_STATUS_SWITCHING</code><a name="#NNG_HTTP_STATUS_SWITCHING"></a></td><td>101</td><td>Switching Protocols</td><td>Used when upgrading or hijacking a connection.</td></tr> +<tr><td><code>NNG_HTTP_STATUS_PROCESSING</code><a name="#NNG_HTTP_STATUS_PROCESSING"></a></td><td>102</td><td>Processing</td><td></td></tr> +<tr><td><code>NNG_HTTP_STATUS_OK</code><a name="#NNG_HTTP_STATUS_OK"></a></td><td>200</td><td>OK</td><td>Successful result.</td></tr> +<tr><td><code>NNG_HTTP_STATUS_CREATED</code><a name="#NNG_HTTP_STATUS_CREATED"></a></td><td>201</td><td>Created</td><td>Resource created successfully.</td></tr> +<tr><td><code>NNG_HTTP_STATUS_ACCEPTED</code><a name="#NNG_HTTP_STATUS_ACCEPTED"></a></td><td>202</td><td>Created</td><td>Request accepted for future processing.</td></tr> +<tr><td><code>NNG_HTTP_STATUS_NOT_AUTHORITATIVE</code><a name="#NNG_HTTP_STATUS_NOT_AUTHORITATIVE"></a></td><td>203</td><td>Not Authoritative</td><td>Request successful, but modified by proxy.</td></tr> +<tr><td><code>NNG_HTTP_STATUS_NO_CONTENT</code><a name="#NNG_HTTP_STATUS_NO_CONTENT"></a></td><td>204</td><td>No Content</td><td>Request successful, no content returned.</td></tr> +<tr><td><code>NNG_HTTP_STATUS_RESET_CONTENT</code><a name="#NNG_HTTP_STATUS_NO_CONTENT"></a></td><td>205</td><td>Reset Content</td><td>Request successful, client should reload content.</td></tr> +<tr><td><code>NNG_HTTP_STATUS_PARTIAL_CONTENT</code><a name="#NNG_HTTP_STATUS_NO_CONTENT"></a></td><td>206</td><td>Partial Content</td><td>Response to a range request.</td></tr> +<tr><td><code>NNG_HTTP_STATUS_MULTI_STATUS</code><a name="#NNG_HTTP_STATUS_MULTI_STATUS"></a></td><td>207</td><td>Multi-Status</td><td>Used with WebDAV.</td></tr> +<tr><td><code>NNG_HTTP_STATUS_ALREADY_REPORTED</code><a name="#NNG_HTTP_STATUS_ALREADY_REPORTED"></a></td><td>208</td><td>Already Reported</td><td>Used with WebDAV.</td></tr> +<tr><td><code>NNG_HTTP_STATUS_IM_USED</code><a name="#NNG_HTTP_STATUS_IM_USED"></a></td><td>226</td><td>IM Used</td><td>Used with delta encodings, rarely supported.</td></tr> +<tr><td><code>NNG_HTTP_STATUS_MULTIPLE_CHOICES</code><a name="#NNG_HTTP_STATUS_MULTIPLE_CHOICES"></a></td><td>300</td><td>Multiple Choices</td><td>Multiple responses possible, client should choose.</td></tr> +<tr><td><code>NNG_HTTP_STATUS_MOVED_PERMANENTLY</code><a name="#NNG_HTTP_STATUS_MOVED_PERMANENTLY"></a></td><td>301</td><td>Moved Permanently</td><td>Permanent redirection, may be saved by client.</td></tr> +<tr><td><code>NNG_HTTP_STATUS_FOUND</code><a name="#NNG_HTTP_STATUS_FOUND"></a></td><td>302</td><td>Found</td><td>Temporary redirection, client may switch to GET.</td></tr> +<tr><td><code>NNG_HTTP_STATUS_SEE_OTHER</code><a name="#NNG_HTTP_STATUS_SEE_OTHER"></a></td><td>303</td><td>See Other</td><td>Redirect, perhaps after a success POST or PUT.</td></tr> +<tr><td><code>NNG_HTTP_STATUS_NOT_MODIFIED</code><a name="#NNG_HTTP_STATUS_NOT_MODIFIED"></a></td><td>304</td><td>Not Modified</td><td>Resource not modified, client may use cached version.</td></tr> +<tr><td><code>NNG_HTTP_STATUS_USE_PROXY</code><a name="#NNG_HTTP_STATUS_USE_PROXY"></a></td><td>305</td><td>Use Proxy</td><td></td></tr> +<tr><td><code>NNG_HTTP_STATUS_TEMPORARY_REDIRECT</code><a name="#NNG_HTTP_STATUS_TEMPORARY_REDIRECT"></a></td><td>307</td><td>Temporary Redirect</td><td>Temporary redirect, preserves method.</td></tr> +<tr><td><code>NNG_HTTP_STATUS_PERMANENT_REDIRECT</code><a name="#NNG_HTTP_STATUS_PERMANENT_REDIRECT"></a></td><td>308</td><td>Permanent Redirect</td><td>Permanent redirect.</td></tr> +<tr><td><code>NNG_HTTP_STATUS_BAD_REQUEST</code><a name="#NNG_HTTP_STATUS_BAD_REQUEST"></a></td><td>400</td><td>Bad Request</td><td>Generic problem with the request.</td></tr> +<tr><td><code>NNG_HTTP_STATUS_UNAUTHORIZED</code><a name="#NNG_HTTP_STATUS_UNAUTHORIZED"></a></td><td>401</td><td>Unauthorized</td><td>Indicates a problem with authentication.</td></tr> +<tr><td><code>NNG_HTTP_STATUS_PAYMENT_REQUIRED</code><a name="#NNG_HTTP_STATUS_PAYMENT_REQUIRED"></a></td><td>402</td><td>Payment Required</td><td></td></tr> +<tr><td><code>NNG_HTTP_STATUS_FORBIDDEN</code><a name="#NNG_HTTP_STATUS_FORBIDDEN"></a></td><td>403</td><td>Forbidden</td><td>No permission to access resource.</td></tr> +<tr><td><code>NNG_HTTP_STATUS_NOT_FOUND</code><a name="#NNG_HTTP_STATUS_NOT_FOUND"></a></td><td>404</td><td>Not Found</td><td>Resource does not exist.</td></tr> +<tr><td><code>NNG_HTTP_STATUS_METHOD_NOT_ALLOWED</code><a name="#NNG_HTTP_STATUS_METHOD_NOT_ALLOWED"></a></td><td>405</td><td>Method Not Allowed</td><td>Resource does not support the method.</td></tr> +<tr><td><code>NNG_HTTP_STATUS_METHOD_NOT_ACCEPTABLE</code><a name="#NNG_HTTP_STATUS_METHOD_NOT_ACCEPTABLE"></a></td><td>406</td><td>Not Acceptable</td><td>Could not satisfy accept requirements.</td></tr> +<tr><td><code>NNG_HTTP_STATUS_PROXY_AUTH_REQUIRED</code><a name="#NNG_HTTP_STATUS_PROXY_AUTH_REQUIRED"></a></td><td>407</td><td>Proxy Authentication Required</td><td>Proxy requires authentication.</td></tr> +<tr><td><code>NNG_HTTP_STATUS_REQUEST_TIMEOUT</code><a name="#NNG_HTTP_STATUS_REQUEST_TIMEOUT"></a></td><td>408</td><td>Request Timeout</td><td>Timed out waiting for request.</td></tr> +<tr><td><code>NNG_HTTP_STATUS_CONFLICT</code><a name="#NNG_HTTP_STATUS_CONFLICT"></a></td><td>409</td><td>Conflict</td><td>Conflicting request.</td></tr> +<tr><td><code>NNG_HTTP_STATUS_GONE</code><a name="#NNG_HTTP_STATUS_GONE"></a></td><td>410</td><td>Gone</td><td>Resource no longer exists.</td></tr> +<tr><td><code>NNG_HTTP_STATUS_LENGTH_REQUIRED</code><a name="#NNG_HTTP_STATUS_LENGTH_REQUIRED"></a></td><td>411</td><td>Length Required</td><td>Missing Content-Length.</td></tr> +<tr><td><code>NNG_HTTP_STATUS_PRECONDITION_FAILED</code><a name="#NNG_HTTP_STATUS_PRECONDITION_FAILED"></a></td><td>412</td><td>Precondition Failed</td><td></td></tr> +<tr><td><code>NNG_HTTP_STATUS_CONTENT_TOO_LARGE</code><a name="#NNG_HTTP_STATUS_PAYLOAD_TOO_LARGE"></a></td><td>413</td><td>Content Too Large</td><td></td></tr> +<tr><td><code>NNG_HTTP_STATUS_URI_TOO_LONG</code><a name="#NNG_HTTP_STATUS_URI_TOO_LONG"></a></td><td>414</td><td>URI Too Long</td><td></td></tr> +<tr><td><code>NNG_HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE</code><a name="#NNG_HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE"></a></td><td>415</td><td>Unsupported Media Type</td><td></td></tr> +<tr><td><code>NNG_HTTP_STATUS_RANGE_NOT_SATISFIABLE</code><a name="#NNG_HTTP_STATUS_RANGE_NOT_SATISFIABLE"></a></td><td>416</td><td>Range Not Satisfiable</td><td></td></tr> +<tr><td><code>NNG_HTTP_STATUS_EXPECTATION_FAILED</code><a name="#NNG_HTTP_STATUS_EXPECTATION_FAILED"></a></td><td>417</td><td>Expectation Failed</td><td></td></tr> +<tr><td><code>NNG_HTTP_STATUS_TEAPOT</code><a name="#NNG_HTTP_STATUS_TEAPOT"></a></td><td>418</td><td>I Am A Teapot</td><td>RFC 2324.</td></tr> +<tr><td><code>NNG_HTTP_STATUS_UNPROCESSABLE_ENTITY</code><a name="#NNG_HTTP_STATUS_UNPROCESSABLE_ENTITY"></a></td><td>422</td><td>Unprocessable Entity</td><td></td></tr> +<tr><td><code>NNG_HTTP_STATUS_LOCKED</code><a name="#NNG_HTTP_STATUS_LOCKED"></a></td><td>423</td><td>Locked</td><td></td></tr> +<tr><td><code>NNG_HTTP_STATUS_FAILED_DEPENDENCY</code><a name="#NNG_HTTP_STATUS_FAILED_DEPEDNENCY"></a></td><td>424</td><td>Failed Dependency</td><td></td></tr> +<tr><td><code>NNG_HTTP_STATUS_TOO_EARLY</code><a name="#NNG_HTTP_STATUS_TOO_EARLY"></a></td><td>425</td><td>Too Early</td><td></td></tr> +<tr><td><code>NNG_HTTP_STATUS_UPGRADE_REQUIRED</code><a name="#NNG_HTTP_STATUS_UPGRADE_REQUIRED"></a></td><td>426</td><td>Upgrade Required</td><td></td></tr> +<tr><td><code>NNG_HTTP_STATUS_PRECONDITION_REQUIRED</code><a name="#NNG_HTTP_STATUS_PRECONDITION_REQUIRED"></a></td><td>428</td><td>Precondition Required</td><td></td></tr> +<tr><td><code>NNG_HTTP_STATUS_TOO_MANY_REQUESTS</code><a name="#NNG_HTTP_STATUS_TOO_MANY_REQUESTS"></a></td><td>429</td><td>Too Many Requests</td><td></td></tr> +<tr><td><code>NNG_HTTP_STATUS_HEADERS_TOO_LARGE</code><a name="#NNG_HTTP_STATUS_HEADERS_TOO_LARGE"></a></td><td>431</td><td>Headers Too Large</td><td></td></tr> +<tr><td><code>NNG_HTTP_STATUS_UNAVAIL_LEGAL_REASONS</code><a name="#NNG_HTTP_STATUS_UNAVAIL_LEGAL_REASONS"></a></td><td>451</td><td>Unavailabe For Legal Reasons</td><td></td></tr> +<tr><td><code>NNG_HTTP_STATUS_INTERNAL_SERVER_ERROR</code><a name="#NNG_HTTP_STATUS_INTERNAL_SERVER_ERROR"></a></td><td>500</td><td>Internal Server Error</td><td></td></tr> +<tr><td><code>NNG_HTTP_STATUS_NOT_IMPLEMENTED</code><a name="#NNG_HTTP_STATUS_NOT_IMPLEMENTED"></a></td><td>501</td><td>Not Implemented</td><td>Server does not implement method.</td></tr> +<tr><td><code>NNG_HTTP_STATUS_BAD_GATEWAY</code><a name="#NNG_HTTP_STATUS_BAD_GATEWAY"></a></td><td>502</td><td>Bad Gateway</td><td></td></tr> +<tr><td><code>NNG_HTTP_STATUS_SERVICE_UNAVAILALE</code><a name="#NNG_HTTP_STATUS_SERVICE_UNAVAILABLE"></a></td><td>503</td><td>Service Unavailable</td><td></td></tr> +<tr><td><code>NNG_HTTP_STATUS_GATEWAY_TIMEOUT</code><a name="#NNG_HTTP_STATUS_GATEWAY_TIMEOUT"></a></td><td>504</td><td>Gateway TImeout</td><td></td></tr> +<tr><td><code>NNG_HTTP_STATUS_HTTP_VERSION_NOT_SUPP</code><a name="#NNG_HTTP_STATUS_HTTP_VERSION_NOT_SUPP"></a></td><td>505</td><td>HTTP Version Not Supported</td><td></td></tr> +<tr><td><code>NNG_HTTP_STATUS_VARIANT_ALSO_NEGOTIATES</code><a name="#NNG_HTTP_STATUS_VARIANT_ALSO_NEGOTIATES"></a></td><td>506</td><td>Variant Also Negotiates</td><td></td></tr> +<tr><td><code>NNG_HTTP_STATUS_INSUFFICIENT_STORAGE</code><a name="#NNG_HTTP_STATUS_INSUFFICIENT_STORAGE"></a></td><td>507</td><td>Variant Also Negotiates</td><td></td></tr> +<tr><td><code>NNG_HTTP_STATUS_LOOP_DETECTED</code><a name="#NNG_HTTP_STATUS_LOOP_DETECTED"></a></td><td>508</td><td>Loop Detected</td><td></td></tr> +<tr><td><code>NNG_HTTP_STATUS_NOT_EXTENDED</code><a name="#NNG_HTTP_STATUS_NOT_EXTENDED"></a></td><td>510</td><td>Not Extended</td><td></td></tr> +<tr><td><code>NNG_HTTP_STATUS_NETWORK_AUTH_REQUIRED</code><a name="#NNG_HTTP_STATUS_NETWORK_AUTH_REQUIRED"></a></td><td>511</td><td>Network Authentication Required</td><td></td></tr> +</tbody></table> +</div> +<h3 id="retrieving-headers"><a class="header" href="#retrieving-headers">Retrieving Headers</a></h3> +<pre><code class="language-c">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); +</code></pre> +<p>The <a name="a012"></a><code>nng_http_get_header</code> returns the header value matching <em>key</em> that was received over <em>conn</em>, +or <code>NULL</code> if no such header exists.</p> +<p>Thus, if <em>conn</em> 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.</p> +<p>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.</p> +<p>The <a name="a013"></a><code>nng_http_next_header</code> function iterates over all the headers, using the same list +that <code>nng_http_get_header</code> uses. To start, it is called with <em>next</em> initialized to <code>NULL</code>. +If a header was found, then it returns <code>true</code>, and sets <em>keyp</em> and <em>valuep</em> to values containing +the header name and value. It also updates <em>next</em>, which should be used for the next iteration.</p> +<p>Once <code>nng_http_next_header</code> returns <code>false</code>, further calls with the same parameters will continue to do so. +The scan can be rest by setting <em>next</em> to <code>NULL</code>.</p> +<h3 id="modifying-headers"><a class="header" href="#modifying-headers">Modifying Headers</a></h3> +<pre><code class="language-c">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); +</code></pre> +<p>The <a name="a014"></a><code>nng_http_add_header</code>, <a name="a015"></a><code>nng_http_set_header</code>, and <a name="a016"></a><code>nng_http_del_header</code> functions are +used to add a modify either the request or response headers for <em>conn</em> prior to sending to the connected peer on <em>conn</em>.</p> +<p>Thus, if the <em>conn</em> is a client connection created by <a href="api//api/http.html#creating-connections"><code>nng_http_client_connect</code></a>, 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.</p> +<p>The <code>nng_http_add_header</code> function adds a header with the name <em>key</em>, and the value <em>val</em>, 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 <a href="api//api/errors.html#NNG_ENOMEM"><code>NNG_ENOMEM</code></a>, <a href="api//api/errors.html#NNG_EMSGSIZE"><code>NNG_EMSGSIZE</code></a>, or <a href="api//api/errors.html#NNG_EINVAL"><code>NNG_EINVAL</code></a>.</p> +<p>The <code>nng_http_set_header</code> function adds the header if it does not already exist, but replaces any and all previously existing +headers with the same name <em>key</em>, if they exist. In all other respects it behaves similarly to <code>nng_http_add_header</code>.</p> +<p>The <code>nng_http_del_header</code> removes all headers with name <em>key</em>.</p> +<div class="mdbook-alerts mdbook-alerts-note"> +<p class="mdbook-alerts-title"> + <span class="mdbook-alerts-icon"></span> + note +</p> +<p>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.</p> +</div> +<h3 id="retrieving-body-content"><a class="header" href="#retrieving-body-content">Retrieving Body Content</a></h3> +<pre><code class="language-c">void nng_http_get_body(nng_http_conn *conn, void **datap, size_t *sizep); +</code></pre> +<p>The <a name="a017"></a><code>nng_http_get_data</code> obtains the most recently received request or +response body. This will be <code>NULL</code> 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”.)</p> +<h3 id="storing-body-content"><a class="header" href="#storing-body-content">Storing Body Content</a></h3> +<pre><code class="language-c">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); +</code></pre> +<p>The <a name="a018"></a><code>nng_http_set_data</code> function sets the outgoing body content to <em>data</em>, +which must be <em>size</em> bytes long. The caller must ensure that <em>data</em> remains +valid for the duration of the transaction.</p> +<p>The <a name="a019"></a><code>nng_http_copy_data</code> function makes a copy of <em>data</em>, which +will be freed automatically when the transaction is finished, but otherwise +behaves like <code>nng_http_set_data</code>.</p> +<p>On client <em>conn</em> objects, these functions update the request object, but on server +<em>conn</em> objects, they update the response object.</p> +<p>These functions also update the relevant “Content-Length” header.</p> +<div class="mdbook-alerts mdbook-alerts-note"> +<p class="mdbook-alerts-title"> + <span class="mdbook-alerts-icon"></span> + note +</p> +<p>The current framework does not support sending data via chunked +transfer-encoding.</p> +</div> +<div class="mdbook-alerts mdbook-alerts-tip"> +<p class="mdbook-alerts-title"> + <span class="mdbook-alerts-icon"></span> + tip +</p> +<p>It is a good idea to also set the <code>Content-Type</code> header.</p> +</div> +<h3 id="closing-the-connection"><a class="header" href="#closing-the-connection">Closing the Connection</a></h3> +<pre><code class="language-c">void nng_http_close(nng_http *conn); +</code></pre> +<p>The <a name="a020"></a><code>nng_http_close</code> function closes the supplied HTTP connection <em>conn</em>, +including any disposing of any underlying file descriptors or related resources.</p> +<p>Once this function, no further access to the <em>conn</em> structure may be made.</p> +<h3 id="reset-connection-state"><a class="header" href="#reset-connection-state">Reset Connection State</a></h3> +<pre><code class="language-c">void nng_http_reset(nng_http *conn); +</code></pre> +<p>The <a name="a021"></a><code>nng_http_reset</code> function resets the request and response state of the +the connection <em>conn</em>, so that it is just as if it had been freshly created with +<a href="api//api/http.html#creating-connections"><code>nng_http_client_connect</code></a> or passed into a handler function for a server callback.</p> +<p>The intended purpose of this function is to clear the object state before reusing the <em>conn</em> for +subsequent transactions.</p> +<h3 id="direct-read-and-write"><a class="header" href="#direct-read-and-write">Direct Read and Write</a></h3> +<pre><code class="language-c">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); +</code></pre> +<p>The <a name="a022"></a><code>nng_http_read</code> and <a name="a023"></a><code>nng_http_write</code> functions read or write data asynchronously from or to the +connection <em>conn</em>, using the <a href="api//api/aio.html#scatter-gather-vectors"><code>nng_iov</code></a> that is set in <em>aio</em> with <a href="api//api/aio.html#scatter-gather-vectors"><code>nng_aio_set_iov</code></a>. +These functions will complete as soon as any data is transferred. +Use <a href="api//api/aio.html#result-of-operation"><code>nng_aio_count</code></a> to determine how much data was actually transferred.</p> +<p>The <a name="a024"></a><code>nng_http_read_all</code> and <a name="a025"></a><code>nng_http_write_all</code> functions perform the same task, but will keep resubmitting +operations until the the entire amount of data requested by the <a href="api//api/aio.html#scatter-gather-vectors"><code>nng_iov</code></a> is transferred.</p> +<div class="mdbook-alerts mdbook-alerts-note"> +<p class="mdbook-alerts-title"> + <span class="mdbook-alerts-icon"></span> + note +</p> +<p>These functions perform no special handling for chunked transfers.</p> +</div> +<p>These functions are most likely to be useful after hijacking the connection with <a href="api//api/http.html#hijacking-connections"><code>nng_http_hijack</code></a>. +They can be used to transfer request or response body data as well.</p> +<h3 id="hijacking-connections"><a class="header" href="#hijacking-connections">Hijacking Connections</a></h3> +<pre><code class="language-c">void nng_http_hijack(nng_http_conn *conn); +</code></pre> +<p>TODO: This API will change to convert the conn into a stream object.</p> +<p>The <a name="a026"></a><code>nng_http_hijack</code> function hijacks the connection <em>conn</em>, causing it +to be disassociated from the HTTP server where it was created.</p> +<p>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.</p> +<p>This function is most useful when called from a handler function. +(See [<code>nng_http_handler_alloc</code>].)</p> +<div class="mdbook-alerts mdbook-alerts-note"> +<p class="mdbook-alerts-title"> + <span class="mdbook-alerts-icon"></span> + note +</p> +<p>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 [<code>nng_http_write_response</code>].)</p> +</div> +<div class="mdbook-alerts mdbook-alerts-tip"> +<p class="mdbook-alerts-title"> + <span class="mdbook-alerts-icon"></span> + tip +</p> +<p>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.</p> +</div> +<h2 id="client-api"><a class="header" href="#client-api">Client API</a></h2> +<p>The NNG client API consists of an API for creating connections, and an API for performing +transactions on those connections.</p> +<h3 id="client-object"><a class="header" href="#client-object">Client Object</a></h3> +<pre><code class="language-c">typedef struct nng_http_client nng_http_client; +</code></pre> +<p>The <a name="a027"></a><code>nng_http_client</code> object is the client side creator for <a href="api//api/http.html#connection-object"><code>nng_http</code></a> objects. +It is analogous to a <a href="api//TODO.html">dialer</a> object used elsewhere in NNG, but it specifically is only for HTTP.</p> +<h3 id="create-a-client"><a class="header" href="#create-a-client">Create a Client</a></h3> +<pre><code class="language-c">void nng_http_client_alloc(nng_http_client *clientp, const nng_url *url); +</code></pre> +<p>The <a name="a028"></a><code>nng_http_client_alloc</code> allocates an HTTP client suitable for +connecting to the server identified by <em>url</em> and stores a pointer to +it in the location referenced by <em>clientp</em>.</p> +<h3 id="destroy-a-client"><a class="header" href="#destroy-a-client">Destroy a Client</a></h3> +<pre><code class="language-c">void nng_http_client_free(nng_http_client *client); +</code></pre> +<p>The <a name="a029"></a><code>nng_http_client_free</code> connection destroys the client object and any +of its resources.</p> +<div class="mdbook-alerts mdbook-alerts-note"> +<p class="mdbook-alerts-title"> + <span class="mdbook-alerts-icon"></span> + note +</p> +<p>Any connections created by <a href="api//api/http.html#creating-connections"><code>nng_http_client_connect</code></a> are not affected by this function, +and must be closed explicitly as needed.</p> +</div> +<h3 id="client-tls"><a class="header" href="#client-tls">Client TLS</a></h3> +<pre><code class="language-c">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); +</code></pre> +<p>The <a name="a030"></a><code>nng_http_client_get_tls</code> and <a name="a031"></a><code>nng_http_client_set_tls</code> functions are used to +retrieve or change the <a href="api//TODO.html">TLS configuration</a> used when making outbound connections, enabling +<a name="a032"></a>TLS as a result.</p> +<p>If TLS has not been previously configured on <em>client</em>, then <code>nng_http_client_get_tls</code> will return <a href="api//api/errors.html#NNG_EINVAL"><code>NNG_EINVAL</code></a>. +Both functions will return <a href="api//api/errors.html#NNG_ENOTSUP"><code>NNG_ENOTSUP</code></a> if either HTTP or TLS is not supported.</p> +<p>Calling <code>nng_http_client_set_tls</code> invalidates any client previously obtained with +<code>nng_http_client_get_tls</code>, unless a separate hold on the object was obtained.</p> +<p>Once TLS is enabled for an <code>nng_http_client</code>, it is not possible to disable TLS.</p> +<div class="mdbook-alerts mdbook-alerts-note"> +<p class="mdbook-alerts-title"> + <span class="mdbook-alerts-icon"></span> + note +</p> +<p>The TLS configuration itself cannnot be changed once it has been used to create a connection, +such as by calling <a href="api//api/http.html#creating-connections"><code>nng_http_client_connect</code></a>, but a new one can be installed in the client. +Existing connections will use the TLS configuration that there were created with.</p> +</div> +<h3 id="creating-connections"><a class="header" href="#creating-connections">Creating Connections</a></h3> +<pre><code class="language-c">#include <nng/http.h> + +void nng_http_client_connect(nng_http_client *client, nng_aio *aio); +</code></pre> +<p>The <a name="a033"></a><code>nng_http_client_connect</code> function makes an outgoing connection to the +server configured for <em>client</em>, and creates an <a href="api//api/http.html#connection-object"><code>nng_http</code></a> object for the connection.</p> +<p>This is done asynchronously, and when the operation succeseds the connection may be +retried from the <em>aio</em> using <a href="api//api/aio.html#inputs-and-outputs"><code>nng_aio_get_output</code></a> with index 0.</p> +<h4 id="example-1-connecting-to-google"><a class="header" href="#example-1-connecting-to-google">Example 1: Connecting to Google</a></h4> +<pre><code class="language-c">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); +} +</code></pre> +<h3 id="preparing-a-transaction"><a class="header" href="#preparing-a-transaction">Preparing a Transaction</a></h3> +<pre><code class="language-c">int nng_http_set_version(nng_http *conn, const char *version); +int nng_http_set_uri(nng_http *conn, const char *uri); +</code></pre> +<p>The <a name="a034"></a><code>nng_http_set_uri</code> 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.</p> +<h3 id="request-body"><a class="header" href="#request-body">Request Body</a></h3> +<h3 id="sending-the-request"><a class="header" href="#sending-the-request">Sending the Request</a></h3> +<pre><code class="language-c">void nng_http_write_request(nng_http *conn, nng_aio *aio); +</code></pre> +<p>The <a name="a035"></a><code>nng_http_write_request</code> function starts an asynchronous write of +the HTTP request associated with <em>conn</em>. +The entire request is sent, +including headers, and if present, the request body data. +(The request body can be set with +[<code>nng_http_set_data</code>] or [<code>nng_http_copy_data</code>].)</p> +<p>This function returns immediately, with no return value. +Completion of the operation is signaled via the <em>aio</em>, and the final result +may be obtained via <a href="api//api/aio.html#result-of-operation"><code>nng_aio_result</code></a>.</p> +<div class="mdbook-alerts mdbook-alerts-tip"> +<p class="mdbook-alerts-title"> + <span class="mdbook-alerts-icon"></span> + tip +</p> +<p>Consider using the [<code>nng_http_transact</code>] function, +which provides a simpler interface for performing a complete HTTP client transaction.</p> +</div> +<h2 id="obtaining-the-response"><a class="header" href="#obtaining-the-response">Obtaining the Response</a></h2> +<pre><code class="language-c">void nng_http_read_response(nng_http *conn, nng_aio *aio); +</code></pre> +<p>The <a name="a036"></a><code>nng_http_read_response</code> function starts an asynchronous read from the +HTTP connection <em>conn</em>, reading an HTTP response into the response associated with <em>conn</em>, including all +of the related headers.</p> +<p>It does <em>not</em> transfer any response body. To do that, use <a href="api//api/http.html#direct-read-and-write"><code>nng_http_read_all</code></a> or <a href="api//api/http.html#direct-read-and-write"><code>nng_http_read</code></a>.</p> +<div class="mdbook-alerts mdbook-alerts-note"> +<p class="mdbook-alerts-title"> + <span class="mdbook-alerts-icon"></span> + note +</p> +<p>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.</p> +</div> +<div class="mdbook-alerts mdbook-alerts-tip"> +<p class="mdbook-alerts-title"> + <span class="mdbook-alerts-icon"></span> + tip +</p> +<p>An easier one-shot method for many use cases might be [<code>nng_http_transact</code>].</p> +</div> +<h3 id="submitting-the-transaction"><a class="header" href="#submitting-the-transaction">Submitting the Transaction</a></h3> +<pre><code class="language-c">int nng_http_transact(nng_http *conn, nng_aio *aio); +</code></pre> +<p>The HTTP request is issued, and the response processed, asynchronously by the <a name="a037"></a><code>nng_http_transact</code> function. +When the function is complete, the <em>aio</em> will be notified.</p> +<p>The <a name="a038"></a><code>nng_http_transact</code> function is used to perform a complete +HTTP exchange over the connection <em>conn</em>, sending the request +and attached body data to the remote server, and reading the response.</p> +<p>The entire response is read, including any associated body, which can +subsequently be obtained using [<code>nng_http_get_data</code>].</p> +<p>This function is intended to make creation of client applications easier, +by performing multiple asynchronous operations required to complete an +entire HTTP transaction.</p> +<p>If an error occurs, the caller should close <em>conn</em> with <a href="api//api/http.html#closing-the-connection"><code>nng_http_close</code></a>, as it may not +necessarily be usable with other transactions.</p> +<div class="mdbook-alerts mdbook-alerts-warning"> +<p class="mdbook-alerts-title"> + <span class="mdbook-alerts-icon"></span> + warning +</p> +<p>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.</p> +</div> +<div class="mdbook-alerts mdbook-alerts-note"> +<p class="mdbook-alerts-title"> + <span class="mdbook-alerts-icon"></span> + note +</p> +<p>A given connection <em>conn</em> should be used with only one +operation or transaction at a time as HTTP/1.1 has no support for +request interleaving.</p> +</div> +<p>This function returns immediately, with no return value. +Completion of the operation is signaled via the <em>aio</em>, and the final result +may be obtained via [<code>nng_aio_result()</code>].</p> +<h3 id="response-body"><a class="header" href="#response-body">Response Body</a></h3> +<h2 id="server-api"><a class="header" href="#server-api">Server API</a></h2> +<h3 id="handlers"><a class="header" href="#handlers">Handlers</a></h3> +<h3 id="sending-the-response"><a class="header" href="#sending-the-response">Sending the Response</a></h3> +<pre><code class="language-c">void nng_http_write_response(nng_http *conn, nng_aio *aio); +</code></pre> +<p>Normally the server will send any attached response, but there are circumstances where +a response must be sent manually, such as when <a href="api//api/http.html#hijacking-connections">hijacking</a> a connection.</p> +<p>In such a case, <a name="a039"></a><code>nng_http_write_response</code> can be called, which will send the response and any attached data, asynchronously +using the <a href="api//api/aio.html#asynchronous-io-handle"><code>nng_aio</code></a> <em>aio</em>.</p> +<p>By default, for <code>HTTP/1.1</code> connections, the connection is kept open, and +will be reused to receive new requests. For <code>HTTP/1.0</code>, or if the client has requested +explicitly by setting the “Connection: close” header, the connection will be closed after the +response is fully sent.</p> +<!-- Symbol cross reference --> +<!-- HTTP --> <!-- Macros --> <!-- Protocols --> <!-- Transports --> @@ -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.)</p> <!-- Symbol cross reference --> +<!-- HTTP --> <!-- Macros --> <!-- Protocols --> <!-- Transports --> @@ -4332,6 +4910,7 @@ iteration is undefined; entries may be repeated or omitted during such an iterat <p>The caller must not attempt to derive any value of the <em>cursor</em> as it refers to internal table indices.</p> <!-- Symbol cross reference --> +<!-- HTTP --> <!-- Macros --> <!-- Protocols --> <!-- Transports --> @@ -4582,6 +5161,7 @@ unambiguously (meaning it must not match any other option specification.)</p> } </code></pre> <!-- Symbol cross reference --> +<!-- HTTP --> <!-- Macros --> <!-- Protocols --> <!-- Transports --> @@ -6148,6 +6728,7 @@ the <em>inproc</em> transport to communicate across this boundary.</p> <p>This limitation also extends to using different instances of the <em>NNG</em> library within the same process.</p> <!-- Symbol cross reference --> +<!-- HTTP --> <!-- Macros --> <!-- Protocols --> <!-- Transports --> @@ -6310,6 +6891,7 @@ where supported by the underlying platform.</p> which can be used to control access, can be set using the function <a href="tran//TODO.html"><code>nng_listener_set_security_descriptor</code></a>.</p> <!-- Symbol cross reference --> +<!-- HTTP --> <!-- Macros --> <!-- Protocols --> <!-- Transports --> @@ -6437,6 +7019,7 @@ There are no further socket details available.</p> These behave in exactly the same fashion as for the <em><a href="tran//tran/ipc.html">ipc</a></em> transport.</p> </div> <!-- Symbol cross reference --> +<!-- HTTP --> <!-- Macros --> <!-- Protocols --> <!-- Transports --> @@ -6610,6 +7193,7 @@ In order to ensure that resources are reclaimed when a peer vanishes unexpectedl keep-alive mechanism is implemented.</p> <p>TODO: Document the tunables for this.</p> <!-- Symbol cross reference --> +<!-- HTTP --> <!-- Macros --> <!-- Protocols --> <!-- Transports --> @@ -6866,10 +7450,6 @@ can be simply removed from your application:</p> </ul> <p>Additionally, the header files containing these functions have been removed, such as <code>nng/transport/ipc/ipc.h</code>. Simply remove <code>#include</code> references to those files.</p> -<p>The <code>NNG_OPT_WSS_REQUEST_HEADERS</code> and <code>NNG_OPT_WSS_RESPONSE_HEADERS</code> aliases for -<code>NNG_OPT_WS_OPT_WS_REQUEST_HEADERS</code> and <code>NNG_OPT_WS_RESPONSE_HEADERS</code> have been removed. -Just convert any use of them to <code>NNG_OPT_WS_REQUEST_HEADERS</code> or -<code>NNG_OPT_WS_RESPONSE_HEADERS</code> as appropriate.</p> <h2 id="tls-configuration-1"><a class="header" href="#tls-configuration-1">TLS Configuration</a></h2> <p>The support for configuring TLS via <code>NNG_OPT_TLS_CONFIG</code>, <code>NNG_TLS_AUTH_MODE</code>, <code>NNG_OPT_TLS_CA_FILE</code>, <code>NNG_OPT_TLS_SERVER_NAME</code>, and similar has been removed.</p> @@ -7032,6 +7612,8 @@ accessors functions are provided:</p> <li><code>u_rawurl</code> is removed - a “cooked” URL can be obtained from the new <a href="migrate//api/url.html#format-a-url"><code>nng_url_sprintf</code></a> function.</li> </ul> <h2 id="http-api"><a class="header" href="#http-api">HTTP API</a></h2> +<p>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.</p> <p>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:</p> @@ -7055,6 +7637,15 @@ They may silently truncate data.</p> </ul> <p>The HTTP handler objects may not be modified once in use. Previously this would fail with <code>NNG_EBUSY</code>. These checks are removed now, but debug builds will assert if an application tries to do so.</p> +<h2 id="websocket-api"><a class="header" href="#websocket-api">WebSocket API</a></h2> +<p>The <code>NNG_OPT_WSS_REQUEST_HEADERS</code>, <code>NNG_OPT_WSS_RESPONSE_HEADERS</code> and +<code>NNG_OPT_WS_OPT_WS_REQUEST_HEADERS</code>, <code>NNG_OPT_WS_RESPONSE_HEADERS</code> have been removed.</p> +<p>The <code>NNG_OPT_WS_REQUEST_HEADER</code> and <code>NNG_OPT_WS_RESPONSE_HEADER</code> option prefixes have been +collapsed into just <code>NNG_OPT_WS_HEADER</code>, 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.</p> +<p>The undocumented hook function signature has changed to reflect changes in the HTTP API.</p> <h2 id="security-descriptors-windows-only"><a class="header" href="#security-descriptors-windows-only">Security Descriptors (Windows Only)</a></h2> <p>The <code>NNG_OPT_IPC_SECURITY_DESCRIPTOR</code> option is removed, and replaced with the functions [<code>nng_listener_get_security_descriptor</code>] and @@ -7072,6 +7663,7 @@ See <a href="migrate//api/args.html#parse-command-line-arguments"><code>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.</p> <!-- Symbol cross reference --> +<!-- HTTP --> <!-- Macros --> <!-- Protocols --> <!-- Transports --> @@ -7254,6 +7846,7 @@ using <code>nn_dial</code> inside the URL is not present in NNG. The correct way to specify the local address is using the <code>NNG_OPT_LOCADDR</code> option on the dialer before starting to dial.</p> <!-- Symbol cross reference --> +<!-- HTTP --> <!-- Macros --> <!-- Protocols --> <!-- Transports --> @@ -7358,6 +7951,40 @@ named pipes, <a href="tran/ipc.html#a004">1</a><br/> <code>nng_fini</code>, <a href="api/init.html#a002">1</a><br/> <code>NNG_FLAG_NONBLOCK</code>, <a href="api/sock.html#a037">1</a>, <a href="api/sock.html#a041">2</a><br/> <code>nng_free</code>, <a href="api/memory.html#a004">1</a><br/> +<code>nng_http</code>, <a href="api/http.html#a001">1</a><br/> +<code>nng_http_add_header</code>, <a href="api/http.html#a014">1</a><br/> +<code>nng_http_client</code>, <a href="api/http.html#a027">1</a><br/> +<code>nng_http_client_alloc</code>, <a href="api/http.html#a028">1</a><br/> +<code>nng_http_client_connect</code>, <a href="api/http.html#a033">1</a><br/> +<code>nng_http_client_free</code>, <a href="api/http.html#a029">1</a><br/> +<code>nng_http_client_get_tls</code>, <a href="api/http.html#a030">1</a><br/> +<code>nng_http_client_set_tls</code>, <a href="api/http.html#a031">1</a><br/> +<code>nng_http_close</code>, <a href="api/http.html#a020">1</a><br/> +<code>nng_http_copy_data</code>, <a href="api/http.html#a019">1</a><br/> +<code>nng_http_del_header</code>, <a href="api/http.html#a016">1</a><br/> +<code>nng_http_get_data</code>, <a href="api/http.html#a017">1</a><br/> +<code>nng_http_get_header</code>, <a href="api/http.html#a012">1</a><br/> +<code>nng_http_get_method</code>, <a href="api/http.html#a003">1</a><br/> +<code>nng_http_get_reason</code>, <a href="api/http.html#a010">1</a><br/> +<code>nng_http_get_status</code>, <a href="api/http.html#a009">1</a><br/> +<code>nng_http_get_version</code>, <a href="api/http.html#a008">1</a><br/> +<code>nng_http_hijack</code>, <a href="api/http.html#a026">1</a><br/> +<code>nng_http_next_header</code>, <a href="api/http.html#a013">1</a><br/> +<code>nng_http_read</code>, <a href="api/http.html#a022">1</a><br/> +<code>nng_http_read_all</code>, <a href="api/http.html#a024">1</a><br/> +<code>nng_http_read_response</code>, <a href="api/http.html#a036">1</a><br/> +<code>nng_http_reset</code>, <a href="api/http.html#a021">1</a><br/> +<code>nng_http_set_data</code>, <a href="api/http.html#a018">1</a><br/> +<code>nng_http_set_header</code>, <a href="api/http.html#a015">1</a><br/> +<code>nng_http_set_method</code>, <a href="api/http.html#a002">1</a><br/> +<code>nng_http_set_status</code>, <a href="api/http.html#a011">1</a><br/> +<code>nng_http_set_uri</code>, <a href="api/http.html#a004">1</a>, <a href="api/http.html#a034">2</a><br/> +<code>nng_http_set_version</code>, <a href="api/http.html#a007">1</a><br/> +<code>nng_http_transact</code>, <a href="api/http.html#a037">1</a>, <a href="api/http.html#a038">2</a><br/> +<code>nng_http_write</code>, <a href="api/http.html#a023">1</a><br/> +<code>nng_http_write_all</code>, <a href="api/http.html#a025">1</a><br/> +<code>nng_http_write_request</code>, <a href="api/http.html#a035">1</a><br/> +<code>nng_http_write_response</code>, <a href="api/http.html#a039">1</a><br/> <code>nng_id_alloc</code>, <a href="api/id_map.html#a006">1</a><br/> <code>nng_id_get</code>, <a href="api/id_map.html#a005">1</a><br/> <code>nng_id_map</code>, <a href="api/id_map.html#a001">1</a><br/> @@ -7559,6 +8186,7 @@ named pipes, <a href="tran/ipc.html#a004">1</a><br/> <code>nng_url_sprintf</code>, <a href="api/url.html#a010">1</a><br/> <code>nng_url_userinfo</code>, <a href="api/url.html#a004">1</a><br/> <code>nng_version</code>, <a href="api/misc.html#a004">1</a><br/> +<code>nni_http_get_uri</code>, <a href="api/http.html#a006">1</a><br/> <em>PAIR</em>, <a href="proto/pair.html#a002">1</a><br/> <em>PAIR</em> protocol, <a href="proto/pair.html#a001">1</a><br/> pipeline pattern, <a href="proto/pull.html#a003">1</a>, <a href="proto/push.html#a003">2</a>, <a href="proto/index.html#a003">3</a><br/> @@ -7603,13 +8231,14 @@ synchronization primitives, <a href="api/synch.html#a001">1</a><br/> threads, <a href="api/thread.html#a001">1</a><br/> thundering herd, <a href="api/synch.html#a016">1</a><br/> timeout, <a href="api/aio.html#a012">1</a><br/> -TLS, <a href="api/stream.html#a062">1</a><br/> +TLS, <a href="api/stream.html#a062">1</a>, <a href="api/http.html#a032">2</a><br/> UDP, <a href="tran/udp.html#a002">1</a><br/> <em>udp</em> transport, <a href="tran/udp.html#a001">1</a><br/> <code>udp://</code>, <a href="tran/udp.html#a005">1</a><br/> Universal Resource Locator, <a href="api/url.html#a001">1</a><br/> UNIX domain sockets, <a href="tran/ipc.html#a003">1</a><br/> <code>unix://</code>, <a href="tran/ipc.html#a006">1</a><br/> +URI, <a href="api/http.html#a005">1</a><br/> URL, <a href="api/url.html#a002">1</a>, <a href="api/stream.html#a024">2</a><br/> version number, <a href="api/misc.html#a005">1</a><br/> voting, <a href="proto/surveyor.html#a004">1</a><br/></p> |
