summaryrefslogtreecommitdiff
path: root/ref/api/http.html
diff options
context:
space:
mode:
authorgdamore <gdamore@users.noreply.github.com>2025-01-16 02:43:50 +0000
committergdamore <gdamore@users.noreply.github.com>2025-01-16 02:43:50 +0000
commit3db54322b4b6024b34878a277789ef082872189b (patch)
tree4c92c574a53c699f37e626618e0c834cc67e8e54 /ref/api/http.html
parente605ded920a4636e93edbbea31d9625ca5428dfb (diff)
downloadnng-3db54322b4b6024b34878a277789ef082872189b.tar.gz
nng-3db54322b4b6024b34878a277789ef082872189b.tar.bz2
nng-3db54322b4b6024b34878a277789ef082872189b.zip
deploy: c4ca4834e39e48676ea50df1fc6239c7dc2a56ff
Diffstat (limited to 'ref/api/http.html')
-rw-r--r--ref/api/http.html223
1 files changed, 218 insertions, 5 deletions
diff --git a/ref/api/http.html b/ref/api/http.html
index 03ab3ef6..4b2713a6 100644
--- a/ref/api/http.html
+++ b/ref/api/http.html
@@ -586,7 +586,7 @@ retried from the <em>aio</em> using <a href="/api/aio.html#inputs-and-outputs"><
nng_url *url;
nng_http_client *client;
nng_http *conn;
-int rv;
+nng_err rv;
// Error checks elided for clarity.
nng_url_parse(&amp;url, "http://www.google.com");
@@ -611,7 +611,6 @@ if ((rv = nng_aio_result(aio)) != 0) {
}
</code></pre>
<h3 id="preparing-a-transaction"><a class="header" href="#preparing-a-transaction">Preparing a Transaction</a></h3>
-<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>
@@ -632,7 +631,7 @@ may be obtained via <a href="/api/aio.html#result-of-operation"><code>nng_aio_re
<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>
+<h3 id="obtaining-the-response"><a class="header" href="#obtaining-the-response">Obtaining the Response</a></h3>
<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
@@ -695,12 +694,226 @@ 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">typedef struct nng_http_handler nng_http_handler;
+</code></pre>
+<p>An <a name="a039"></a><code>nng_http_handler</code> encapsulates a function used used to handle
+incoming requests on an HTTP server, routed based on method and URI,
+and the parameters used with that function.</p>
+<p>Every handler has a Request-URI to which it refers, which is determined by the <em>path</em> argument.
+Only the path component of the Request URI is considered when determining whether the handler should be called.</p>
+<p>This implementation limits the <em>path</em> length to 1024 bytes, including the
+zero termination byte. This does not prevent requests with much longer
+URIs from being supported, but doing so will require setting the handler to match a parent path in the tree using
+[<code>nng_http_handler_set_tree</code>].</p>
+<div class="mdbook-alerts mdbook-alerts-tip">
+<p class="mdbook-alerts-title">
+ <span class="mdbook-alerts-icon"></span>
+ tip
+</p>
+<p>The NNG HTTP framework is optimized for URLs shorter than 200 characters.</p>
+</div>
+<p>Additionally each handler has a method it is registered to handle
+(the default is “GET” andc can be changed with [<code>nng_http_handler_set_method</code>]), and
+optionally a “Host” header it can be matched against (see [<code>nng_http_handler_set_host</code>]).</p>
+<p>In some cases, a handler may reference a logical tree rather (directory)
+rather than just a single element.
+(See [<code>nng_http_handler_set_tree</code>]).</p>
+<h3 id="implementing-a-handler"><a class="header" href="#implementing-a-handler">Implementing a Handler</a></h3>
+<pre><code class="language-c">typedef void (*nng_http_hander_func)(nng_http_conn *conn, void *arg, nng_aio *aio);
+
+nng_err nng_http_handler_alloc(nng_http_handler **hp, const char *path, nng_http_handler_func cb);
+</code></pre>
+<p>The <a name="a040"></a><code>nng_http_handler_alloc</code> function allocates a generic 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 <em>hp</em>.</p>
+<p>The handler function is specified by <em>cb</em>.
+This function uses the asynchronous I/O framework.</p>
+<p>The function receives the connection on <em>conn</em>, and an optional data pointer that was set
+previously with [<code>nng_http_handler_set_data</code>] as the second argument. The
+final argument is the <a href="/api/aio.html#asynchronous-io-handle"><code>nng_aio</code></a> <em>aio</em>, which must be “finished” to complete the operation.</p>
+<p>The handler may call [<code>nng_http_write_response</code>] to send the response, or
+it may simply let the framework do so on its behalf. The server will perform
+this step if the callback has not already done so.</p>
+<p>Response headers may be set using <a href="/api/http.html#modifying-headers"><code>nng_http_set_header</code></a>, and request headers
+may be accessed by using <a href="/api/http.html#retrieving-headers"><code>nng_http_get_header</code></a>.</p>
+<p>Likewise the request body may be accessed, using <a href="/api/http.html#retrieving-body-content"><code>nng_http_get_body</code></a>, and
+the response body may be set using either <a href="/api/http.html#storing-body-content"><code>nng_http_set_body</code></a> or <a href="/api/http.html#storing-body-content"><code>nng_http_copy_body</code></a>.</p>
+<div class="mdbook-alerts mdbook-alerts-note">
+<p class="mdbook-alerts-title">
+ <span class="mdbook-alerts-icon"></span>
+ note
+</p>
+<p>The request body is only collected for the handler if the
+[<code>nng_http_handler_collect_body</code>] function has been called for the handler.</p>
+</div>
+<p>The HTTP status should be set for the transaction using <a href="/api/http.html#http-status"><code>nng_http_set_status</code></a>.</p>
+<p>Finally, the handler should finish the operation by calling the <a href="/TODO.html"><code>nng_aio_finish</code></a> function
+after having set the status to [<code>NNG_OK</code>].
+If any other status is set on the <em>aio</em>, then a generic 500 response will be created and
+sent, if possible, and the connection will be closed.</p>
+<p>The <em>aio</em> may be scheduled for deferred completion using the <a href="/TODO.html"><code>nng_aio_start</code></a>.</p>
+<h3 id="serving-directories-and-files"><a class="header" href="#serving-directories-and-files">Serving Directories and Files</a></h3>
+<pre><code class="language-c">nng_err nng_http_handler_alloc_directory(nng_http_handler **hp, const char *path, const char *dirname);
+nng_err nng_http_handler_alloc_file(nng_http_handler **hp, const char *path, const char *filename);
+</code></pre>
+<p>The <a name="a041"></a><code>nng_http_handler_alloc_directory</code> and <a name="a042"></a><code>nng_http_handler_alloc_file</code>
+create handlers pre-configured to act as static content servers for either a full
+directory at <em>dirname</em>, or the single file at <em>filename</em>. These support the “GET” and “HEAD”
+methods, and the directory variant will dynamically generate <code>index.html</code> content based on
+the directory contents. These will also set the “Content-Type” if the file extension
+matches one of the built-in values already known. If the no suitable MIME type can be
+determined, the content type is set to “application/octet-stream”.</p>
+<h3 id="static-handler"><a class="header" href="#static-handler">Static Handler</a></h3>
+<pre><code class="language-c">nng_err nng_http_handler_alloc_static(nng_http_handler **hp, const char *path,
+ const void *data, size_t size, const char *content_type);
+</code></pre>
+<p>The <a name="a043"></a><code>nng_http_handler_alloc_static</code> function creates a handler that
+serves the content located in <em>data</em> (consisting of <em>size</em> bytes) at the URI <em>path</em>.
+The <em>content_type</em> determines the “Content-Type” header. If <code>NULL</code> is specified
+then a value of <code>application/octet-stream</code> is assumed.</p>
+<h3 id="redirect-handler"><a class="header" href="#redirect-handler">Redirect Handler</a></h3>
+<pre><code class="language-c">nng_err nng_http_handler_alloc_redirect(nng_http_handler **hp, const char *path,
+ nng_http_status status, const char *location);
+</code></pre>
+<p>The <a name="a044"></a><code>nng_http_handler_alloc_redirect</code> function creates a handler with
+a function that simply directions from the URI at <em>path</em> to the given <em>location</em>.</p>
+<p>The HTTP reply it creates will be with [status code][<code>nng_http_status</code>] <em>status</em>,
+which should be a 3XX code such as 301, and a <code>Location:</code> header will contain the URL
+referenced by <em>location</em>, with any residual suffix from the request
+URI appended.</p>
+<div class="mdbook-alerts mdbook-alerts-tip">
+<p class="mdbook-alerts-title">
+ <span class="mdbook-alerts-icon"></span>
+ tip
+</p>
+<p>Use [<code>nng_http_handler_set_tree</code>] to redirect an entire tree.
+For example, it is possible to redirect an entire HTTP site to another
+HTTPS site by specifying <code>/</code> as the path and then using the base
+of the new site, such as <code>https://newsite.example.com</code> as the new location.</p>
+</div>
+<div class="mdbook-alerts mdbook-alerts-tip">
+<p class="mdbook-alerts-title">
+ <span class="mdbook-alerts-icon"></span>
+ tip
+</p>
+<p>Be sure to use the appropriate value for <em>status</em>.
+Permanent redirection should use [<code>NNG_HTTP_STATUS_STATUS_MOVED_PERMANENTLY</code>] (301)
+and temporary redirections should use [<code>NNG_HTTP_STATUS_TEMPORARY_REDIRECT</code>] (307).
+In REST APIs, using a redirection to supply the new location of an object
+created with <code>POST</code> should use [<code>NNG_HTTP_STATUS_SEE_OTHER</code>] (303).</p>
+</div>
+<h3 id="collecting-request-body"><a class="header" href="#collecting-request-body">Collecting Request Body</a></h3>
+<pre><code class="language-c">void nng_http_handler_collect_body(nng_http_handler *handler, bool want, size_t maxsz);
+</code></pre>
+<p>The <a name="a045"></a><code>nng_http_handler_collect_body</code> function requests that HTTP server
+framework collect any reuqest body for the request and attach it to the
+connection before calling the callback for the <em>handler</em>.</p>
+<p>Subsequently the data can be retrieved by the handler from the request with the
+<a href="/api/http.html#retrieving-body-content"><code>nng_http_get_body</code></a> function.</p>
+<p>The collection is enabled if <em>want</em> is true.
+Furthermore, the data that the client may sent is limited by the
+value of <em>maxsz</em>.
+If the client attempts to send more data than <em>maxsz</em>, then the
+request will be terminated with [<code>NNG_HTTP_STATUS_CONTENT_TOO_LARGE</code>] (413).</p>
+<div class="mdbook-alerts mdbook-alerts-tip">
+<p class="mdbook-alerts-title">
+ <span class="mdbook-alerts-icon"></span>
+ tip
+</p>
+<p>Limiting the size of incoming request data can provide protection
+against denial of service attacks, as a buffer of the client-supplied
+size must be allocated to receive the data.</p>
+</div>
+<blockquote>
+<p>In order to provide an unlimited size, use <code>(size_t)-1</code> for <em>maxsz</em>.
+The value <code>0</code> for <em>maxsz</em> can be used to prevent any data from being passed
+by the client.</p>
+</blockquote>
+<blockquote>
+<p>The built-in handlers for files, directories, and static data limit the
+<em>maxsz</em> to zero by default.
+Otherwise the default setting is to enable this capability with a default
+value of <em>maxsz</em> of 1 megabyte.</p>
+</blockquote>
+<div class="mdbook-alerts mdbook-alerts-note">
+<p class="mdbook-alerts-title">
+ <span class="mdbook-alerts-icon"></span>
+ note
+</p>
+<p>NNG specifically does not support the <code>Chunked</code> transfer-encoding.
+This is considered a bug, and is a deficiency for full HTTP/1.1 compliance.
+However, few clients send data in this format, so in practice this should
+create few limitations.</p>
+</div>
+<h3 id="setting-callback-argument"><a class="header" href="#setting-callback-argument">Setting Callback Argument</a></h3>
+<pre><code class="language-c">void nng_http_handler_set_data(nng_http_handler *handler, void *data,
+ void (*dtor)(void *));
+</code></pre>
+<p>The <a name="a046"></a><code>nng_http_handler_set_data</code> function is used to set the
+<em>data</em> argument that will be passed to the callback.</p>
+<p>Additionally, when the handler is deallocated, if <em>dtor</em> is not <code>NULL</code>,
+then it will be called with <em>data</em> as its argument.
+The intended use of this function is deallocate any resources associated with <em>data</em>.</p>
+<h3 id="setting-the-method"><a class="header" href="#setting-the-method">Setting the Method</a></h3>
+<pre><code class="language-c">void nng_http_handler_set_method(nng_http_handler *handler, const char *method);
+</code></pre>
+<p>The <a name="a047"></a><code>nng_http_handler_set_method</code> function sets the <em>method</em> that the
+<em>handler</em> will be called for, such as “GET” or “POST”.
+(By default the “GET” method is handled.)</p>
+<p>If <em>method</em> is <code>NULL</code> the handler will be executed for all methods.
+The handler may determine the actual method used with the <a href="/api/http.html#http-method"><code>nng_http_get_method</code></a> function.</p>
+<p>The server will automatically call “GET” handlers if the client
+sends a “HEAD” request, and will suppress HTTP body data in the responses
+sent for such requests.</p>
+<div class="mdbook-alerts mdbook-alerts-note">
+<p class="mdbook-alerts-title">
+ <span class="mdbook-alerts-icon"></span>
+ note
+</p>
+<p>If <em>method</em> is longer than 32-bytes, it may be truncated silently.</p>
+</div>
+<h3 id="filtering-by-host"><a class="header" href="#filtering-by-host">Filtering by Host</a></h3>
+<pre><code class="language-c">void nng_http_handler_set_host(nng_http_handler *handler, const char *host);
+</code></pre>
+<p>The <a name="a048"></a><code>nng_http_handler_set_host</code> function is used to limit the scope of the
+<em>handler</em> so that it will only be called when the specified <em>host</em> matches
+the value of the <code>Host:</code> HTTP header.</p>
+<p>This can be used to create servers with different content for different virtual hosts.</p>
+<p>The value of the <em>host</em> can include a colon and port, and should match
+exactly the value of the <code>Host</code> header sent by the client.
+(Canonicalization of the host name is performed.)</p>
+<div class="mdbook-alerts mdbook-alerts-note">
+<p class="mdbook-alerts-title">
+ <span class="mdbook-alerts-icon"></span>
+ note
+</p>
+<p>The port number may be ignored; at present the HTTP server framework
+does not support a single server listening on different ports concurrently.</p>
+</div>
+<h3 id="handling-an-entire-tree"><a class="header" href="#handling-an-entire-tree">Handling an Entire Tree</a></h3>
+<pre><code class="language-c">void nng_http_handler_set_tree(nng_http_handler *handler);
+</code></pre>
+<p>The <a name="a049"></a><code>nng_http_handler_set_tree</code> function causes the <em>handler</em> to be matched if the request URI sent
+by the client is a logical child of the path for <em>handler</em>, and no more specific
+<em>handler</em> has been registered.</p>
+<p>This is useful in cases when the handler would like to examine the entire path
+and possibly behave differently; for example a REST API that uses the rest of
+the path to pass additional parameters.</p>
+<div class="mdbook-alerts mdbook-alerts-tip">
+<p class="mdbook-alerts-title">
+ <span class="mdbook-alerts-icon"></span>
+ tip
+</p>
+<p>This function is useful when constructing API handlers where a single
+service address (path) supports dynamically generated children.
+It can also provide a logical fallback instead of relying on a 404 error code.</p>
+</div>
+<h3 id="sending-the-response-explicitly"><a class="header" href="#sending-the-response-explicitly">Sending the Response Explicitly</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/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
+<p>In such a case, <a name="a050"></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/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