diff options
| author | Robert Bielik <robert.bielik@dirac.com> | 2020-01-19 03:29:52 +0100 |
|---|---|---|
| committer | Garrett D'Amore <garrett@damore.org> | 2020-01-18 18:29:52 -0800 |
| commit | 10133ca9b5439e67b287703739e23e7d82fb76c4 (patch) | |
| tree | 19d9b46c3dc3d646c866bd4b397263016c43beff | |
| parent | 132acf7ceb59aa9567a7d254686dd612a3a79dfb (diff) | |
| download | nng-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.c | 7 | ||||
| -rw-r--r-- | tests/httpserver.c | 203 |
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; |
