Page MenuHomeFreeBSD

D48390.diff
No OneTemporary

D48390.diff

diff --git a/libexec/flua/libfetch/fetch.3lua b/libexec/flua/libfetch/fetch.3lua
--- a/libexec/flua/libfetch/fetch.3lua
+++ b/libexec/flua/libfetch/fetch.3lua
@@ -18,11 +18,36 @@
.Pp
The module exports the following functions:
.Bl -tag -width Ds
-.It Fn fetch.get_url url outfile
+.It Fn fetch.get_url url outfile [headers]
Downloads the content from the specified
.Fa url
and saves it to
.Fa outfile .
+An optional
+.Fa headers
+table can be provided with HTTP headers as key-value pairs.
+Returns
+.Dv true
+on success, or
+.Dv nil
+and an error message on failure.
+.It Fn fetch.put_url url infile [headers]
+Uploads the content from
+.Fa infile
+to the specified
+.Fa url
+using HTTP PUT.
+Returns
+.Dv true
+on success, or
+.Dv nil
+and an error message on failure.
+.It Fn fetch.post_url url infile [headers]
+Uploads the content from
+.Fa infile
+to the specified
+.Fa url
+using HTTP POST.
Returns
.Dv true
on success, or
@@ -100,6 +125,29 @@
> f.get_url("https://wrong.host.badssl.com/", "/tmp/i")
SSL certificate subject doesn't match host wrong.host.badssl.com
nil Failed to read from URL: Authentication error
+
+> -- Upload a file using PUT
+> f.put_url("http://example.com/upload", "/tmp/data.txt")
+true
+
+> -- Submit form data using POST
+> f.post_url("http://example.com/submit", "/tmp/form.txt")
+true
+
+> -- GET with custom headers
+> headers = {
+> ["User-Agent"] = "MyApp/1.0",
+> ["Accept"] = "application/json"
+> }
+> f.get_url("http://api.example.com/data", "/tmp/data", headers)
+true
+
+> -- POST with content type header
+> headers = {
+> ["Content-Type"] = "application/json"
+> }
+> f.post_url("http://api.example.com/submit", "/tmp/data.json", headers)
+true
.Ed
.Sh SEE ALSO
.Xr fetch 3 ,
diff --git a/libexec/flua/libfetch/lfetch.c b/libexec/flua/libfetch/lfetch.c
--- a/libexec/flua/libfetch/lfetch.c
+++ b/libexec/flua/libfetch/lfetch.c
@@ -8,7 +8,9 @@
#include <errno.h>
#include <sys/param.h>
+#include <sys/stat.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <fetch.h>
@@ -17,11 +19,63 @@
#include "lfetch.h"
#define CHUNK_SIZE 4096
+#define MAX_HEADERS 32
/*
* Minimal implementation of libfetch
*/
+/* Helper function to build headers string from Lua table */
+static char *
+build_headers(lua_State *L, int index)
+{
+ char *headers = NULL;
+ size_t total_len = 0;
+ size_t header_count = 0;
+
+ if (!lua_istable(L, index)) {
+ return strdup("");
+ }
+
+ /* First pass: calculate total length needed */
+ lua_pushnil(L);
+ while (lua_next(L, index) != 0 && header_count < MAX_HEADERS) {
+ const char *key = lua_tostring(L, -2);
+ const char *value = lua_tostring(L, -1);
+ if (key && value) {
+ total_len += strlen(key) + strlen(value) + 4; /* key: value\n\0 */
+ header_count++;
+ }
+ lua_pop(L, 1);
+ }
+
+ if (total_len == 0) {
+ return strdup("");
+ }
+
+ headers = malloc(total_len);
+ if (headers == NULL) {
+ return NULL;
+ }
+ headers[0] = '\0';
+
+ /* Second pass: build headers string */
+ lua_pushnil(L);
+ while (lua_next(L, index) != 0) {
+ const char *key = lua_tostring(L, -2);
+ const char *value = lua_tostring(L, -1);
+ if (key && value) {
+ strcat(headers, key);
+ strcat(headers, ": ");
+ strcat(headers, value);
+ strcat(headers, "\n");
+ }
+ lua_pop(L, 1);
+ }
+
+ return headers;
+}
+
static int
lfetch_parse_url(lua_State *L)
{
@@ -66,6 +120,19 @@
struct url *u;
FILE *fetch;
FILE *file;
+ char *headers = NULL;
+
+ /* Get optional headers table */
+ if (lua_gettop(L) >= 3) {
+ headers = build_headers(L, 3);
+ if (headers == NULL) {
+ lua_pushnil(L);
+ lua_pushstring(L, "Failed to allocate memory for headers");
+ return 2;
+ }
+ } else {
+ headers = strdup("");
+ }
u = fetchParseURL(url);
if (u == NULL) {
@@ -83,7 +150,8 @@
return 2;
}
- fetch = fetchGet(u, "");
+ fetch = fetchGet(u, headers);
+ free(headers);
if (fetch == NULL) {
fclose(file);
fetchFreeURL(u);
@@ -113,10 +181,182 @@
return 1;
}
+static int
+lfetch_put_url(lua_State *L)
+{
+ const char *url = luaL_checkstring(L, 1);
+ const char *in = luaL_checkstring(L, 2);
+ struct url *u;
+ FILE *fetch;
+ FILE *file;
+ char *headers = NULL;
+ char *buf;
+ struct stat sb;
+ size_t size;
+
+ u = fetchParseURL(url);
+ if (u == NULL) {
+ lua_pushnil(L);
+ lua_pushstring(L, "Failed to parse URL");
+ return (2);
+ }
+
+ file = fopen(in, "r");
+ if (file == NULL) {
+ fetchFreeURL(u);
+ lua_pushnil(L);
+ lua_pushfstring(L, "Failed to open input file: %s", strerror(errno));
+ return 2;
+ }
+
+ if (fstat(fileno(file), &sb) == -1) {
+ fclose(file);
+ fetchFreeURL(u);
+ lua_pushnil(L);
+ lua_pushfstring(L, "Failed to stat input file: %s", strerror(errno));
+ return 2;
+ }
+
+ size = sb.st_size;
+ buf = malloc(size);
+ if (buf == NULL) {
+ fclose(file);
+ fetchFreeURL(u);
+ lua_pushnil(L);
+ lua_pushstring(L, "Failed to allocate memory for request");
+ return 2;
+ }
+
+ if (fread(buf, 1, size, file) != size) {
+ free(buf);
+ fclose(file);
+ fetchFreeURL(u);
+ lua_pushnil(L);
+ lua_pushstring(L, "Failed to read input file");
+ return 2;
+ }
+ fclose(file);
+
+ /* Get optional headers table */
+ if (lua_gettop(L) >= 3) {
+ headers = build_headers(L, 3);
+ if (headers == NULL) {
+ free(buf);
+ lua_pushnil(L);
+ lua_pushstring(L, "Failed to allocate memory for headers");
+ return 2;
+ }
+ } else {
+ headers = strdup("");
+ }
+
+ fetch = fetchReqHTTP(u, "PUT", buf, headers, "");
+ free(headers);
+ free(buf);
+ if (fetch == NULL) {
+ fetchFreeURL(u);
+ lua_pushnil(L);
+ lua_pushfstring(L, "Failed to PUT to URL: %s", strerror(errno));
+ return 2;
+ }
+
+ fclose(fetch);
+ fetchFreeURL(u);
+ lua_pushboolean(L, 1);
+ return 1;
+}
+
+static int
+lfetch_post_url(lua_State *L)
+{
+ const char *url = luaL_checkstring(L, 1);
+ const char *in = luaL_checkstring(L, 2);
+ struct url *u;
+ FILE *fetch;
+ FILE *file;
+ char *buf;
+ char *headers = NULL;
+ struct stat sb;
+ size_t size;
+
+ u = fetchParseURL(url);
+ if (u == NULL) {
+ lua_pushnil(L);
+ lua_pushstring(L, "Failed to parse URL");
+ return (2);
+ }
+
+ file = fopen(in, "r");
+ if (file == NULL) {
+ fetchFreeURL(u);
+ lua_pushnil(L);
+ lua_pushfstring(L, "Failed to open input file: %s", strerror(errno));
+ return 2;
+ }
+
+ if (fstat(fileno(file), &sb) == -1) {
+ fclose(file);
+ fetchFreeURL(u);
+ lua_pushnil(L);
+ lua_pushfstring(L, "Failed to stat input file: %s", strerror(errno));
+ return 2;
+ }
+
+ size = sb.st_size;
+ buf = malloc(size);
+ if (buf == NULL) {
+ fclose(file);
+ fetchFreeURL(u);
+ lua_pushnil(L);
+ lua_pushstring(L, "Failed to allocate memory for request");
+ return 2;
+ }
+
+ if (fread(buf, 1, size, file) != size) {
+ free(buf);
+ fclose(file);
+ fetchFreeURL(u);
+ lua_pushnil(L);
+ lua_pushstring(L, "Failed to read input file");
+ return 2;
+ }
+ fclose(file);
+
+ /* Get optional headers table */
+ if (lua_gettop(L) >= 3) {
+ headers = build_headers(L, 3);
+ if (headers == NULL) {
+ free(buf);
+ lua_pushnil(L);
+ lua_pushstring(L, "Failed to allocate memory for headers");
+ return 2;
+ }
+ } else {
+ headers = strdup("");
+ }
+
+ fetch = fetchReqHTTP(u, "POST", buf, headers, "");
+ free(headers);
+ free(buf);
+ if (fetch == NULL) {
+ fetchFreeURL(u);
+ lua_pushnil(L);
+ lua_pushfstring(L, "Failed to POST to URL: %s", strerror(errno));
+ return 2;
+ }
+
+ fclose(fetch);
+ fetchFreeURL(u);
+ lua_pushboolean(L, 1);
+ return 1;
+}
+
static const struct
luaL_Reg fetchlib[] = {
{"get_url", lfetch_get_url},
{"parse_url", lfetch_parse_url},
+ {"put_url", lfetch_put_url},
+ {"post_url", lfetch_post_url},
{NULL, NULL}
};

File Metadata

Mime Type
text/plain
Expires
Wed, Mar 4, 2:23 AM (6 h, 20 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29201431
Default Alt Text
D48390.diff (7 KB)

Event Timeline