2020-05-16 01:10:11 +02:00
|
|
|
/*Export kore's functions to lua*/
|
|
|
|
#include <kore/kore.h>
|
|
|
|
#include <kore/http.h>
|
|
|
|
#ifdef BUILD_PROD
|
|
|
|
#include <luajit.h>
|
|
|
|
#endif
|
|
|
|
#include <lauxlib.h>
|
|
|
|
#include <lua.h>
|
|
|
|
#include <lualib.h>
|
|
|
|
//#include <inet/in.h>//linux only I guess
|
|
|
|
#include "libkore.h"
|
2020-05-17 19:16:29 +02:00
|
|
|
#include <syslog.h>
|
|
|
|
|
|
|
|
#define LUA_PUSH_CONST(L,a) lua_pushnumber(L,a); lua_setfield(L,-2,#a);
|
2020-05-16 01:10:11 +02:00
|
|
|
|
|
|
|
struct http_request*
|
|
|
|
luaL_checkrequest(lua_State *L, int pos){
|
|
|
|
if(!lua_isuserdata(L,pos)){
|
|
|
|
lua_pushstring(L,"Bad argument, expected userdata, got ");
|
|
|
|
lua_pushstring(L,lua_typename(L,lua_type(L,pos)));
|
|
|
|
lua_concat(L,2);
|
|
|
|
lua_error(L);
|
|
|
|
}
|
|
|
|
return lua_touserdata(L,pos);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
http_response(request::userdata, errcode::number, data::string)
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
lhttp_response(lua_State *L){
|
|
|
|
size_t size;
|
|
|
|
const char *data = luaL_checklstring(L,-1,&size);
|
|
|
|
int httpcode = luaL_checkint(L,-2);
|
|
|
|
struct http_request *req = luaL_checkrequest(L,-3);
|
|
|
|
http_response(req,httpcode,data,size);
|
|
|
|
lua_pop(L,3);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
http_method_text(request::userdata)::string
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
lhttp_method_text(lua_State *L){
|
|
|
|
struct http_request *req = luaL_checkrequest(L,-1);
|
|
|
|
lua_pop(L,1);
|
|
|
|
const char *method = http_method_text(req->method);
|
|
|
|
lua_pushstring(L,method);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
http_request_get_path(request::userdata)::string
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
lhttp_request_get_path(lua_State *L){
|
|
|
|
struct http_request *req = luaL_checkrequest(L,-1);
|
|
|
|
lua_pop(L,1);
|
|
|
|
const char *path = req->path;
|
|
|
|
lua_pushstring(L,path);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
http_request_get_host(request::userdata)::string
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
lhttp_request_get_host(lua_State *L){
|
|
|
|
struct http_request *req = luaL_checkrequest(L,-1);
|
|
|
|
lua_pop(L,1);
|
|
|
|
const char *host = req->host;
|
|
|
|
lua_pushstring(L,host);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
http_request_populate_post(request::userdata)
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
lhttp_request_populate_post(lua_State *L){
|
|
|
|
struct http_request *req = luaL_checkrequest(L,-1);
|
|
|
|
lua_pop(L,1);
|
|
|
|
http_populate_post(req);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
http_request_populate_qs(request::userdata)
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
lhttp_request_populate_qs(lua_State *L){
|
|
|
|
struct http_request *req = luaL_checkrequest(L,-1);
|
|
|
|
lua_pop(L,1);
|
|
|
|
http_populate_qs(req);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
http_response_header(request::userdata, header::string, value::string)
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
lhttp_response_header(lua_State *L){
|
|
|
|
const char *value = luaL_checkstring(L,-1);
|
|
|
|
const char *header = luaL_checkstring(L,-2);
|
|
|
|
struct http_request *req = luaL_checkrequest(L,-3);
|
|
|
|
lua_pop(L,3);
|
|
|
|
http_response_header(req, header, value);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-02-03 05:09:12 +01:00
|
|
|
/*
|
|
|
|
http_request_header(request::userdata, header::string)::(string || false, string)
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
lhttp_request_header(lua_State *L){
|
|
|
|
const char *header = luaL_checkstring(L,-1);
|
|
|
|
struct http_request *req = luaL_checkrequest(L,-2);
|
|
|
|
lua_pop(L,2);
|
|
|
|
const char *data;
|
|
|
|
int err = http_request_header(req,header,&data);
|
|
|
|
if(err == KORE_RESULT_OK){
|
|
|
|
lua_pushstring(L,data);
|
|
|
|
return 1;
|
|
|
|
}else{
|
|
|
|
lua_pushboolean(L,0);
|
|
|
|
lua_pushstring(L,"Failed to get header: ");
|
|
|
|
lua_pushstring(L,header);
|
|
|
|
lua_concat(L,2);
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-05-16 01:10:11 +02:00
|
|
|
/*
|
|
|
|
http_response_cookie(req::userdata, name::string, value::string, path::string, expires::number, maxage::number)
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
lhttp_response_cookie(lua_State *L){
|
|
|
|
//int flags = luaL_checkint(L,-1);//TODO: flags
|
|
|
|
int maxage = luaL_checkint(L,-1);
|
|
|
|
int expires = luaL_checkint(L,-2);
|
|
|
|
const char *path = luaL_checkstring(L,-3);
|
|
|
|
const char *value = luaL_checkstring(L,-4);
|
|
|
|
const char *name = luaL_checkstring(L,-5);
|
|
|
|
struct http_request *req = luaL_checkrequest(L,-6);
|
|
|
|
lua_pop(L,6);
|
|
|
|
http_response_cookie(req,name,value,path,expires,maxage,NULL);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
http_request_cookie(req::userdata, name::string)::string | nil
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
lhttp_request_cookie(lua_State *L){
|
|
|
|
char *value;
|
|
|
|
const char *name = luaL_checkstring(L,-1);
|
|
|
|
struct http_request *req = luaL_checkrequest(L,-2);
|
|
|
|
lua_pop(L,2);
|
|
|
|
if(http_request_cookie(req,name,&value)){
|
|
|
|
lua_pushstring(L,value);
|
|
|
|
}else{
|
|
|
|
lua_pushnil(L);
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
This method may fail, if it does, it will return false plus an error message
|
|
|
|
http_argument_get_string(request::userdata, name::string)::(string || false, string)
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
lhttp_argument_get_string(lua_State *L){
|
|
|
|
const char *name = luaL_checkstring(L,-1);
|
|
|
|
struct http_request *req = luaL_checkrequest(L,-2);
|
|
|
|
lua_pop(L,2);
|
|
|
|
const char *value;
|
|
|
|
int err = http_argument_get_string(req,name,&value);
|
|
|
|
if(err == KORE_RESULT_OK){
|
|
|
|
lua_pushstring(L,value);
|
|
|
|
return 1;
|
|
|
|
}else{
|
|
|
|
lua_pushboolean(L,0);
|
|
|
|
lua_pushstring(L,"Failed to find argument: ");
|
|
|
|
lua_pushstring(L,name);
|
|
|
|
lua_concat(L,2);
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
Get the ip of this connection, ipv6 supported
|
|
|
|
http_request_get_ip(request::userdata)::string
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
lhttp_request_get_ip(lua_State *L){
|
|
|
|
struct http_request *req = luaL_checkrequest(L,-1);
|
|
|
|
lua_pop(L,1);
|
|
|
|
char addr[INET6_ADDRSTRLEN];
|
|
|
|
switch(req->owner->family){
|
|
|
|
case AF_INET:
|
|
|
|
inet_ntop(
|
|
|
|
req->owner->family,
|
|
|
|
&(req->owner->addr.ipv4.sin_addr),
|
|
|
|
addr,
|
|
|
|
sizeof(addr)
|
|
|
|
);
|
|
|
|
break;
|
|
|
|
case AF_INET6:
|
|
|
|
inet_ntop(
|
|
|
|
req->owner->family,
|
|
|
|
&(req->owner->addr.ipv6.sin6_addr),
|
|
|
|
addr,
|
|
|
|
sizeof(addr)
|
|
|
|
);
|
|
|
|
break;
|
|
|
|
case AF_UNIX:
|
|
|
|
default:
|
|
|
|
lua_pushstring(L,"Tried to get IP from unknown socket family:");
|
|
|
|
lua_getglobal(L,"tostring");
|
|
|
|
lua_pushnumber(L,req->owner->family);
|
|
|
|
lua_call(L,1,1);
|
|
|
|
lua_concat(L,2);
|
|
|
|
lua_error(L);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
lua_pushstring(L,addr);
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
http_populate_cookies(request::userdata)
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
lhttp_populate_cookies(lua_State *L){
|
|
|
|
struct http_request *req = luaL_checkrequest(L,-1);
|
|
|
|
lua_pop(L,1);
|
|
|
|
http_populate_cookies(req);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
http_populate_multipart_form(request::userdata)
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
lhttp_populate_multipart_form(lua_State *L){
|
|
|
|
struct http_request *req = luaL_checkrequest(L,-1);
|
|
|
|
lua_pop(L,1);
|
|
|
|
http_populate_multipart_form(req);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
http_file_get(request::userdata, name::string)::string
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
lhttp_file_get(lua_State *L){
|
|
|
|
const char *name = luaL_checkstring(L,-1);
|
|
|
|
struct http_request *req = luaL_checkrequest(L,-2);
|
|
|
|
lua_pop(L,2);
|
|
|
|
struct http_file *f = http_file_lookup(req, name);
|
|
|
|
if(f == NULL){
|
|
|
|
lua_pushstring(L,"No such file:");
|
|
|
|
lua_pushstring(L,name);
|
|
|
|
lua_concat(L,2);
|
|
|
|
lua_error(L);
|
|
|
|
}
|
|
|
|
char s[f->length + 1];
|
|
|
|
size_t read = http_file_read(f,s,f->length);
|
|
|
|
if(read < f->length){
|
|
|
|
lua_pushstring(L,"Failed to read contents of:");
|
|
|
|
lua_pushstring(L,name);
|
|
|
|
lua_concat(L,2);
|
|
|
|
lua_error(L);
|
|
|
|
}
|
|
|
|
s[f->length] = '\0';
|
2020-05-19 20:04:39 +02:00
|
|
|
lua_pushlstring(L,s,read);
|
2020-05-16 01:10:11 +02:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2020-05-17 19:16:29 +02:00
|
|
|
/*
|
2020-12-23 07:02:02 +01:00
|
|
|
log(priority::integer,message::string) //formating must be done before calling
|
2020-05-17 19:16:29 +02:00
|
|
|
*/
|
|
|
|
int
|
|
|
|
lkore_log(lua_State *L){
|
|
|
|
const char *str = luaL_checkstring(L,-1);
|
|
|
|
int prio = luaL_checkint(L,-2);
|
|
|
|
lua_pop(L,2);
|
|
|
|
kore_log(prio,"%s",str);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-05-16 01:10:11 +02:00
|
|
|
static const luaL_Reg kore_funcs[] = {
|
|
|
|
{"http_response", lhttp_response},
|
|
|
|
{"http_response_header", lhttp_response_header},
|
2021-02-03 05:09:12 +01:00
|
|
|
{"http_request_header", lhttp_request_header},
|
2020-05-16 01:10:11 +02:00
|
|
|
{"http_method_text",lhttp_method_text},
|
|
|
|
{"http_request_get_path",lhttp_request_get_path},
|
|
|
|
{"http_request_get_host",lhttp_request_get_host},
|
|
|
|
{"http_request_populate_post",lhttp_request_populate_post},
|
|
|
|
{"http_request_populate_qs",lhttp_request_populate_qs},
|
|
|
|
{"http_request_cookie",lhttp_request_cookie},
|
|
|
|
{"http_response_cookie",lhttp_response_cookie},
|
|
|
|
{"http_argument_get_string",lhttp_argument_get_string},
|
|
|
|
{"http_request_get_ip",lhttp_request_get_ip},
|
|
|
|
{"http_populate_cookies",lhttp_populate_cookies},
|
|
|
|
{"http_populate_multipart_form",lhttp_populate_multipart_form},
|
|
|
|
{"http_file_get",lhttp_file_get},
|
2020-05-17 19:16:29 +02:00
|
|
|
{"log",lkore_log},
|
2020-05-16 01:10:11 +02:00
|
|
|
{NULL,NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static const luaL_Reg http_request_meta[] = {
|
|
|
|
{NULL,NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
void
|
|
|
|
load_kore_libs(lua_State *L){
|
|
|
|
luaL_newmetatable(L,"http_request");//{m_http_request}
|
|
|
|
lua_newtable(L);//{m_http_request},{}
|
|
|
|
luaL_register(L,NULL,http_request_meta);//{m_http_request},{meta}
|
|
|
|
lua_setfield(L,-2,"__index");//{m_http_request}
|
|
|
|
lua_pop(L,1);
|
|
|
|
|
|
|
|
lua_getglobal(L,"_G");
|
|
|
|
luaL_register(L,NULL,kore_funcs);
|
2020-05-17 19:16:29 +02:00
|
|
|
//Push priority constants for use with log()
|
|
|
|
LUA_PUSH_CONST(L,LOG_EMERG);
|
|
|
|
LUA_PUSH_CONST(L,LOG_ALERT);
|
|
|
|
LUA_PUSH_CONST(L,LOG_CRIT);
|
|
|
|
LUA_PUSH_CONST(L,LOG_ERR);
|
|
|
|
LUA_PUSH_CONST(L,LOG_WARNING);
|
|
|
|
LUA_PUSH_CONST(L,LOG_NOTICE);
|
|
|
|
LUA_PUSH_CONST(L,LOG_INFO);
|
|
|
|
LUA_PUSH_CONST(L,LOG_DEBUG);
|
2021-01-16 21:59:56 +01:00
|
|
|
|
|
|
|
//Set a global variable "PRODUCTION" true or false
|
2020-05-17 19:16:29 +02:00
|
|
|
#ifdef BUILD_PROD
|
2020-05-18 16:41:27 +02:00
|
|
|
lua_pushboolean(L,1);
|
2020-05-17 19:16:29 +02:00
|
|
|
#else
|
2020-05-18 16:41:27 +02:00
|
|
|
lua_pushboolean(L,0);
|
2020-05-17 19:16:29 +02:00
|
|
|
#endif
|
|
|
|
lua_setfield(L,-2,"PRODUCTION");
|
2020-05-16 01:10:11 +02:00
|
|
|
lua_pop(L,1);
|
|
|
|
}
|