aboutsummaryrefslogtreecommitdiff
path: root/src/supplemental/http
diff options
context:
space:
mode:
authorGarrett D'Amore <garrett@damore.org>2025-01-12 09:01:33 -0800
committerGarrett D'Amore <garrett@damore.org>2025-01-12 09:24:29 -0800
commit169166a0ef4fad56860c40ba2eda23f27b8a4cb1 (patch)
tree20f9ab16bb077af353148b108eb884d1a9e9fa1d /src/supplemental/http
parent4f445061dc9dbc1e437ff04eff6f39f021bd5bec (diff)
downloadnng-169166a0ef4fad56860c40ba2eda23f27b8a4cb1.tar.gz
nng-169166a0ef4fad56860c40ba2eda23f27b8a4cb1.tar.bz2
nng-169166a0ef4fad56860c40ba2eda23f27b8a4cb1.zip
http: use common canonify at request parse time
Diffstat (limited to 'src/supplemental/http')
-rw-r--r--src/supplemental/http/http_conn.c2
-rw-r--r--src/supplemental/http/http_msg.c4
-rw-r--r--src/supplemental/http/http_server.c107
3 files changed, 17 insertions, 96 deletions
diff --git a/src/supplemental/http/http_conn.c b/src/supplemental/http/http_conn.c
index 65c240f5..e143d9b3 100644
--- a/src/supplemental/http/http_conn.c
+++ b/src/supplemental/http/http_conn.c
@@ -1145,7 +1145,7 @@ nni_http_set_content_type(nng_http *conn, const char *ctype)
const char *
nni_http_get_uri(nng_http *conn)
{
- return (conn->uri);
+ return ((conn->uri && conn->uri[0]) ? conn->uri : "/");
}
int
diff --git a/src/supplemental/http/http_msg.c b/src/supplemental/http/http_msg.c
index 8c62fb5f..3c4ce491 100644
--- a/src/supplemental/http/http_msg.c
+++ b/src/supplemental/http/http_msg.c
@@ -16,6 +16,7 @@
#include "core/list.h"
#include "core/nng_impl.h"
+#include "core/url.h"
#include "http_api.h"
#include "http_msg.h"
#include "nng/http.h"
@@ -231,7 +232,8 @@ http_req_parse_line(nng_http *conn, void *line)
version++;
nni_http_set_method(conn, method);
- if (((rv = nni_http_set_uri(conn, uri, NULL)) != 0) ||
+ if (((rv = nni_url_canonify_uri(uri)) != 0) ||
+ ((rv = nni_http_set_uri(conn, uri, NULL)) != 0) ||
((rv = nni_http_set_version(conn, version)) != 0)) {
return (rv);
}
diff --git a/src/supplemental/http/http_server.c b/src/supplemental/http/http_server.c
index bec0c01a..096d985c 100644
--- a/src/supplemental/http/http_server.c
+++ b/src/supplemental/http/http_server.c
@@ -332,83 +332,6 @@ http_sconn_txdone(void *arg)
}
}
-static char
-http_hexval(char c)
-{
- if ((c >= '0') && (c <= '9')) {
- return (c - '0');
- }
- if ((c >= 'a') && (c <= 'f')) {
- return ((c - 'a') + 10);
- }
- if ((c >= 'A') && (c <= 'F')) {
- return ((c - 'A') + 10);
- }
- return (0);
-}
-
-// XXX: REPLACE THIS WITH CODE USING THE URL FRAMEWORK.
-static char *
-http_uri_canonify(char *path)
-{
- char *tmp;
- char *dst;
-
- // Chomp off query string.
- if ((tmp = strchr(path, '?')) != NULL) {
- *tmp = '\0';
- }
- // If the URI was absolute, make it relative.
- if ((nni_strncasecmp(path, "http://", strlen("http://")) == 0) ||
- (nni_strncasecmp(path, "https://", strlen("https://")) == 0)) {
- // Skip past the ://
- path = strchr(path, ':');
- path += 3;
-
- // scan for the end of the host, distinguished by a /
- // path delimiter. There might not be one, in which
- // case the whole thing is the host and we assume the
- // path is just /.
- if ((path = strchr(path, '/')) == NULL) {
- return ("/");
- }
- }
-
- // Now we have to unescape things. Unescaping is a shrinking
- // operation (strictly), so this is safe. This is just URL
- // decode. Note that paths with an embedded NUL are going to be
- // treated as though truncated. Don't be that guy that sends
- // %00 in a URL.
- //
- // XXX: Normalizer needs to leave % encoded stuff in there if
- // the characters to which they refer are reserved. See RFC 3986
- // section 6.2.2.
- tmp = path;
- dst = path;
- while (*tmp != '\0') {
- char c;
- if ((c = *tmp) != '%') {
- *dst++ = c;
- tmp++;
- continue;
- }
- if (isxdigit(tmp[1]) && isxdigit(tmp[2])) {
- c = http_hexval(tmp[1]);
- c *= 16;
- c += http_hexval(tmp[2]);
- *dst++ = c;
- tmp += 3;
- } else {
- // garbage in, garbage out
- *dst++ = c;
- tmp++;
- }
- }
- *dst = '\0';
-
- return ((strlen(path) != 0) ? path : "/");
-}
-
static void
http_sconn_error(http_sconn *sc, uint16_t err)
{
@@ -509,9 +432,7 @@ http_sconn_rxdone(void *arg)
nni_http_handler *head = NULL;
const char *val;
nni_http_req *req = nni_http_conn_req(sc->conn);
- char *uri;
- size_t urisz;
- char *path;
+ const char *uri;
bool badmeth = false;
bool needhost = false;
const char *host;
@@ -563,6 +484,15 @@ http_sconn_rxdone(void *arg)
needhost = true;
}
+ // NB: The URI will already have been canonified by the REQ parser
+ uri = nni_http_get_uri(sc->conn);
+ if (uri[0] != '/') {
+ // We do not support authority form or asterisk form at present
+ sc->close = true;
+ http_sconn_error(sc, NNG_HTTP_STATUS_BAD_REQUEST);
+ return;
+ }
+
// If the connection was 1.0, or a connection: close was
// requested, then mark this close on our end.
if ((val = nni_http_get_header(sc->conn, "Connection")) != NULL) {
@@ -588,20 +518,10 @@ http_sconn_rxdone(void *arg)
}
}
- val = nni_http_get_uri(sc->conn);
- urisz = strlen(val) + 1;
- if ((uri = nni_alloc(urisz)) == NULL) {
- http_sconn_close(sc); // out of memory
- return;
- }
- strncpy(uri, val, urisz);
- path = http_uri_canonify(uri);
-
host = nni_http_get_header(sc->conn, "Host");
if ((host == NULL) && (needhost)) {
// Per RFC 2616 14.23 we have to send 400 status here.
http_sconn_error(sc, NNG_HTTP_STATUS_BAD_REQUEST);
- nni_free(uri, urisz);
return;
}
@@ -614,14 +534,14 @@ http_sconn_rxdone(void *arg)
}
len = strlen(h->uri);
- if (strncmp(path, h->uri, len) != 0) {
+ if (strncmp(uri, h->uri, len) != 0) {
continue;
}
- switch (path[len]) {
+ switch (uri[len]) {
case '\0':
break;
case '/':
- if ((path[len + 1] != '\0') && (!h->tree)) {
+ if ((uri[len + 1] != '\0') && (!h->tree)) {
// Trailing component and not a directory.
continue;
}
@@ -652,7 +572,6 @@ http_sconn_rxdone(void *arg)
if ((h == NULL) && (head != NULL)) {
h = head;
}
- nni_free(uri, urisz);
if (h == NULL) {
nni_mtx_unlock(&s->mtx);
if (badmeth) {