From 6cbc0f817066b8bbab84a9be466223652b628d42 Mon Sep 17 00:00:00 2001 From: ame Date: Mon, 26 Aug 2024 22:33:07 -0500 Subject: initial param matching --- makefile | 2 +- src/net.c | 3 ++- src/net/util.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ src/net/util.h | 2 ++ src/types/parray.c | 7 +++++++ src/types/parray.h | 2 ++ tests/net.lua | 8 ++++++++ 7 files changed, 70 insertions(+), 2 deletions(-) diff --git a/makefile b/makefile index 72e3243..11731cb 100644 --- a/makefile +++ b/makefile @@ -2,7 +2,7 @@ CC := clang GIT_COMMIT := "$(shell git describe --tags)-$(shell git describe --always --match 'NOT A TAG')" -CFLAGS := -fPIC -DGIT_COMMIT='$(GIT_COMMIT)' -Wall +CFLAGS := -fPIC -DGIT_COMMIT='$(GIT_COMMIT)' LFLAGS := -lm -shared LINKER := clang diff --git a/src/net.c b/src/net.c index 7db887b..2966905 100644 --- a/src/net.c +++ b/src/net.c @@ -70,7 +70,8 @@ void* handle_client(void *_arg){ str_push(aa, sk->c); - void* v = parray_find(paths, aa->c); + //parray_t* v = parray_find(paths, aa->c); + parray_t* v = route_match(paths, aa->c); if(sT != NULL) rolling_file_parse(L, &files_idx, &body_idx, buffer + header_eof + 4, sT, bytes_received - header_eof - 4, file_cont); diff --git a/src/net/util.c b/src/net/util.c index 213be9f..bc2c6bb 100644 --- a/src/net/util.c +++ b/src/net/util.c @@ -239,3 +239,51 @@ int content_disposition(str* src, parray_t** _dest){ return 1; } + +int match_param(char* path, char* match){ + int pi, mi = pi = 0; + int step = 0; + //0 increment both + //1 move match to find '/' or '\0' + //2 move path to find '}' + for(; path[pi] != '\0' && match[mi] != '\0';){ + if(step == 0){ + if(path[pi] == '{'){ + step = 1; + } else { + pi++; + mi++; + } + } else if (step == 1){ + if(match[mi] == '/'){ + printf("\n"); + step = 2; + } else { + printf("%c",match[mi]); + mi++; + } + } else if (step == 2){ + if(path[pi] == '}'){ + step = 0; + } else { + pi++; + } + } + } + return 0; +} + +parray_t* route_match(parray_t* paths, char* request){ + parray_t* out = parray_initl(paths->len); + out->len = 0; + + for(int i = 0; i != paths->len; i++){ + match_param(paths->P[i].key->c, request); + if(strcmp(request, paths->P[i].key->c) == 0){ + out->P[out->len] = paths->P[i]; + out->len++; + + } + } + return out; +} diff --git a/src/net/util.h b/src/net/util.h index d723b6f..ea7c294 100644 --- a/src/net/util.h +++ b/src/net/util.h @@ -45,3 +45,5 @@ void http_code(int code, char* code_det); void client_fd_errors(int client_fd); int content_disposition(str* src, parray_t** _dest); + +parray_t* route_match(parray_t* paths, char* path); diff --git a/src/types/parray.c b/src/types/parray.c index a1109c5..b1e41a2 100644 --- a/src/types/parray.c +++ b/src/types/parray.c @@ -31,6 +31,13 @@ parray_t* parray_init(){ return awa; } +parray_t* parray_initl(int len){ + parray_t* awa = malloc(sizeof * awa); + awa->P = malloc(sizeof * awa->P * len); + awa->len = len; + return awa; +} + /** * @brief sets value at key to value, adds a new index if new * diff --git a/src/types/parray.h b/src/types/parray.h index fb89689..7972cc1 100644 --- a/src/types/parray.h +++ b/src/types/parray.h @@ -17,6 +17,8 @@ enum free_type { }; parray_t* parray_init(); +parray_t* parray_initl(int len); + void parray_set(parray_t*, char*, void*); void parray_push(parray_t*, char*, void*); void* parray_get(parray_t* , char*); diff --git a/tests/net.lua b/tests/net.lua index 25ca696..fdb17d4 100644 --- a/tests/net.lua +++ b/tests/net.lua @@ -17,6 +17,14 @@ net.listen( io.pprint("online") _G.server = server + + server:all("/{name}", function(res, req) + print("name is "..req.name) + end) + server:all("*", function(res, req) + print("all") + end) + server:all("/", function(res, req) b = crypto.md5("hello") -- cgit v1.2.3 From f605f194eb45235989fc5ec91505201498834f24 Mon Sep 17 00:00:00 2001 From: amelia squires Date: Thu, 29 Aug 2024 00:10:05 -0500 Subject: should be working + tests --- src/net/util.c | 81 +++++++++++++++++++++++++++++++++++++++++++++------------ src/net/util.h | 3 +++ src/reg.c | 3 +++ src/test.c | 25 ++++++++++++++++++ src/test.h | 9 +++++++ tests/match.lua | 37 ++++++++++++++++++++++++++ tests/net.lua | 13 ++++++++- 7 files changed, 154 insertions(+), 17 deletions(-) create mode 100644 src/test.c create mode 100644 src/test.h create mode 100644 tests/match.lua diff --git a/src/net/util.c b/src/net/util.c index bc2c6bb..c25ac39 100644 --- a/src/net/util.c +++ b/src/net/util.c @@ -240,37 +240,84 @@ int content_disposition(str* src, parray_t** _dest){ return 1; } -int match_param(char* path, char* match){ - int pi, mi = pi = 0; +int match_param(char* path, char* match, parray_t* arr){ + int pi, index, imatch, start, mi; + mi = pi = imatch = start = 0; + index = -1; + int step = 0; //0 increment both - //1 move match to find '/' or '\0' - //2 move path to find '}' - for(; path[pi] != '\0' && match[mi] != '\0';){ + //1 move path to find '}' + //2 move match to find '/' or '\0' + char* name; + + for(; /*(path[pi] != '\0' || step == 2) && */(match[mi] != '\0' || step == 1);){ if(step == 0){ if(path[pi] == '{'){ + step = 1; + start = pi; + } else if(path[pi] == '*'){ + //printf("found\n"); + index = pi; + imatch = mi; + } else { - pi++; + + if(path[pi] != match[mi]){ + //printf("whaa\n"); + if(index == -1) return 0; + //printf("here\n"); + pi = index + 1; + imatch++; + mi = imatch; + + } mi++; } + pi++; + } else if (step == 1){ - if(match[mi] == '/'){ - printf("\n"); + if(path[pi] == '}'){ step = 2; + name = calloc(pi - start, sizeof * name); + memcpy(name, path + start + 1, pi - start - 1); + start = mi; + //printf(": "); } else { - printf("%c",match[mi]); - mi++; + //printf("%c", path[pi]); } + pi++; + } else if (step == 2){ - if(path[pi] == '}'){ + //change this to maybe match the next path char? + if(match[mi] == '/'){ step = 0; + + char* out = calloc(mi - start, sizeof * out); + memcpy(out, match + start, mi - start); + parray_set(arr, name, out); + free(name); + //printf("\n"); } else { - pi++; + //printf("%c", match[mi]); + mi++; } } } - return 0; + + if(step == 2){ + char* out = calloc(mi - start, sizeof * out); + memcpy(out, match + start, mi - start); + parray_set(arr, name, out); + free(name); + } + + if(path[pi] != 0) for(; path[pi] == '*'; pi++); + + //printf("path: '%s':'%s'\nmatch: '%s':'%s'\nend: %i,%i\n",path, &path[pi], match,&match[mi],path[pi],match[mi]); + + return path[pi] == 0 && match[mi] == 0; } parray_t* route_match(parray_t* paths, char* request){ @@ -278,12 +325,14 @@ parray_t* route_match(parray_t* paths, char* request){ out->len = 0; for(int i = 0; i != paths->len; i++){ - match_param(paths->P[i].key->c, request); - if(strcmp(request, paths->P[i].key->c) == 0){ + //if(match_param(paths->P[i].key->c, request)) + //*if(strcmp(request, paths->P[i].key->c) == 0)*/{ + //printf("pass!\n"); out->P[out->len] = paths->P[i]; out->len++; - } + //} } + printf("\n"); return out; } diff --git a/src/net/util.h b/src/net/util.h index ea7c294..17a99ac 100644 --- a/src/net/util.h +++ b/src/net/util.h @@ -47,3 +47,6 @@ void client_fd_errors(int client_fd); int content_disposition(str* src, parray_t** _dest); parray_t* route_match(parray_t* paths, char* path); + +int match_param(char* path, char* match, parray_t* arr); + diff --git a/src/reg.c b/src/reg.c index dbd3c48..7345d4b 100644 --- a/src/reg.c +++ b/src/reg.c @@ -6,6 +6,7 @@ #include "math.h" #include "net.h" #include "thread.h" +#include "test.h" #include #include @@ -36,6 +37,7 @@ open_common(math); open_common(config); open_common(net); open_common(thread); +open_common(test); #define push(T, name)\ lua_pushstring(L, #name);\ @@ -62,6 +64,7 @@ int luaopen_lullaby(lua_State* L) { push(top, config); push(top, net); push(top, thread); + push(top, test); luaI_tsets(L, top, "version", GIT_COMMIT) //lreg("array", array_function_list); //lreg("crypto", crypto_function_list); diff --git a/src/test.c b/src/test.c new file mode 100644 index 0000000..4408878 --- /dev/null +++ b/src/test.c @@ -0,0 +1,25 @@ +#include "test.h" +#include "net/util.h" +#include "types/parray.h" + +int ld_match(lua_State* L){ + parray_t* a = parray_init(); + int o = match_param(lua_tostring(L, 1), lua_tostring(L, 2), a); + + if(o == 0){ + lua_pushinteger(L, o); + return 1; + } + + lua_newtable(L); + int tidx = lua_gettop(L); + for(int i = 0; i != a->len; i++){ + //printf("%s:%s\n",a->P[i].key->c, (char*)a->P[i].value); + luaI_tsets(L, tidx, a->P[i].key->c, (char*)a->P[i].value); + } + + lua_pushinteger(L, o); + lua_pushvalue(L, tidx); + return 2; +} + diff --git a/src/test.h b/src/test.h new file mode 100644 index 0000000..01527c6 --- /dev/null +++ b/src/test.h @@ -0,0 +1,9 @@ +#include "lua.h" + +int ld_match(lua_State*); + +static const luaL_Reg test_function_list [] = { + {"_match", ld_match}, + + {NULL,NULL} +}; diff --git a/tests/match.lua b/tests/match.lua new file mode 100644 index 0000000..d9c1533 --- /dev/null +++ b/tests/match.lua @@ -0,0 +1,37 @@ +llb = require "lullaby" + +function test(a, b, match, expect) + res, out = llb.test._match(a, b) + + if res ~= match then + return llb.io.error("res != match") + end + + if res == 0 then return end + + if llb.array.len(out) ~= llb.array.len(expect) then + return llb.io.error("out != expect") + end + + for i, v in ipairs(expect) do + if v ~= out[i] then + return llb.io.error("out != expect") + end + end + llb.io.pprint(out) +end + +test("/{test}/","/name/", 1, {test="name"}) +test("*","/wdejowe/wde", 1, {}) +test("/*/{hello}/{meow}/end","/blah/blah/hii/end", 1, {hello="blah", meow="hii"}) +test("/*/*/{test}/*/*/end/*/real","/a/b/testing/d/e/end/f/real", 1, {test="testing"}) +test("/*/a/b/end/{word}","/w/o/m/p/a/b/end/meow", 1, {word="meow"}) +test("*", "meow/meow/meow", 1, {}) +test("{meow}", "owo", 1, {meow="owo"}) +test("/{meow}", "/owo", 1, {meow="owo"}) +test("{meow}", "/", 0) +test("/{meow}", "/", 0) + + + + diff --git a/tests/net.lua b/tests/net.lua index fdb17d4..940e2fb 100644 --- a/tests/net.lua +++ b/tests/net.lua @@ -19,12 +19,23 @@ net.listen( _G.server = server server:all("/{name}", function(res, req) - print("name is "..req.name) + --print("name is "..req.name) + print("name") end) + + server:all("/{name}/nya/{user}", function(res, req) + --print("name is "..req.name) + print("name id user") + end) + server:all("*", function(res, req) print("all") end) + server:all("/{name}/user/*/{id}", function(res, req) + print("owo") + end) + server:all("/", function(res, req) b = crypto.md5("hello") -- cgit v1.2.3 From dfb108f6c7abbdeba832d3568d77153fc8c5a3a6 Mon Sep 17 00:00:00 2001 From: ame Date: Sun, 1 Sep 2024 20:18:34 -0500 Subject: clean --- src/net/util.c | 110 +++++++++++++++++++++++++++----------------------------- tests/match.lua | 21 ++++++----- 2 files changed, 66 insertions(+), 65 deletions(-) diff --git a/src/net/util.c b/src/net/util.c index c25ac39..41069fb 100644 --- a/src/net/util.c +++ b/src/net/util.c @@ -245,68 +245,66 @@ int match_param(char* path, char* match, parray_t* arr){ mi = pi = imatch = start = 0; index = -1; - int step = 0; - //0 increment both - //1 move path to find '}' - //2 move match to find '/' or '\0' + enum steps { + NORMAL, + GET_KEY, + GET_VALUE + }; + + enum steps step = NORMAL; char* name; for(; /*(path[pi] != '\0' || step == 2) && */(match[mi] != '\0' || step == 1);){ - if(step == 0){ - if(path[pi] == '{'){ - - step = 1; - start = pi; - } else if(path[pi] == '*'){ - //printf("found\n"); - index = pi; - imatch = mi; - - } else { - - if(path[pi] != match[mi]){ - //printf("whaa\n"); - if(index == -1) return 0; - //printf("here\n"); - pi = index + 1; - imatch++; - mi = imatch; - + switch(step){ + case NORMAL: + if(path[pi] == '{'){ + + step = GET_KEY; + start = pi; + } else if(path[pi] == '*'){ + index = pi; + imatch = mi; + + } else { + + if(path[pi] != match[mi]){ + if(index == -1) return 0; + + pi = index + 1; + imatch++; + mi = imatch; + continue; + } + mi++; + } + pi++; + break; + case GET_KEY: + if(path[pi] == '}'){ + step = GET_VALUE; + name = calloc(pi - start, sizeof * name); + memcpy(name, path + start + 1, pi - start - 1); + start = mi; } - mi++; - } - pi++; - - } else if (step == 1){ - if(path[pi] == '}'){ - step = 2; - name = calloc(pi - start, sizeof * name); - memcpy(name, path + start + 1, pi - start - 1); - start = mi; - //printf(": "); - } else { - //printf("%c", path[pi]); - } - pi++; - - } else if (step == 2){ - //change this to maybe match the next path char? - if(match[mi] == '/'){ - step = 0; - - char* out = calloc(mi - start, sizeof * out); - memcpy(out, match + start, mi - start); - parray_set(arr, name, out); - free(name); - //printf("\n"); - } else { - //printf("%c", match[mi]); - mi++; - } + pi++; + break; + case GET_VALUE: + //change this to maybe match the next path char? + if(match[mi] == '/'){ + step = NORMAL; + + char* out = calloc(mi - start, sizeof * out); + memcpy(out, match + start, mi - start); + parray_set(arr, name, out); + free(name); + } else { + mi++; + } + break; } } - if(step == 2){ + if(step == GET_VALUE){ char* out = calloc(mi - start, sizeof * out); memcpy(out, match + start, mi - start); parray_set(arr, name, out); @@ -315,8 +313,6 @@ int match_param(char* path, char* match, parray_t* arr){ if(path[pi] != 0) for(; path[pi] == '*'; pi++); - //printf("path: '%s':'%s'\nmatch: '%s':'%s'\nend: %i,%i\n",path, &path[pi], match,&match[mi],path[pi],match[mi]); - return path[pi] == 0 && match[mi] == 0; } diff --git a/tests/match.lua b/tests/match.lua index d9c1533..000b1e7 100644 --- a/tests/match.lua +++ b/tests/match.lua @@ -2,13 +2,17 @@ llb = require "lullaby" function test(a, b, match, expect) res, out = llb.test._match(a, b) + + if res == 0 and res == match then return end - if res ~= match then - return llb.io.error("res != match") + if res ~= match then + return llb.io.error(a..":"..b.." res("..res..") != expected") end - if res == 0 then return end - + if res == 0 then + return llb.io.error(a..":"..b.." res == match") + end + if llb.array.len(out) ~= llb.array.len(expect) then return llb.io.error("out != expect") end @@ -18,10 +22,10 @@ function test(a, b, match, expect) return llb.io.error("out != expect") end end - llb.io.pprint(out) end test("/{test}/","/name/", 1, {test="name"}) +test("/", "/wawawawawawaw", 0) test("*","/wdejowe/wde", 1, {}) test("/*/{hello}/{meow}/end","/blah/blah/hii/end", 1, {hello="blah", meow="hii"}) test("/*/*/{test}/*/*/end/*/real","/a/b/testing/d/e/end/f/real", 1, {test="testing"}) @@ -31,7 +35,8 @@ test("{meow}", "owo", 1, {meow="owo"}) test("/{meow}", "/owo", 1, {meow="owo"}) test("{meow}", "/", 0) test("/{meow}", "/", 0) - - - +test("/*/", "/test", 0) +test("/{meow}/", "/aw", 0) +--i dont know if this should be valid, but idc +test("/{meow}/", "//", 1, {meow=""}) -- cgit v1.2.3 From 8a3be37b30dffda61cc8c3dc5c7b1af8fec3d539 Mon Sep 17 00:00:00 2001 From: amelia squires Date: Wed, 4 Sep 2024 00:17:02 -0500 Subject: fix leak --- src/lua.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lua.c b/src/lua.c index 238e1b8..225dfbf 100644 --- a/src/lua.c +++ b/src/lua.c @@ -87,6 +87,7 @@ void luaI_deepcopy(lua_State* src, lua_State* dest, enum deep_copy_flags flags){ //printf("use %p\n", lua_topointer(src, at2)); //lua_pop(dest, 1); lua_remove(dest, -2); + free(aauwu); return; } free(aauwu); -- cgit v1.2.3 From 3bdf71c456a905607cb597ccc515bb222f86321d Mon Sep 17 00:00:00 2001 From: amelia squires Date: Wed, 4 Sep 2024 01:17:25 -0500 Subject: add to server, and fix leaks --- src/net.c | 34 ++++++++++++++++++++++++++++++++-- src/net/util.c | 18 +++++++++++++++--- src/net/util.h | 4 ++-- tests/net.lua | 7 ++++++- 4 files changed, 55 insertions(+), 8 deletions(-) diff --git a/src/net.c b/src/net.c index 2966905..48c685d 100644 --- a/src/net.c +++ b/src/net.c @@ -71,7 +71,22 @@ void* handle_client(void *_arg){ str_push(aa, sk->c); //parray_t* v = parray_find(paths, aa->c); - parray_t* v = route_match(paths, aa->c); + larray_t* params = larray_init(); + parray_t* v = route_match(paths, aa->c, ¶ms); + + /*for(int i = 0; i != params->len; i++){ + int id = larray_geti(params, i); + parray_t* par = params->arr[id].value; + printf("%i\n", i); + for(int x = 0; x != par->len; x++){ + printf("\t%s : %s\n",par->P[x].key->c, (char*)par->P[x].value); + } + + parray_clear(par, STR); + + } + + larray_clear(params);*/ if(sT != NULL) rolling_file_parse(L, &files_idx, &body_idx, buffer + header_eof + 4, sT, bytes_received - header_eof - 4, file_cont); @@ -154,13 +169,27 @@ void* handle_client(void *_arg){ luaI_tsets(L, header_idx, "Content-Type", "text/html"); luaI_tsetv(L, res_idx, "header", header_idx); - + //get all function that kinda match parray_t* owo = (parray_t*)v; for(int i = 0; i != owo->len; i++){ //though these are arrays of arrays we have to iterate *again* struct sarray_t* awa = (struct sarray_t*)owo->P[i].value; + //push url params + lua_newtable(L); + int new_param_idx = lua_gettop(L); + + int id = larray_geti(params, i); + parray_t* par = params->arr[id].value; + + for(int z = 0; z != par->len; z++){ + luaI_tsets(L, new_param_idx, par->P[z].key->c, (char*)par->P[z].value); + } + parray_clear(par, FREE); + + luaI_tsetv(L, req_idx, "paramaters", new_param_idx); + for(int z = 0; z != awa->len; z++){ char* path; struct lchar* wowa = awa->cs[z]; @@ -181,6 +210,7 @@ void* handle_client(void *_arg){ } } } + larray_clear(params); parray_lclear(owo); //dont free the rest lua_pushstring(L, "client_fd"); diff --git a/src/net/util.c b/src/net/util.c index 41069fb..868da0f 100644 --- a/src/net/util.c +++ b/src/net/util.c @@ -316,19 +316,31 @@ int match_param(char* path, char* match, parray_t* arr){ return path[pi] == 0 && match[mi] == 0; } -parray_t* route_match(parray_t* paths, char* request){ - parray_t* out = parray_initl(paths->len); +parray_t* route_match(parray_t* paths, char* request, larray_t** _params){ + larray_t* params = *_params; + parray_t* out = parray_initl(paths->len * 2); + parray_t* temp; out->len = 0; for(int i = 0; i != paths->len; i++){ //if(match_param(paths->P[i].key->c, request)) //*if(strcmp(request, paths->P[i].key->c) == 0)*/{ //printf("pass!\n"); + //printf("%i\n", i); + + temp = parray_init(); + + if(match_param(paths->P[i].key->c, request, temp)){ out->P[out->len] = paths->P[i]; + larray_set(¶ms, out->len, (void*)temp); out->len++; + } else { + parray_clear(temp, FREE); + } //} } - printf("\n"); + + *_params = params; return out; } diff --git a/src/net/util.h b/src/net/util.h index 17a99ac..98d4d93 100644 --- a/src/net/util.h +++ b/src/net/util.h @@ -1,5 +1,5 @@ #include "common.h" - +#include "../types/larray.h" /** * @brief calls recv into buffer until everything is read * @@ -46,7 +46,7 @@ void client_fd_errors(int client_fd); int content_disposition(str* src, parray_t** _dest); -parray_t* route_match(parray_t* paths, char* path); +parray_t* route_match(parray_t* paths, char* path, larray_t** params); int match_param(char* path, char* match, parray_t* arr); diff --git a/tests/net.lua b/tests/net.lua index 940e2fb..90a18c3 100644 --- a/tests/net.lua +++ b/tests/net.lua @@ -21,19 +21,24 @@ net.listen( server:all("/{name}", function(res, req) --print("name is "..req.name) print("name") + io.pprint(req.paramaters) end) server:all("/{name}/nya/{user}", function(res, req) --print("name is "..req.name) - print("name id user") + print("name user") + io.pprint(req.paramaters) end) server:all("*", function(res, req) print("all") + io.pprint(req.paramaters) end) server:all("/{name}/user/*/{id}", function(res, req) print("owo") + io.pprint(req.paramaters) + end) server:all("/", function(res, req) -- cgit v1.2.3 From ab5c24cd0eb59b704cf98d388338293db3768c81 Mon Sep 17 00:00:00 2001 From: amelia squires Date: Wed, 4 Sep 2024 12:49:26 -0500 Subject: net rewrite docs --- docs/net.md | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/docs/net.md b/docs/net.md index 474cdbe..e548cb1 100644 --- a/docs/net.md +++ b/docs/net.md @@ -30,7 +30,7 @@ server:unlock() ... ``` -### server:close +### server:close ** closes server @@ -41,6 +41,8 @@ closes server the function has 2 arguments, the first (res) contains functions and info about resolving the request, the second (req) contains info on the request, the path allows for wildcards, multiple get requests per path is allowed +it also allows for path paramaters which is a wildcard directory that pushes the results into req.paramaters (read below) + the actual name of the function will change based on what request method you want to accept, all requests are treated the exact same on the backend, besides HEAD requests which will also use all GET requets, and the 'all' variant will get everything ```lua @@ -56,6 +58,10 @@ server:GET("/", function(res, req) ... end) ... + +server:GET("/home/{user}/id", function(res, req) + --sets req.paramaters.user to whatever path was requested +end) ``` #### res:write @@ -119,6 +125,26 @@ res:sendfile("./html/index.html") ... ``` +### req.paramaters + +a list of paramaters for the current function + +a path of '/user/{name}/id' +and a request of '/user/amelia/id' +would set req.paramaters.name to amelia + +currently you can not have multiple paramaters per directory + +> this could be changed in later versions + +/home/{name} is valid + +/flight/{id}-{airline} is not + +these can, of course be used with wildcards however you want + +/*/{user}/id would match /a/b/c/meow/id with req.paramaters.user being equal to meow + ### req:roll 'takes an integer of bytes to read & parse (optional, otherwise the max amount of bytes will be read) -- cgit v1.2.3