diff --git a/docs/man/nng_http_handler_alloc.3http.adoc b/docs/man/nng_http_handler_alloc.3http.adoc index 8d55c7522..3eb9674a5 100644 --- a/docs/man/nng_http_handler_alloc.3http.adoc +++ b/docs/man/nng_http_handler_alloc.3http.adoc @@ -114,11 +114,7 @@ The `Content-Type` will be set automatically based upon the extension of the requested file name. If a content type cannot be determined from the extension, then `application/octet-stream` is used. -The directory handler is created as a tree handler initially in exclusive mode (see -xref:nng_http_handler_set_tree.3http.adoc[nng_http_handler_set_tree_exclusive]). -This can be changed by calling -xref:nng_http_handler_set_tree.3http.adoc[nng_http_handler_set_tree(3http)] -after creating the directory handler. +The directory handler is created as a tree handler. === File Handler @@ -183,7 +179,6 @@ xref:nng_http_handler_free.3http.adoc[nng_http_handler_free(3http)], xref:nng_http_handler_set_host.3http.adoc[nng_http_handler_set_host(3http)], xref:nng_http_handler_set_method.3http.adoc[nng_http_handler_set_method(3http)], xref:nng_http_handler_set_tree.3http.adoc[nng_http_handler_set_tree(3http)], -xref:nng_http_handler_set_tree.3http.adoc[nng_http_handler_set_tree_exclusive(3http)], xref:nng_http_server_add_handler.3http.adoc[nng_http_server_add_handler(3http)], xref:nng_strerror.3.adoc[nng_strerror(3)], xref:nng_aio.5.adoc[nng_aio(5)], diff --git a/docs/man/nng_http_handler_set_tree.3http.adoc b/docs/man/nng_http_handler_set_tree.3http.adoc index 821a5f7bf..77b1cc598 100644 --- a/docs/man/nng_http_handler_set_tree.3http.adoc +++ b/docs/man/nng_http_handler_set_tree.3http.adoc @@ -1,6 +1,6 @@ = nng_http_handler_set_tree(3http) -// Copyright 2024 Staysail Systems, Inc. +// Copyright 2025 Staysail Systems, Inc. // Copyright 2018 Capitar IT Group BV // Copyright 2020 Dirac Research // @@ -21,8 +21,6 @@ nng_http_handler_set_tree - set HTTP handler to match trees #include void nng_http_handler_set_tree(nng_http_handler *handler); - -void nng_http_handler_set_tree_exclusive(nng_http_handler *handler); ---- == DESCRIPTION @@ -31,27 +29,17 @@ The `nng_http_handler_set_tree()` function causes the _handler_ to be matched if by the client is a logical child of the path for _handler_, and no more specific _handler_ has been registered. -The `nng_http_handler_set_tree_exclusive()` function is similar to `nng_http_server_set_tree()` -with the distinction that the _handler_ will be considered to *exclusively* handle its request URI. -Unlike `nng_http_server_set_tree()`, it will not be possible to register additional -handlers in logical subdirectories of _handler_. - 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. -TIP: These methods are useful when constructing API handlers where a single +TIP: This function is useful when constructing API handlers where a single service address (path) supports dynamically generated children. - -TIP: The non-exclusive form is also useful for providing a default handler to be -generated when a more specific child does not exist. -This can provide a better experience for users than the standard 404 error -handling. +It can also provide a logical fallback instead of relying on a 404 error code. == SEE ALSO [.text-left] xref:nng_http_handler_alloc.3http.adoc[nng_http_handler_alloc(3http)], xref:nng_http_server_add_handler.3http.adoc[nng_http_server_add_handler(3http)], -xref:nng_http_get_method.3http.adoc[nng_http_get_method(3http)], -xref:nng.7.adoc[nng(7)] +xref:nng_http_get_method.3http.adoc[nng_http_get_method(3http)] diff --git a/docs/man/nng_http_set_method.3http.adoc b/docs/man/nng_http_set_method.3http.adoc deleted file mode 100644 index 893dc8755..000000000 --- a/docs/man/nng_http_set_method.3http.adoc +++ /dev/null @@ -1,44 +0,0 @@ -= nng_http_set_method(3http) -// -// Copyright 2025 Staysail Systems, Inc. -// Copyright 2018 Capitar IT Group BV -// -// This document is supplied under the terms of the MIT License, a -// copy of which should be located in the distribution where this -// file was obtained (LICENSE.txt). A copy of the license may also be -// found online at https://opensource.org/licenses/MIT. -// - -== NAME - -nng_http_set_method - set HTTP request method - -== SYNOPSIS - -[source, c] ----- -#include -#include - -void nng_http_set_method(nng_http *conn, const char *method); ----- - -== DESCRIPTION - -The `nng_http_set_method()` sets the HTTP method associated with -the connection _conn_ to _method_. The _method_ must be a string, -such as "GET" or "POST". - -The default value method for newly allocated requests is "GET". - -If the method is longer than 32 bytes, it may be silently truncated. -(There are no methods defined that are this long.) - -The value _method_ is copied, so the caller may dispose of it after -the call completes. - -== SEE ALSO - -[.text-left] -xref:nng_http_get_method.3http.adoc[nng_http_get_method(3http)], -xref:nng.7.adoc[nng(7)] diff --git a/docs/man/nng_http_set_reason.3http.adoc b/docs/man/nng_http_set_reason.3http.adoc deleted file mode 100644 index 62fb45611..000000000 --- a/docs/man/nng_http_set_reason.3http.adoc +++ /dev/null @@ -1,54 +0,0 @@ -= nng_http_set_reason(3http) -// -// Copyright 2025 Staysail Systems, Inc. -// Copyright 2018 Capitar IT Group BV -// -// This document is supplied under the terms of the MIT License, a -// copy of which should be located in the distribution where this -// file was obtained (LICENSE.txt). A copy of the license may also be -// found online at https://opensource.org/licenses/MIT. -// - -== NAME - -nng_http_set_reason - set HTTP response reason - -== SYNOPSIS - -[source, c] ----- -#include -#include - -int nng_http_set_reason(nng_http *conn, const char *reason); ----- - -== DESCRIPTION - -The `nng_http_set_reason()` sets the human readable reason -associated with the response for _conn_ to _reason_. - -If the value of _reason_ is `NULL` (the default), then a default reason -phrase is supplied based upon the value of the status code (see -xref:nng_http_set_status.3http.adoc[`nng_http_set_status()`]). - -TIP: The _reason_ is never parsed automatically, but it can be a hint for humans - to help them understand the nature of any erroneous result. - -A local copy of the _reason_ is made in the response _res_. - -== RETURN VALUES - -This function returns 0 on success, and non-zero otherwise. - -== ERRORS - -[horizontal] -`NNG_ENOMEM`:: Insufficient memory to perform the operation. -`NNG_ENOTSUP`:: No support for HTTP in the library. - -== SEE ALSO - -[.text-left] -xref:nng_http_get_reason.3http.adoc[nng_http_get_reason(3http)], -xref:nng_http_set_status.3http.adoc[nng_http_set_status(3http)] diff --git a/docs/ref/migrate/nng1.md b/docs/ref/migrate/nng1.md index cc3e76b98..9e35465b9 100644 --- a/docs/ref/migrate/nng1.md +++ b/docs/ref/migrate/nng1.md @@ -349,7 +349,6 @@ They may silently truncate data. - [`nng_http_handler_set_host`] - [`nng_http_handler_set_method`] - [`nng_http_handler_set_tree`] -- [`nng_http_handler_set_tree_exclusive`] 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. diff --git a/include/nng/http.h b/include/nng/http.h index ec29e56ef..6a57cfe6e 100644 --- a/include/nng/http.h +++ b/include/nng/http.h @@ -298,14 +298,6 @@ NNG_DECL void nng_http_handler_collect_body(nng_http_handler *, bool, size_t); // called for an exact path match. NNG_DECL void nng_http_handler_set_tree(nng_http_handler *); -// nng_http_handler_set_tree_exclusive indicates that the handler is being -// registered for a heirarchical tree *exclusively*, rather than just a single -// path, so it will be called for all child paths supplied. By default the -// handler is only called for an exact path match. Exclusive means that any -// other handler on a conflicting path will induce an address conflict error -// when added to a server. -NNG_DECL void nng_http_handler_set_tree_exclusive(nng_http_handler *); - // nng_http_handler_set_data is used to store additional data, along with // a possible clean up routine. (The clean up is a custom de-allocator and // will be called with the supplied data as an argument, when the handler diff --git a/src/supplemental/http/http_api.h b/src/supplemental/http/http_api.h index b2b07b992..ade6cf069 100644 --- a/src/supplemental/http/http_api.h +++ b/src/supplemental/http/http_api.h @@ -275,13 +275,6 @@ extern void nni_http_handler_collect_body(nni_http_handler *, bool, size_t); // will probably need to inspect the URL of the request. extern void nni_http_handler_set_tree(nni_http_handler *); -// nni_http_handler_set_tree_exclusive marks the handler as servicing the -// entire tree (e.g. a directory) exclusively, rather than just a leaf node. -// When servicing a tree exclusively, other handlers sharing parts of the uri -// will induce an address conflict when adding them to a server. The handler -// will probably need to inspect the URL of the request. -extern void nni_http_handler_set_tree_exclusive(nni_http_handler *); - // nni_http_handler_set_host limits the handler to only being called for // the given Host: field. This can be used to set up multiple virtual // hosts. Note that host names must match exactly. If NULL or an empty diff --git a/src/supplemental/http/http_msg.c b/src/supplemental/http/http_msg.c index 988bb37e6..fbe73e4cc 100644 --- a/src/supplemental/http/http_msg.c +++ b/src/supplemental/http/http_msg.c @@ -83,39 +83,6 @@ nni_http_res_reset(nni_http_res *res) res->code = 0; } -static int -http_del_header(nni_list *hdrs, const char *key) -{ - http_header *h; - NNI_LIST_FOREACH (hdrs, h) { - if (nni_strcasecmp(key, h->name) == 0) { - nni_http_free_header(h); - return (0); - } - } - return (NNG_ENOENT); -} - -int -nni_http_req_del_header(nni_http_req *req, const char *key) -{ - int rv = NNG_ENOENT; - while (http_del_header(&req->data.hdrs, key) == 0) { - rv = 0; - } - return (rv); -} - -int -nni_http_res_del_header(nni_http_res *res, const char *key) -{ - int rv = NNG_ENOENT; - while (http_del_header(&res->data.hdrs, key) == 0) { - rv = 0; - } - return (rv); -} - // http_entity_set_data sets the entity, but does not update the // content-length header. static void diff --git a/src/supplemental/http/http_public.c b/src/supplemental/http/http_public.c index ef0008022..5b39ba02b 100644 --- a/src/supplemental/http/http_public.c +++ b/src/supplemental/http/http_public.c @@ -433,16 +433,6 @@ nng_http_handler_set_tree(nng_http_handler *h) #endif } -void -nng_http_handler_set_tree_exclusive(nng_http_handler *h) -{ -#ifdef NNG_SUPP_HTTP - nni_http_handler_set_tree_exclusive(h); -#else - NNI_ARG_UNUSED(h); -#endif -} - void nng_http_handler_set_data(nng_http_handler *h, void *dat, void (*dtor)(void *)) { diff --git a/src/supplemental/http/http_server.c b/src/supplemental/http/http_server.c index 7fbd7a56d..76ac075d9 100644 --- a/src/supplemental/http/http_server.c +++ b/src/supplemental/http/http_server.c @@ -36,7 +36,6 @@ struct nng_http_handler { nng_sockaddr host_addr; bool host_ip; bool tree; - bool tree_exclusive; nni_atomic_int ref; nni_atomic_bool busy; size_t maxbody; @@ -121,13 +120,12 @@ nni_http_handler_init( } (void) snprintf(h->uri, sizeof(h->uri), "%s", uri); NNI_LIST_NODE_INIT(&h->node); - h->cb = cb; - h->data = NULL; - h->dtor = NULL; - h->tree = false; - h->tree_exclusive = false; - h->maxbody = 1024 * 1024; // Up to 1MB of body - h->getbody = true; + h->cb = cb; + h->data = NULL; + h->dtor = NULL; + h->tree = false; + h->maxbody = 1024 * 1024; // Up to 1MB of body + h->getbody = true; (void) strcpy(h->method, "GET"); (void) strcpy(h->host, ""); *hp = h; @@ -182,16 +180,7 @@ void nni_http_handler_set_tree(nni_http_handler *h) { NNI_ASSERT(!nni_atomic_get_bool(&h->busy)); - h->tree = true; - h->tree_exclusive = false; -} - -void -nni_http_handler_set_tree_exclusive(nni_http_handler *h) -{ - NNI_ASSERT(!nni_atomic_get_bool(&h->busy)); - h->tree = true; - h->tree_exclusive = true; + h->tree = true; } void @@ -1095,18 +1084,13 @@ int nni_http_server_add_handler(nni_http_server *s, nni_http_handler *h) { nni_http_handler *h2; - size_t len; // Must have a legal method (and not one that is HEAD), path, // and handler. (The reason HEAD is verboten is that we supply // it automatically as part of GET support.) - if ((((len = strlen(h->uri)) > 0) && (h->uri[0] != '/')) || - (h->cb == NULL)) { + if (((h->uri[0] != 0) && (h->uri[0] != '/')) || (h->cb == NULL)) { return (NNG_EINVAL); } - while ((len > 0) && (h->uri[len - 1] == '/')) { - len--; // ignore trailing '/' (this collapses them) - } nni_mtx_lock(&s->mtx); // General rule for finding a conflict is that if either uri @@ -1114,73 +1098,27 @@ nni_http_server_add_handler(nni_http_server *s, nni_http_handler *h) // collision. (But only if the methods match, and the host // matches.) Note that a wild card host matches both. NNI_LIST_FOREACH (&s->handlers, h2) { - size_t len2; - if ((h2->host[0] != 0) && (h->host[0] != 0) && - (nni_strcasecmp(h2->host, h->host) != 0)) { + if (nni_strcasecmp(h2->host, h->host) != 0) { // Hosts don't match, so we are safe. continue; } - if (((h2->host[0] == 0) && (h->host[0] != 0)) || - ((h->host[0] == 0) && (h2->host[0] != 0))) { - continue; // Host specified for just one. - } - if (((h->method[0] == 0) && (h2->method[0] != 0)) || - ((h2->method[0] == 0) && (h->method[0] != 0))) { - continue; // Method specified for just one. - } - if ((h->method[0] != 0) && - (strcmp(h2->method, h->method) != 0)) { + if (strcmp(h2->method, h->method) != 0) { // Different methods, so again we are fine. continue; } - len2 = strlen(h2->uri); - - while ((len2 > 0) && (h2->uri[len2 - 1] == '/')) { - len2--; // ignore trailing '/' + if (strcmp(h->uri, h2->uri) != 0) { + continue; // not a duplicate } - if ((h2->tree && h2->tree_exclusive) || - (h->tree && h->tree_exclusive)) { - // Old behavior - if (strncmp(h->uri, h2->uri, - len > len2 ? len2 : len) != 0) { - continue; // prefixes don't match. - } - - if (len2 > len) { - if ((h2->uri[len] == '/') && (h->tree)) { - nni_mtx_unlock(&s->mtx); - return (NNG_EADDRINUSE); - } - } else if (len > len2) { - if ((h->uri[len2] == '/') && (h2->tree)) { - nni_mtx_unlock(&s->mtx); - return (NNG_EADDRINUSE); - } - } else { - nni_mtx_unlock(&s->mtx); - return (NNG_EADDRINUSE); - } - } else { - if (len != len2) { - continue; // length mismatch - } - - if (strcmp(h->uri, h2->uri) != 0) { - continue; // not a duplicate - } - - nni_mtx_unlock(&s->mtx); - return (NNG_EADDRINUSE); - } + nni_mtx_unlock(&s->mtx); + return (NNG_EADDRINUSE); } // Maintain list of handlers in longest uri first order NNI_LIST_FOREACH (&s->handlers, h2) { - size_t len2 = strlen(h2->uri); - if (len > len2) { + if (strcmp(h->uri, h2->uri) > 0) { nni_list_insert_before(&s->handlers, h, h2); break; } @@ -1532,8 +1470,8 @@ nni_http_handler_init_directory( if ((hf = NNI_ALLOC_STRUCT(hf)) == NULL) { return (NNG_ENOMEM); } - if (((hf->path = nni_strdup(path)) == NULL) || - ((hf->base = nni_strdup(uri)) == NULL)) { + if (((hf->path = nng_strdup(path)) == NULL) || + ((hf->base = nng_strdup(uri)) == NULL)) { http_file_free(hf); return (NNG_ENOMEM); } @@ -1543,9 +1481,9 @@ nni_http_handler_init_directory( return (rv); } // We don't permit a body for getting a file. - nni_http_handler_collect_body(h, true, 0); - nni_http_handler_set_tree_exclusive(h); - nni_http_handler_set_data(h, hf, http_file_free); + nng_http_handler_set_tree(h); + nng_http_handler_collect_body(h, true, 0); + nng_http_handler_set_data(h, hf, http_file_free); *hpp = h; return (0);