Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F146487462
D48390.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
7 KB
Referenced Files
None
Subscribers
None
D48390.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D48390: flua: add PUT, POST, and header support to lua fetch
Attached
Detach File
Event Timeline
Log In to Comment