website
git clone https://git.pyrossh.dev/website
木 Personal website of pyrossh. Built with astrojs, shiki, vite.
8316688
— pyrossh
2026-07-14T13:35:03+05:30
feat: add infrastructure modules for merjs port
- build.zig +120 -0
- build.zig.zon +26 -0
- src/config.zig +67 -0
- src/lib.zig +10 -0
- src/mercss_jit.zig +30 -0
- src/s3.zig +122 -0
build.zig
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
const std = @import("std");
|
|
2
|
+
|
|
3
|
+
pub fn build(b: *std.Build) void {
|
|
4
|
+
const target = b.standardTargetOptions(.{});
|
|
5
|
+
const optimize = b.standardOptimizeOption(.{});
|
|
6
|
+
|
|
7
|
+
const merjs_dep = b.dependency("merjs", .{});
|
|
8
|
+
const mer_mod = merjs_dep.module("mer");
|
|
9
|
+
|
|
10
|
+
const config_mod = b.createModule(.{ .root_source_file = b.path("src/config.zig") });
|
|
11
|
+
const s3_mod = b.createModule(.{ .root_source_file = b.path("src/s3.zig") });
|
|
12
|
+
const lib_mod = b.createModule(.{ .root_source_file = b.path("src/lib.zig") });
|
|
13
|
+
lib_mod.addImport("config", config_mod);
|
|
14
|
+
lib_mod.addImport("s3", s3_mod);
|
|
15
|
+
|
|
16
|
+
const main_mod = b.createModule(.{
|
|
17
|
+
.root_source_file = b.path("src/main.zig"),
|
|
18
|
+
.target = target,
|
|
19
|
+
.optimize = optimize,
|
|
20
|
+
.strip = if (optimize != .Debug) true else null,
|
|
21
|
+
});
|
|
22
|
+
main_mod.addImport("mer", mer_mod);
|
|
23
|
+
main_mod.addImport("config", config_mod);
|
|
24
|
+
main_mod.addImport("s3", s3_mod);
|
|
25
|
+
main_mod.addImport("lib", lib_mod);
|
|
26
|
+
addDirModules(b, main_mod, mer_mod, config_mod, s3_mod, lib_mod, "app");
|
|
27
|
+
addDirModules(b, main_mod, mer_mod, config_mod, s3_mod, lib_mod, "api");
|
|
28
|
+
addRoutesModule(b, main_mod, mer_mod, config_mod, s3_mod, lib_mod);
|
|
29
|
+
|
|
30
|
+
const exe = b.addExecutable(.{ .name = "app", .root_module = main_mod });
|
|
31
|
+
b.installArtifact(exe);
|
|
32
|
+
|
|
33
|
+
// zig build codegen
|
|
34
|
+
const codegen_mod = b.createModule(.{
|
|
35
|
+
.root_source_file = b.path("tools/codegen.zig"),
|
|
36
|
+
.target = b.graph.host,
|
|
37
|
+
.optimize = .Debug,
|
|
38
|
+
});
|
|
39
|
+
codegen_mod.addImport("runtime", merjs_dep.module("runtime"));
|
|
40
|
+
const mercss_mod = b.createModule(.{ .root_source_file = b.path("src/mercss_jit.zig") });
|
|
41
|
+
codegen_mod.addImport("mercss_jit", mercss_mod);
|
|
42
|
+
const codegen_exe = b.addExecutable(.{
|
|
43
|
+
.name = "codegen",
|
|
44
|
+
.root_module = codegen_mod,
|
|
45
|
+
});
|
|
46
|
+
const run_codegen = b.addRunArtifact(codegen_exe);
|
|
47
|
+
run_codegen.setCwd(b.path("."));
|
|
48
|
+
b.step("codegen", "Regenerate src/generated/routes.zig").dependOn(&run_codegen.step);
|
|
49
|
+
|
|
50
|
+
// Auto-run codegen before compiling (fresh clones just work).
|
|
51
|
+
exe.step.dependOn(&run_codegen.step);
|
|
52
|
+
|
|
53
|
+
// zig build serve
|
|
54
|
+
const run_exe = b.addRunArtifact(exe);
|
|
55
|
+
run_exe.step.dependOn(b.getInstallStep());
|
|
56
|
+
if (b.args) |args| run_exe.addArgs(args);
|
|
57
|
+
b.step("serve", "Start the dev server").dependOn(&run_exe.step);
|
|
58
|
+
|
|
59
|
+
// zig build test
|
|
60
|
+
const test_mod = b.createModule(.{
|
|
61
|
+
.root_source_file = b.path("src/main.zig"),
|
|
62
|
+
.target = target,
|
|
63
|
+
.optimize = optimize,
|
|
64
|
+
});
|
|
65
|
+
test_mod.addImport("mer", mer_mod);
|
|
66
|
+
test_mod.addImport("config", config_mod);
|
|
67
|
+
test_mod.addImport("s3", s3_mod);
|
|
68
|
+
test_mod.addImport("lib", lib_mod);
|
|
69
|
+
addDirModules(b, test_mod, mer_mod, config_mod, s3_mod, lib_mod, "app");
|
|
70
|
+
addDirModules(b, test_mod, mer_mod, config_mod, s3_mod, lib_mod, "api");
|
|
71
|
+
addRoutesModule(b, test_mod, mer_mod, config_mod, s3_mod, lib_mod);
|
|
72
|
+
const run_tests = b.addRunArtifact(b.addTest(.{ .root_module = test_mod }));
|
|
73
|
+
run_tests.step.dependOn(&run_codegen.step);
|
|
74
|
+
b.step("test", "Compile the starter app").dependOn(&run_tests.step);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
fn addRoutesModule(b: *std.Build, mod: *std.Build.Module, mer_mod: *std.Build.Module, config_mod: *std.Build.Module, s3_mod: *std.Build.Module, lib_mod: *std.Build.Module) void {
|
|
78
|
+
const routes_mod = b.createModule(.{
|
|
79
|
+
.root_source_file = b.path("src/generated/routes.zig"),
|
|
80
|
+
});
|
|
81
|
+
routes_mod.addImport("mer", mer_mod);
|
|
82
|
+
routes_mod.addImport("config", config_mod);
|
|
83
|
+
routes_mod.addImport("s3", s3_mod);
|
|
84
|
+
routes_mod.addImport("lib", lib_mod);
|
|
85
|
+
addDirModules(b, routes_mod, mer_mod, config_mod, s3_mod, lib_mod, "app");
|
|
86
|
+
addDirModules(b, routes_mod, mer_mod, config_mod, s3_mod, lib_mod, "api");
|
|
87
|
+
mod.addImport("routes", routes_mod);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
fn addDirModules(b: *std.Build, mod: *std.Build.Module, mer_mod: *std.Build.Module, config_mod: *std.Build.Module, s3_mod: *std.Build.Module, lib_mod: *std.Build.Module, dir: []const u8) void {
|
|
91
|
+
const layout_path = b.fmt("{s}/layout.zig", .{dir});
|
|
92
|
+
const layout_mod: ?*std.Build.Module = blk: {
|
|
93
|
+
std.Io.Dir.cwd().access(b.graph.io, layout_path, .{}) catch break :blk null;
|
|
94
|
+
const m = b.createModule(.{ .root_source_file = b.path(layout_path) });
|
|
95
|
+
m.addImport("mer", mer_mod);
|
|
96
|
+
m.addImport("config", config_mod);
|
|
97
|
+
m.addImport("s3", s3_mod);
|
|
98
|
+
m.addImport("lib", lib_mod);
|
|
99
|
+
mod.addImport(b.fmt("{s}/layout", .{dir}), m);
|
|
100
|
+
break :blk m;
|
|
101
|
+
};
|
|
102
|
+
var d = std.Io.Dir.cwd().openDir(b.graph.io, dir, .{ .iterate = true }) catch return;
|
|
103
|
+
defer d.close(b.graph.io);
|
|
104
|
+
var walker = d.walk(b.allocator) catch return;
|
|
105
|
+
defer walker.deinit();
|
|
106
|
+
while (walker.next(b.graph.io) catch null) |entry| {
|
|
107
|
+
if (entry.kind != .file) continue;
|
|
108
|
+
if (!std.mem.endsWith(u8, entry.path, ".zig")) continue;
|
|
109
|
+
if (std.mem.eql(u8, entry.path, "layout.zig")) continue;
|
|
110
|
+
const file_path = b.fmt("{s}/{s}", .{ dir, entry.path });
|
|
111
|
+
const import_name = b.fmt("{s}/{s}", .{ dir, entry.path[0 .. entry.path.len - 4] });
|
|
112
|
+
const route_mod = b.createModule(.{ .root_source_file = b.path(file_path) });
|
|
113
|
+
route_mod.addImport("mer", mer_mod);
|
|
114
|
+
route_mod.addImport("config", config_mod);
|
|
115
|
+
route_mod.addImport("s3", s3_mod);
|
|
116
|
+
route_mod.addImport("lib", lib_mod);
|
|
117
|
+
if (layout_mod) |lm| route_mod.addImport(b.fmt("{s}/layout", .{dir}), lm);
|
|
118
|
+
mod.addImport(import_name, route_mod);
|
|
119
|
+
}
|
|
120
|
+
}
|
build.zig.zon
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
.{
|
|
2
|
+
.name = .website,
|
|
3
|
+
.version = "0.1.0",
|
|
4
|
+
.minimum_zig_version = "0.16.0",
|
|
5
|
+
.fingerprint = 0x476f5de705d5dc2b,
|
|
6
|
+
.dependencies = .{
|
|
7
|
+
.merjs = .{
|
|
8
|
+
.url = "git+https://github.com/justrach/merjs.git",
|
|
9
|
+
.hash = "merjs-0.2.5-qL9LkovAYAB6QqPjk8p53hM_A9bJA10slWVPpmu77Thc",
|
|
10
|
+
},
|
|
11
|
+
.zmd = .{
|
|
12
|
+
.url = "git+https://github.com/jetzig-framework/zmd.git",
|
|
13
|
+
.hash = "zmd-0.2.0-H8YV7VfEAACoEBk4Yy0feU3HmoIE-7oqjuiGadj3t1mv",
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
.paths = .{
|
|
17
|
+
"build.zig",
|
|
18
|
+
"build.zig.zon",
|
|
19
|
+
"src",
|
|
20
|
+
"app",
|
|
21
|
+
"api",
|
|
22
|
+
"public",
|
|
23
|
+
"content",
|
|
24
|
+
"assets",
|
|
25
|
+
},
|
|
26
|
+
}
|
src/config.zig
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
const std = @import("std");
|
|
2
|
+
|
|
3
|
+
pub const site_title = "pyrossh";
|
|
4
|
+
pub const site_description = "Welcome to my website!";
|
|
5
|
+
pub const site_url = "https://pyrossh.dev";
|
|
6
|
+
|
|
7
|
+
pub const Repo = struct {
|
|
8
|
+
title: []const u8,
|
|
9
|
+
description: []const u8,
|
|
10
|
+
tags: []const []const u8,
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
pub const Tool = struct {
|
|
14
|
+
name: []const u8,
|
|
15
|
+
link: []const u8,
|
|
16
|
+
image: ?[]const u8,
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
pub const NavItem = struct {
|
|
20
|
+
href: []const u8,
|
|
21
|
+
label: []const u8,
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
pub const repos = &[_]Repo{
|
|
25
|
+
.{ .title = "rust-embed", .description = "rust macro which loads files into the rust binary at compile time during release and loads the file from the fs during dev.", .tags = &[_][]const u8{ "rust", "proc-macro", "http" } },
|
|
26
|
+
.{ .title = "website", .description = "Personal website of pyrossh", .tags = &[_][]const u8{ "astro", "js", "html", "css" } },
|
|
27
|
+
.{ .title = "plum", .description = "A statically typed, imperative programming language inspired by rust, python", .tags = &[_][]const u8{ "treesitter", "compiler", "wasm" } },
|
|
28
|
+
.{ .title = "edge-city", .description = "edge-city is a next level meta-framework for react that runs only on edge runtimes", .tags = &[_][]const u8{ "react", "js", "ssr" } },
|
|
29
|
+
.{ .title = "gromer", .description = "gromer is a framework and cli to build multipage web apps in golang using htmx and alpinejs.", .tags = &[_][]const u8{ "golang", "htmx", "ssr" } },
|
|
30
|
+
.{ .title = "atoms-element", .description = "A simple web component library for defining your custom elements.", .tags = &[_][]const u8{ "js" } },
|
|
31
|
+
.{ .title = "atoms-state", .description = "Simple State management for react", .tags = &[_][]const u8{ "js", "react", "flux" } },
|
|
32
|
+
.{ .title = "remote-monitor", .description = "Remote Monitoring and Control using GSM-SMS", .tags = &[_][]const u8{ "c++", "teensy", "arduino" } },
|
|
33
|
+
.{ .title = "only-bible-app", .description = "The only bible app you will ever need. No ads. No in-app purchases. No distractions.", .tags = &[_][]const u8{ "kotlin", "android", "ios" } },
|
|
34
|
+
.{ .title = "gdx-studio", .description = "An IDE for creating Games using libgdx and Java", .tags = &[_][]const u8{ "libgdx", "java", "desktop" } },
|
|
35
|
+
.{ .title = "rp2350", .description = "code to drive rp2350", .tags = &[_][]const u8{ "zig", "raspberry-pi" } },
|
|
36
|
+
.{ .title = "config", .description = "Common configuration", .tags = &[_][]const u8{ "brew", "nushell" } },
|
|
37
|
+
.{ .title = "sabel-ide", .description = "sabel-ide", .tags = &[_][]const u8{ "python", "qt" } },
|
|
38
|
+
.{ .title = "tide-jsx", .description = "Tide + JSX", .tags = &[_][]const u8{ "rust", "proc-macro", "jsx" } },
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
pub const tools = &[_]Tool{
|
|
42
|
+
.{ .name = "Stats", .link = "https://github.com/exelban/stats", .image = "/assets/logos/stats.png" },
|
|
43
|
+
.{ .name = "Void", .link = "https://github.com/voideditor/void", .image = "/assets/logos/void.png" },
|
|
44
|
+
.{ .name = "Helix", .link = "https://github.com/helix-editor/helix", .image = "/assets/logos/helix.png" },
|
|
45
|
+
.{ .name = "Nushell", .link = "https://github.com/nushell/nushell", .image = "/assets/logos/nu.png" },
|
|
46
|
+
.{ .name = "Ghostty", .link = "https://github.com/ghostty-org/ghostty", .image = "/assets/logos/ghostty.png" },
|
|
47
|
+
.{ .name = "Zellij", .link = "https://zellij.dev/", .image = "/assets/logos/zellij.png" },
|
|
48
|
+
.{ .name = "Zen", .link = "https://github.com/zen-browser/desktop", .image = "/assets/logos/zen.svg" },
|
|
49
|
+
.{ .name = "Bruno", .link = "https://github.com/usebruno/bruno", .image = "/assets/logos/bruno.png" },
|
|
50
|
+
.{ .name = "Secretive", .link = "https://github.com/maxgoedjen/secretive", .image = null },
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
pub const nav_items = &[_]NavItem{
|
|
54
|
+
.{ .href = "/cv", .label = "cv" },
|
|
55
|
+
.{ .href = "/posts", .label = "posts" },
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
pub fn getRepo(id: []const u8) ?Repo {
|
|
59
|
+
for (repos) |repo| {
|
|
60
|
+
if (std.mem.eql(u8, repo.title, id)) return repo;
|
|
61
|
+
}
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
pub fn getRepos() []const Repo {
|
|
66
|
+
return repos;
|
|
67
|
+
}
|
src/lib.zig
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
pub const config = @import("config");
|
|
2
|
+
pub const s3 = @import("s3");
|
|
3
|
+
pub const content = @import("content.zig");
|
|
4
|
+
pub const frontmatter = @import("frontmatter.zig");
|
|
5
|
+
pub const markdown = @import("markdown.zig");
|
|
6
|
+
pub const files = @import("files.zig");
|
|
7
|
+
pub const gitBug = @import("gitBug.zig");
|
|
8
|
+
pub const gitReader = @import("gitReader.zig");
|
|
9
|
+
pub const diff = @import("diff.zig");
|
|
10
|
+
pub const repoContent = @import("repoContent.zig");
|
src/mercss_jit.zig
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// Stub — provide real implementation when needed.
|
|
2
|
+
const std = @import("std");
|
|
3
|
+
|
|
4
|
+
pub const DesignSystem = struct {
|
|
5
|
+
allocator: std.mem.Allocator,
|
|
6
|
+
|
|
7
|
+
pub fn init(allocator: std.mem.Allocator) DesignSystem {
|
|
8
|
+
return .{ .allocator = allocator };
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
pub fn deinit(self: *DesignSystem) void {
|
|
12
|
+
_ = self;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
pub fn loadDefaults(self: *DesignSystem) !void {
|
|
16
|
+
_ = self;
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
pub fn compile(allocator: std.mem.Allocator, ds: *DesignSystem, candidates: []const []const u8) ![]const u8 {
|
|
21
|
+
_ = ds;
|
|
22
|
+
_ = candidates;
|
|
23
|
+
return allocator.dupe(u8, "/* mercss stub */");
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
pub fn scan(content: []const u8, allocator: std.mem.Allocator, candidates: *std.ArrayList([]const u8)) !void {
|
|
27
|
+
_ = content;
|
|
28
|
+
_ = allocator;
|
|
29
|
+
_ = candidates;
|
|
30
|
+
}
|
src/s3.zig
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
const std = @import("std");
|
|
2
|
+
const mer = @import("mer");
|
|
3
|
+
|
|
4
|
+
const S3 = @This();
|
|
5
|
+
|
|
6
|
+
allocator: std.mem.Allocator,
|
|
7
|
+
endpoint: []const u8,
|
|
8
|
+
region: []const u8,
|
|
9
|
+
access_key: []const u8,
|
|
10
|
+
secret_key: []const u8,
|
|
11
|
+
|
|
12
|
+
pub fn init(allocator: std.mem.Allocator) S3 {
|
|
13
|
+
return .{
|
|
14
|
+
.allocator = allocator,
|
|
15
|
+
.endpoint = mer.env("S3_ENDPOINT") orelse "",
|
|
16
|
+
.region = mer.env("S3_REGION") orelse "auto",
|
|
17
|
+
.access_key = mer.env("S3_ACCESS_KEY_ID") orelse "",
|
|
18
|
+
.secret_key = mer.env("S3_SECRET_ACCESS_KEY") orelse "",
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
pub fn getObject(self: S3, key: []const u8) ?[]const u8 {
|
|
23
|
+
const url = std.fmt.allocPrint(self.allocator, "{s}/{s}", .{ self.endpoint, key }) catch return null;
|
|
24
|
+
defer self.allocator.free(url);
|
|
25
|
+
|
|
26
|
+
const headers = self.signedHeaders("GET", key, "", 0);
|
|
27
|
+
defer self.allocator.free(headers);
|
|
28
|
+
|
|
29
|
+
var hdrs = [_]std.http.Header{.{
|
|
30
|
+
.name = "Authorization",
|
|
31
|
+
.value = headers,
|
|
32
|
+
}};
|
|
33
|
+
|
|
34
|
+
var resp = mer.fetch(self.allocator, .{
|
|
35
|
+
.url = url,
|
|
36
|
+
.method = .GET,
|
|
37
|
+
.headers = &hdrs,
|
|
38
|
+
}) catch return null;
|
|
39
|
+
defer resp.deinit(self.allocator);
|
|
40
|
+
|
|
41
|
+
if (resp.status != .ok and resp.status != .no_content) return null;
|
|
42
|
+
return resp.body;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
pub fn getObjectArrayBuffer(self: S3, key: []const u8) ?[]u8 {
|
|
46
|
+
const url = std.fmt.allocPrint(self.allocator, "{s}/{s}", .{ self.endpoint, key }) catch return null;
|
|
47
|
+
defer self.allocator.free(url);
|
|
48
|
+
|
|
49
|
+
const headers = self.signedHeaders("GET", key, "", 0);
|
|
50
|
+
defer self.allocator.free(headers);
|
|
51
|
+
|
|
52
|
+
var hdrs = [_]std.http.Header{.{
|
|
53
|
+
.name = "Authorization",
|
|
54
|
+
.value = headers,
|
|
55
|
+
}};
|
|
56
|
+
|
|
57
|
+
var resp = mer.fetch(self.allocator, .{
|
|
58
|
+
.url = url,
|
|
59
|
+
.method = .GET,
|
|
60
|
+
.headers = &hdrs,
|
|
61
|
+
}) catch return null;
|
|
62
|
+
defer resp.deinit(self.allocator);
|
|
63
|
+
|
|
64
|
+
if (resp.status != .ok and resp.status != .no_content) return null;
|
|
65
|
+
return self.allocator.dupe(u8, resp.body) catch null;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
pub fn putObject(self: S3, key: []const u8, data: []const u8, content_type: []const u8) !void {
|
|
69
|
+
const url = try std.fmt.allocPrint(self.allocator, "{s}/{s}", .{ self.endpoint, key });
|
|
70
|
+
defer self.allocator.free(url);
|
|
71
|
+
|
|
72
|
+
const auth = self.signedHeaders("PUT", key, content_type, data.len);
|
|
73
|
+
defer self.allocator.free(auth);
|
|
74
|
+
|
|
75
|
+
var hdrs = [_]std.http.Header{
|
|
76
|
+
.{ .name = "Authorization", .value = auth },
|
|
77
|
+
.{ .name = "Content-Type", .value = content_type },
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
var resp = try mer.fetch(self.allocator, .{
|
|
81
|
+
.url = url,
|
|
82
|
+
.method = .PUT,
|
|
83
|
+
.body = data,
|
|
84
|
+
.headers = &hdrs,
|
|
85
|
+
});
|
|
86
|
+
defer resp.deinit(self.allocator);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
pub fn listObjects(self: S3, prefix: []const u8) ?[]const u8 {
|
|
90
|
+
const url = std.fmt.allocPrint(self.allocator, "{s}/?prefix={s}&list-type=2", .{ self.endpoint, prefix }) catch return null;
|
|
91
|
+
defer self.allocator.free(url);
|
|
92
|
+
|
|
93
|
+
const auth = self.signedHeaders("GET", "?prefix=" ++ prefix ++ "&list-type=2", "", 0);
|
|
94
|
+
defer self.allocator.free(auth);
|
|
95
|
+
|
|
96
|
+
var hdrs = [_]std.http.Header{.{
|
|
97
|
+
.name = "Authorization",
|
|
98
|
+
.value = auth,
|
|
99
|
+
}};
|
|
100
|
+
|
|
101
|
+
var resp = mer.fetch(self.allocator, .{
|
|
102
|
+
.url = url,
|
|
103
|
+
.method = .GET,
|
|
104
|
+
.headers = &hdrs,
|
|
105
|
+
}) catch return null;
|
|
106
|
+
defer resp.deinit(self.allocator);
|
|
107
|
+
|
|
108
|
+
if (resp.status != .ok) return null;
|
|
109
|
+
return self.allocator.dupe(u8, resp.body) catch null;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/// Simplified AWS SigV4 signing. For production, use a proper implementation.
|
|
113
|
+
fn signedHeaders(self: S3, method: []const u8, key: []const u8, content_type: []const u8, body_len: usize) []u8 {
|
|
114
|
+
_ = method;
|
|
115
|
+
_ = key;
|
|
116
|
+
_ = content_type;
|
|
117
|
+
_ = body_len;
|
|
118
|
+
// Simplified signing — for R2 with proper IAM, this may need full SigV4.
|
|
119
|
+
// R2 supports AWS SigV4-compatible signing.
|
|
120
|
+
// For now, returns a minimal auth header.
|
|
121
|
+
return std.fmt.allocPrint(self.allocator, "Bearer {s}", .{self.secret_key}) catch "";
|
|
122
|
+
}
|