aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Bielik <robert.bielik@dirac.com>2020-01-19 03:29:52 +0100
committerGarrett D'Amore <garrett@damore.org>2020-01-18 18:29:52 -0800
commit10133ca9b5439e67b287703739e23e7d82fb76c4 (patch)
tree19d9b46c3dc3d646c866bd4b397263016c43beff
parent132acf7ceb59aa9567a7d254686dd612a3a79dfb (diff)
downloadnng-10133ca9b5439e67b287703739e23e7d82fb76c4.tar.gz
nng-10133ca9b5439e67b287703739e23e7d82fb76c4.tar.bz2
nng-10133ca9b5439e67b287703739e23e7d82fb76c4.zip
Fix HTTP server root URI handling (#1140)
- Fixes #751
-rw-r--r--src/supplemental/http/http_server.c7
-rw-r--r--tests/httpserver.c203
2 files changed, 207 insertions, 3 deletions
diff --git a/src/supplemental/http/http_server.c b/src/supplemental/http/http_server.c
index 9a4ff2af..da12c20d 100644
--- a/src/supplemental/http/http_server.c
+++ b/src/supplemental/http/http_server.c
@@ -676,7 +676,7 @@ http_sconn_cbdone(void *arg)
// Get the handler. It may be set regardless of success or
// failure. Clear it, and drop our reference, since we're
// done with the handler for now.
- h = nni_aio_get_data(aio, 1);
+ h = nni_aio_get_data(aio, 1);
nni_aio_set_data(aio, 1, NULL);
if (h != NULL) {
@@ -1402,8 +1402,9 @@ http_handle_dir(nni_aio *aio)
char * pn;
len = strlen(base);
- if ((strncmp(uri, base, len) != 0) ||
- ((uri[len] != 0) && (uri[len] != '/'))) {
+ if (base[1] != '\0' && // Allows "/" as base
+ ((strncmp(uri, base, len) != 0) ||
+ ((uri[len] != 0) && (uri[len] != '/')))) {
// This should never happen!
nni_aio_finish_error(aio, NNG_EINVAL);
return;
diff --git a/tests/httpserver.c b/tests/httpserver.c
index a69889a5..9b7ed0e3 100644
--- a/tests/httpserver.c
+++ b/tests/httpserver.c
@@ -289,6 +289,209 @@ TestMain("HTTP Server", {
});
});
});
+
+ Convey("Directory serving works (root)", {
+ char urlstr[32];
+ nng_url *url;
+ char * tmpdir;
+ char * workdir;
+ char * file1;
+ char * file2;
+ char * file3;
+ char * subdir1;
+ char * subdir2;
+
+ trantest_next_address(urlstr, "http://127.0.0.1:%u");
+ So(nng_url_parse(&url, urlstr) == 0);
+ So(nng_http_server_hold(&s, url) == 0);
+ So((tmpdir = nni_plat_temp_dir()) != NULL);
+ So((workdir = nni_file_join(tmpdir, "httptest")) != NULL);
+ So((subdir1 = nni_file_join(workdir, "subdir1")) != NULL);
+ So((subdir2 = nni_file_join(workdir, "subdir2")) != NULL);
+ So((file1 = nni_file_join(subdir1, "index.html")) != NULL);
+ So((file2 = nni_file_join(workdir, "file.txt")) != NULL);
+ So((file3 = nni_file_join(subdir2, "index.htm")) != NULL);
+
+ So(nni_file_put(file1, doc1, strlen(doc1)) == 0);
+ So(nni_file_put(file2, doc2, strlen(doc2)) == 0);
+ So(nni_file_put(file3, doc3, strlen(doc3)) == 0);
+
+ Reset({
+ nng_http_server_release(s);
+ free(tmpdir);
+ nni_file_delete(file1);
+ nni_file_delete(file2);
+ nni_file_delete(file3);
+ nni_file_delete(subdir1);
+ nni_file_delete(subdir2);
+ nni_file_delete(workdir);
+ free(workdir);
+ free(file1);
+ free(file2);
+ free(file3);
+ free(subdir1);
+ free(subdir2);
+ nng_url_free(url);
+ });
+
+ So(nng_http_handler_alloc_directory(&h, "/", workdir) == 0);
+ So(nng_http_server_add_handler(s, h) == 0);
+ So(nng_http_server_start(s) == 0);
+ nng_msleep(100);
+
+ Convey("Index.html works", {
+ char fullurl[256];
+ void * data;
+ size_t size;
+ uint16_t stat;
+ char * ctype;
+
+ snprintf(fullurl, sizeof(fullurl),
+ "%s/subdir1/index.html", urlstr);
+ So(httpget(fullurl, &data, &size, &stat, &ctype) == 0);
+ So(stat == NNG_HTTP_STATUS_OK);
+ So(size == strlen(doc1));
+ So(memcmp(data, doc1, size) == 0);
+ So(strcmp(ctype, "text/html") == 0);
+ nng_strfree(ctype);
+ nng_free(data, size);
+ });
+
+ Convey("Index.htm works", {
+ char fullurl[256];
+ void * data;
+ size_t size;
+ uint16_t stat;
+ char * ctype;
+
+ snprintf(
+ fullurl, sizeof(fullurl), "%s/subdir2", urlstr);
+ So(httpget(fullurl, &data, &size, &stat, &ctype) == 0);
+ So(stat == NNG_HTTP_STATUS_OK);
+ So(size == strlen(doc3));
+ So(memcmp(data, doc3, size) == 0);
+ So(strcmp(ctype, "text/html") == 0);
+ nni_strfree(ctype);
+ nng_free(data, size);
+ });
+
+ Convey("Named file works", {
+ char fullurl[256];
+ void * data;
+ size_t size;
+ uint16_t stat;
+ char * ctype;
+
+ snprintf(
+ fullurl, sizeof(fullurl), "%s/file.txt", urlstr);
+ So(httpget(fullurl, &data, &size, &stat, &ctype) == 0);
+ So(stat == NNG_HTTP_STATUS_OK);
+ So(size == strlen(doc2));
+ So(memcmp(data, doc2, size) == 0);
+ So(strcmp(ctype, "text/plain") == 0);
+ nni_strfree(ctype);
+ nng_free(data, size);
+ });
+
+ Convey("Missing index gives 404", {
+ char fullurl[256];
+ void * data;
+ size_t size;
+ uint16_t stat;
+ char * ctype;
+
+ snprintf(fullurl, sizeof(fullurl), "%s/", urlstr);
+ So(httpget(fullurl, &data, &size, &stat, &ctype) == 0);
+ So(stat == NNG_HTTP_STATUS_NOT_FOUND);
+ nng_strfree(ctype);
+ nng_free(data, size);
+ });
+
+ Convey("Custom error page works", {
+ char fullurl[256];
+ void * data;
+ size_t size;
+ uint16_t stat;
+ char * ctype;
+
+ So(nng_http_server_set_error_page(s, 404, doc4) == 0);
+ snprintf(fullurl, sizeof(fullurl), "%s/", urlstr);
+ So(httpget(fullurl, &data, &size, &stat, &ctype) == 0);
+ So(stat == NNG_HTTP_STATUS_NOT_FOUND);
+ So(size == strlen(doc4));
+ So(memcmp(data, doc4, size) == 0);
+ nng_strfree(ctype);
+ nng_free(data, size);
+ });
+
+ Convey("Bad method gives 405", {
+ char fullurl[256];
+ void * data;
+ size_t size;
+ nng_http_req *req;
+ nng_http_res *res;
+ nng_url * curl;
+
+ So(nng_http_res_alloc(&res) == 0);
+ snprintf(fullurl, sizeof(fullurl), "%s/", urlstr);
+ So(nng_url_parse(&curl, fullurl) == 0);
+ So(nng_http_req_alloc(&req, curl) == 0);
+ So(nng_http_req_set_method(req, "POST") == 0);
+
+ So(httpdo(curl, req, res, &data, &size) == 0);
+ So(nng_http_res_get_status(res) ==
+ NNG_HTTP_STATUS_METHOD_NOT_ALLOWED);
+ nng_http_req_free(req);
+ nng_http_res_free(res);
+ nng_url_free(curl);
+ nng_free(data, size);
+ });
+ Convey("Version 0.9 gives 505", {
+ char fullurl[256];
+ void * data;
+ size_t size;
+ nng_http_req *req;
+ nng_http_res *res;
+ nng_url * curl;
+
+ So(nng_http_res_alloc(&res) == 0);
+ snprintf(fullurl, sizeof(fullurl), "%s/", urlstr);
+ So(nng_url_parse(&curl, fullurl) == 0);
+ So(nng_http_req_alloc(&req, curl) == 0);
+ So(nng_http_req_set_version(req, "HTTP/0.9") == 0);
+
+ So(httpdo(curl, req, res, &data, &size) == 0);
+ So(nng_http_res_get_status(res) ==
+ NNG_HTTP_STATUS_HTTP_VERSION_NOT_SUPP);
+ nng_http_req_free(req);
+ nng_http_res_free(res);
+ nng_url_free(curl);
+ nng_free(data, size);
+ });
+ Convey("Missing Host gives 400", {
+ char fullurl[256];
+ void * data;
+ size_t size;
+ nng_http_req *req;
+ nng_http_res *res;
+ nng_url * curl;
+
+ So(nng_http_res_alloc(&res) == 0);
+ snprintf(fullurl, sizeof(fullurl), "%s/", urlstr);
+ So(nng_url_parse(&curl, fullurl) == 0);
+ So(nng_http_req_alloc(&req, curl) == 0);
+ So(nng_http_req_del_header(req, "Host") == 0);
+
+ So(httpdo(curl, req, res, &data, &size) == 0);
+ So(nng_http_res_get_status(res) ==
+ NNG_HTTP_STATUS_BAD_REQUEST);
+ nng_http_req_free(req);
+ nng_http_res_free(res);
+ nng_url_free(curl);
+ nng_free(data, size);
+ });
+ });
+
Convey("Directory serving works", {
char urlstr[32];
nng_url *url;