aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/net.md28
-rw-r--r--makefile2
-rw-r--r--src/lua.c1
-rw-r--r--src/net.c35
-rw-r--r--src/net/util.c105
-rw-r--r--src/net/util.h7
-rw-r--r--src/reg.c3
-rw-r--r--src/test.c25
-rw-r--r--src/test.h9
-rw-r--r--src/types/parray.c7
-rw-r--r--src/types/parray.h2
-rw-r--r--tests/match.lua42
-rw-r--r--tests/net.lua24
13 files changed, 285 insertions, 5 deletions
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)
diff --git a/makefile b/makefile
index dcd7451..086ee34 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 := -DGIT_COMMIT='$(GIT_COMMIT)' -Wall
+CFLAGS := -fPIC -DGIT_COMMIT='$(GIT_COMMIT)'
LFLAGS := -lm -shared
LINKER := $(CC)
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);
diff --git a/src/net.c b/src/net.c
index 2243117..b71b290 100644
--- a/src/net.c
+++ b/src/net.c
@@ -74,7 +74,23 @@ void* handle_client(void *_arg){
str* aa = str_init(portc);
str_push(aa, sk->c);
- void* v = parray_find(paths, aa->c);
+ //parray_t* v = parray_find(paths, aa->c);
+ larray_t* params = larray_init();
+ parray_t* v = route_match(paths, aa->c, &params);
+
+ /*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);
@@ -157,13 +173,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];
@@ -184,6 +214,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 36f6d39..1fec987 100644
--- a/src/net/util.c
+++ b/src/net/util.c
@@ -251,3 +251,108 @@ int content_disposition(str* src, parray_t** _dest){
return 1;
}
+
+int match_param(char* path, char* match, parray_t* arr){
+ int pi, index, imatch, start, mi;
+ mi = pi = imatch = start = 0;
+ index = -1;
+
+ enum steps {
+ NORMAL,
+ GET_KEY,
+ GET_VALUE
+ };
+
+ enum steps step = NORMAL;
+ char* name;
+
+ for(; /*(path[pi] != '\0' || step == 2) && */(match[mi] != '\0' || step == 1);){
+ 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;
+ }
+ 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 == GET_VALUE){
+ 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++);
+
+ return path[pi] == 0 && match[mi] == 0;
+}
+
+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(&params, out->len, (void*)temp);
+ out->len++;
+ } else {
+ parray_clear(temp, FREE);
+ }
+
+ //}
+ }
+
+ *_params = params;
+ return out;
+}
diff --git a/src/net/util.h b/src/net/util.h
index d723b6f..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
*
@@ -45,3 +45,8 @@ 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, larray_t** params);
+
+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 <signal.h>
#include <stdlib.h>
@@ -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/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/match.lua b/tests/match.lua
new file mode 100644
index 0000000..000b1e7
--- /dev/null
+++ b/tests/match.lua
@@ -0,0 +1,42 @@
+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(a..":"..b.." res("..res..") != expected")
+ 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
+
+ for i, v in ipairs(expect) do
+ if v ~= out[i] then
+ return llb.io.error("out != expect")
+ end
+ end
+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"})
+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)
+test("/*/", "/test", 0)
+test("/{meow}/", "/aw", 0)
+--i dont know if this should be valid, but idc
+test("/{meow}/", "//", 1, {meow=""})
+
diff --git a/tests/net.lua b/tests/net.lua
index 25ca696..90a18c3 100644
--- a/tests/net.lua
+++ b/tests/net.lua
@@ -17,6 +17,30 @@ net.listen(
io.pprint("online")
_G.server = server
+
+ 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 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)
b = crypto.md5("hello")