102 lines
2.0 KiB
C
102 lines
2.0 KiB
C
#include <lua.h>
|
|
#include <lualib.h>
|
|
#include <lauxlib.h>
|
|
#include <curl/curl.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "lib.h"
|
|
|
|
typedef struct {
|
|
char **segments;
|
|
size_t *sizes;
|
|
size_t n, cap;
|
|
} http_body_buff_t;
|
|
|
|
static size_t body_writer(char *ptr, size_t _, size_t size, void *pbuff) {
|
|
http_body_buff_t *buff = pbuff;
|
|
|
|
size_t new_cap = buff->cap;
|
|
while (buff->n >= new_cap) {
|
|
new_cap *= 2;
|
|
}
|
|
|
|
if (new_cap > buff->cap) {
|
|
buff->segments = realloc(buff->segments, sizeof(*buff->segments) * new_cap);
|
|
buff->sizes = realloc(buff->sizes, sizeof(*buff->sizes) * new_cap);
|
|
buff->cap = new_cap;
|
|
}
|
|
|
|
buff->segments[buff->n] = malloc(size);
|
|
memcpy(buff->segments[buff->n], ptr, size);
|
|
buff->sizes[buff->n] = size;
|
|
buff->n++;
|
|
|
|
|
|
return size;
|
|
}
|
|
|
|
static char *body_compress(http_body_buff_t buff, size_t *psize) {
|
|
size_t size = 0;
|
|
|
|
for (size_t i = 0; i < buff.n; i++) {
|
|
size += buff.sizes[i];
|
|
}
|
|
|
|
char *res = malloc(size + 1);
|
|
res[size] = 0;
|
|
|
|
size_t offset = 0;
|
|
|
|
for (size_t i = 0; i < buff.n; i++) {
|
|
memcpy(res + offset, buff.segments[i], buff.sizes[i]);
|
|
offset += buff.sizes[i];
|
|
free(buff.segments[i]);
|
|
}
|
|
|
|
free(buff.segments);
|
|
free(buff.sizes);
|
|
|
|
*psize = size;
|
|
return res;
|
|
}
|
|
|
|
static int lib_http_get(lua_State *ctx) {
|
|
const char *url = luaL_checkstring(ctx, 1);
|
|
|
|
http_body_buff_t buff = {
|
|
.segments = malloc(sizeof *buff.segments * 16),
|
|
.sizes = malloc(sizeof *buff.sizes * 16),
|
|
.n = 0,
|
|
.cap = 16,
|
|
};
|
|
|
|
CURL *curl = curl_easy_init();
|
|
curl_easy_setopt(curl, CURLOPT_URL, url);
|
|
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, body_writer);
|
|
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buff);
|
|
|
|
CURLcode code = curl_easy_perform(curl);
|
|
curl_easy_cleanup(curl);
|
|
|
|
if (code != CURLE_OK) {
|
|
return luaL_error(ctx, "HTTP GET failed: %s", curl_easy_strerror(code));
|
|
}
|
|
|
|
size_t size;
|
|
char *body = body_compress(buff, &size);
|
|
lua_pushlstring(ctx, body, size);
|
|
free(body);
|
|
|
|
return 1;
|
|
}
|
|
|
|
int http_open_lib(lua_State *ctx) {
|
|
luaL_newlib(ctx, ((luaL_Reg[]) {
|
|
{ "get", lib_http_get },
|
|
{ NULL, NULL },
|
|
}));
|
|
|
|
return 1;
|
|
}
|