aboutsummaryrefslogtreecommitdiff
path: root/tests/httpserver.c
diff options
context:
space:
mode:
authorGarrett D'Amore <garrett@damore.org>2018-01-19 17:13:40 -0800
committerGarrett D'Amore <garrett@damore.org>2018-01-20 15:03:12 -0800
commit7dbc9ae4fef34c6fd836b939bd559e54b8008b72 (patch)
tree54660fef8a4a597c067a18953a295f1cfdb96cf0 /tests/httpserver.c
parent338706c2420ce3e51b546a6ba2574e10346a511b (diff)
downloadnng-7dbc9ae4fef34c6fd836b939bd559e54b8008b72.tar.gz
nng-7dbc9ae4fef34c6fd836b939bd559e54b8008b72.tar.bz2
nng-7dbc9ae4fef34c6fd836b939bd559e54b8008b72.zip
fixes #216 HTTP server side API refactoring, directory serving support
This changes the backend (internal) HTTP API to provide a much more sensible handler scheme, where the handlers are opaque objects and we can allocate a handler for different types of tasks. We've also added support serving up directories of static content, and added code to validate that the directory serving is working as intended. This is a key enabling step towards the public API.
Diffstat (limited to 'tests/httpserver.c')
-rw-r--r--tests/httpserver.c260
1 files changed, 239 insertions, 21 deletions
diff --git a/tests/httpserver.c b/tests/httpserver.c
index 147d0532..0d3f3710 100644
--- a/tests/httpserver.c
+++ b/tests/httpserver.c
@@ -18,11 +18,10 @@
// Basic HTTP server tests.
#include "core/nng_impl.h"
#include "supplemental/http/http.h"
-#include "supplemental/sha1/sha1.h"
-const uint8_t utf8_sha1sum[20] = { 0x54, 0xf3, 0xb8, 0xbb, 0xfe, 0xda, 0x6f,
- 0xb4, 0x96, 0xdd, 0xc9, 0x8b, 0x8c, 0x41, 0xf4, 0xfe, 0xe5, 0xa9, 0x7d,
- 0xa9 };
+const char *doc1 = "<html><body>Someone <b>is</b> home!</body</html>";
+const char *doc2 = "This is a text file.";
+const char *doc3 = "<html><body>This is doc number 3.</body></html>";
void
cleanup(void)
@@ -30,29 +29,127 @@ cleanup(void)
nng_fini();
}
+static int
+httpget(const char *addr, void **datap, size_t *sizep, uint16_t *statp,
+ char **ctypep)
+{
+ int rv;
+ nni_aio * aio = NULL;
+ nni_http_client *cli = NULL;
+ nni_http * h = NULL;
+ nni_http_req * req = NULL;
+ nni_http_res * res = NULL;
+ nni_url * url = NULL;
+ size_t clen = 0;
+ void * data = NULL;
+ char * ctype = NULL;
+ const char * ptr;
+
+ if (((rv = nni_url_parse(&url, addr)) != 0) ||
+ ((rv = nni_aio_init(&aio, NULL, NULL)) != 0) ||
+ ((rv = nni_http_req_init(&req)) != 0) ||
+ ((rv = nni_http_res_init(&res)) != 0) ||
+ ((rv = nni_http_client_init(&cli, addr)) != 0)) {
+ goto fail;
+ }
+ nni_http_client_connect(cli, aio);
+ nni_aio_wait(aio);
+ if ((rv = nni_aio_result(aio)) != 0) {
+ goto fail;
+ }
+
+ h = nni_aio_get_output(aio, 0);
+ if (((rv = nni_http_req_set_method(req, "GET")) != 0) ||
+ ((rv = nni_http_req_set_version(req, "HTTP/1.1")) != 0) ||
+ ((rv = nni_http_req_set_uri(req, url->u_path)) != 0) ||
+ ((rv = nni_http_req_set_header(req, "Host", url->u_host)) != 0)) {
+ goto fail;
+ }
+ nni_http_write_req(h, req, aio);
+ nni_aio_wait(aio);
+ if ((rv = nni_aio_result(aio)) != 0) {
+ goto fail;
+ }
+ nni_http_read_res(h, res, aio);
+ nni_aio_wait(aio);
+ if ((rv = nni_aio_result(aio)) != 0) {
+ goto fail;
+ }
+
+ *statp = nni_http_res_get_status(res);
+ clen = 0;
+ if ((*statp == NNI_HTTP_STATUS_OK) &&
+ ((ptr = nni_http_res_get_header(res, "Content-Length")) != NULL)) {
+ clen = atoi(ptr);
+ }
+
+ if (clen > 0) {
+ data = nni_alloc(clen);
+ aio->a_niov = 1;
+ aio->a_iov[0].iov_len = clen;
+ aio->a_iov[0].iov_buf = data;
+ nni_http_read_full(h, aio);
+ nni_aio_wait(aio);
+ if ((rv = nni_aio_result(aio)) != 0) {
+ goto fail;
+ }
+ if ((ptr = nni_http_res_get_header(res, "Content-Type")) !=
+ NULL) {
+ ctype = nni_strdup(ptr);
+ }
+ }
+
+ *datap = data;
+ *sizep = clen;
+ *ctypep = ctype;
+
+fail:
+ if (rv != 0) {
+ if (data != NULL) {
+ nni_free(data, clen);
+ }
+ nni_strfree(ctype);
+ }
+ if (url != NULL) {
+ nni_url_free(url);
+ }
+ if (aio != NULL) {
+ nni_aio_fini(aio);
+ }
+ if (req != NULL) {
+ nni_http_req_fini(req);
+ }
+ if (res != NULL) {
+ nni_http_res_fini(res);
+ }
+ if (h != NULL) {
+ nni_http_fini(h);
+ }
+ if (cli != NULL) {
+ nni_http_client_fini(cli);
+ }
+
+ return (rv);
+}
+
TestMain("HTTP Client", {
- nni_http_server *s;
+ nni_http_server * s;
+ nni_http_handler *h;
nni_init();
atexit(cleanup);
Convey("We can start an HTTP server", {
- nng_sockaddr sa;
- nni_aio * aio;
- char portbuf[16];
- char url[32];
- char *doc = "<html><body>Someone <b>is</b> home!</body</html>";
+ nni_aio *aio;
+ char portbuf[16];
+ char url[32];
trantest_next_address(portbuf, "%u");
snprintf(url, sizeof(url), "http://127.0.0.1:%s", portbuf);
So(nni_aio_init(&aio, NULL, NULL) == 0);
- aio->a_addr = &sa;
- nni_plat_tcp_resolv("127.0.0.1", portbuf, NNG_AF_INET, 0, aio);
- nni_aio_wait(aio);
- So(nni_aio_result(aio) == 0);
So(nni_http_server_init(&s, url) == 0);
@@ -61,8 +158,9 @@ TestMain("HTTP Client", {
nni_http_server_fini(s);
});
- So(nni_http_server_add_static(s, NULL, "text/html",
- "/home.html", doc, strlen(doc)) == 0);
+ So(nni_http_handler_init_static(&h, "/home.html", doc1,
+ strlen(doc1), "text/html") == 0);
+ So(nni_http_server_add_handler(s, h) == 0);
So(nni_http_server_start(s) == 0);
Convey("We can connect a client to it", {
@@ -132,18 +230,138 @@ TestMain("HTTP Client", {
ptr = nni_http_res_get_header(
res, "Content-Length");
So(ptr != NULL);
- So(atoi(ptr) == strlen(doc));
+ So(atoi(ptr) == strlen(doc1));
aio->a_niov = 1;
- aio->a_iov[0].iov_len = strlen(doc);
+ aio->a_iov[0].iov_len = strlen(doc1);
aio->a_iov[0].iov_buf = (void *) chunk;
nni_http_read_full(h, aio);
nni_aio_wait(aio);
So(nni_aio_result(aio) == 0);
- So(nni_aio_count(aio) == strlen(doc));
- So(memcmp(chunk, doc, strlen(doc)) == 0);
+ So(nni_aio_count(aio) == strlen(doc1));
+ So(memcmp(chunk, doc1, strlen(doc1)) == 0);
});
});
});
-});
+ Convey("Directory serving works", {
+ nni_aio *aio;
+ char portbuf[16];
+ char url[32];
+ char * tmpdir;
+ char * workdir;
+ char * file1;
+ char * file2;
+ char * file3;
+ char * subdir1;
+ char * subdir2;
+
+ trantest_next_address(portbuf, "%u");
+
+ snprintf(url, sizeof(url), "http://127.0.0.1:%s", portbuf);
+
+ So(nni_aio_init(&aio, NULL, NULL) == 0);
+ So(nni_http_server_init(&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({
+ nni_aio_fini(aio);
+ nni_http_server_fini(s);
+ nni_strfree(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);
+ nni_strfree(workdir);
+ nni_strfree(file1);
+ nni_strfree(file2);
+ nni_strfree(file3);
+ nni_strfree(subdir1);
+ nni_strfree(subdir2);
+ });
+
+ So(nni_http_handler_init_directory(&h, "/docs", workdir) == 0);
+ So(nni_http_server_add_handler(s, h) == 0);
+ So(nni_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/docs/subdir1/index.html", url);
+ So(httpget(fullurl, &data, &size, &stat, &ctype) == 0);
+ So(stat == NNI_HTTP_STATUS_OK);
+ So(size == strlen(doc1));
+ So(memcmp(data, doc1, size) == 0);
+ So(strcmp(ctype, "text/html") == 0);
+ nni_strfree(ctype);
+ nni_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/docs/subdir2", url);
+ So(httpget(fullurl, &data, &size, &stat, &ctype) == 0);
+ So(stat == NNI_HTTP_STATUS_OK);
+ So(size == strlen(doc3));
+ So(memcmp(data, doc3, size) == 0);
+ So(strcmp(ctype, "text/html") == 0);
+ nni_strfree(ctype);
+ nni_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/docs/file.txt", url);
+ So(httpget(fullurl, &data, &size, &stat, &ctype) == 0);
+ So(stat == NNI_HTTP_STATUS_OK);
+ So(size == strlen(doc2));
+ So(memcmp(data, doc2, size) == 0);
+ So(strcmp(ctype, "text/plain") == 0);
+ nni_strfree(ctype);
+ nni_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/docs/", url);
+ So(httpget(fullurl, &data, &size, &stat, &ctype) == 0);
+ So(stat == NNI_HTTP_STATUS_NOT_FOUND);
+ So(size == 0);
+ });
+ });
+})