atproto pds in zig pds.zat.dev
pds atproto
24

Configure Feed

Select the types of activity you want to include in your feed.

speed up configured appview proxy

zzstoatzz (Jun 3, 2026, 2:29 PM -0500) e588554c 495e92b2

+95
+33
src/atproto/proxy.zig
··· 1 1 const std = @import("std"); 2 2 const auth = @import("../auth/tokens.zig"); 3 + const config = @import("../core/config.zig"); 3 4 const log = @import("../core/log.zig"); 4 5 const http_api = @import("../http/api.zig"); 5 6 const scopes = @import("../internal/scopes.zig"); ··· 128 129 if (hash == 0 or hash + 1 >= proxy_to.len) return error.InvalidProxyHeader; 129 130 const did = proxy_to[0..hash]; 130 131 const service_id = proxy_to[hash + 1 ..]; 132 + if (try configuredProxyService(allocator, did, service_id)) |service| return service; 131 133 const did_doc = try fetchDidDocument(allocator, did); 132 134 const service_ref = try std.fmt.allocPrint(allocator, "#{s}", .{service_id}); 133 135 const endpoint = serviceEndpoint(did_doc.value, service_ref) orelse return error.ServiceNotFound; ··· 135 137 .did = try allocator.dupe(u8, did), 136 138 .service_id = try allocator.dupe(u8, service_id), 137 139 .endpoint = try allocator.dupe(u8, std.mem.trim(u8, endpoint, "/")), 140 + }; 141 + } 142 + 143 + fn configuredProxyService(allocator: std.mem.Allocator, did: []const u8, service_id: []const u8) !?ProxyService { 144 + if (!std.mem.eql(u8, service_id, config.proxyServiceId())) return null; 145 + if (!std.mem.eql(u8, did, config.proxyServiceDid())) return null; 146 + return .{ 147 + .did = try allocator.dupe(u8, did), 148 + .service_id = try allocator.dupe(u8, service_id), 149 + .endpoint = try allocator.dupe(u8, config.proxyServiceUrl()), 138 150 }; 139 151 } 140 152 ··· 308 320 try std.testing.expect(!isProtectedMethod("com.atproto.repo.getRecord")); 309 321 try std.testing.expect(!isProtectedMethod("com.atproto.repo.listRecords")); 310 322 } 323 + 324 + test "configured proxy service skips did resolution" { 325 + const before_did = config.proxyServiceDid(); 326 + const before_id = config.proxyServiceId(); 327 + const before_url = config.proxyServiceUrl(); 328 + defer config.setProxyServiceDid(before_did); 329 + defer config.setProxyServiceId(before_id); 330 + defer config.setProxyServiceUrl(before_url); 331 + config.setProxyServiceDid("did:web:api.bsky.app"); 332 + config.setProxyServiceId("bsky_appview"); 333 + config.setProxyServiceUrl("https://api.bsky.app"); 334 + 335 + const service = (try resolveProxyService(std.testing.allocator, "did:web:api.bsky.app#bsky_appview")); 336 + defer std.testing.allocator.free(service.did); 337 + defer std.testing.allocator.free(service.service_id); 338 + defer std.testing.allocator.free(service.endpoint); 339 + 340 + try std.testing.expectEqualStrings("did:web:api.bsky.app", service.did); 341 + try std.testing.expectEqualStrings("bsky_appview", service.service_id); 342 + try std.testing.expectEqualStrings("https://api.bsky.app", service.endpoint); 343 + }
+34
src/core/config.zig
··· 11 11 var blobstore_path_value: []const u8 = "dev/blobs"; 12 12 var handle_domains_value: []const u8 = ".test"; 13 13 var crawlers_value: []const u8 = "https://bsky.network,https://vsky.network"; 14 + var proxy_service_did_value: []const u8 = "did:web:api.bsky.app"; 15 + var proxy_service_id_value: []const u8 = "bsky_appview"; 16 + var proxy_service_url_value: []const u8 = "https://api.bsky.app"; 14 17 var jwt_secret_value: []const u8 = "zds-local-development-jwt-secret-change-me"; 15 18 var admin_token_value: ?[]const u8 = null; 16 19 var invite_required_value: bool = false; ··· 66 69 return crawlers_value; 67 70 } 68 71 72 + pub fn proxyServiceDid() []const u8 { 73 + return proxy_service_did_value; 74 + } 75 + 76 + pub fn proxyServiceId() []const u8 { 77 + return proxy_service_id_value; 78 + } 79 + 80 + pub fn proxyServiceUrl() []const u8 { 81 + return proxy_service_url_value; 82 + } 83 + 69 84 pub fn jwtSecret() []const u8 { 70 85 return jwt_secret_value; 71 86 } ··· 130 145 crawlers_value = value; 131 146 } 132 147 148 + pub fn setProxyServiceDid(value: []const u8) void { 149 + proxy_service_did_value = value; 150 + } 151 + 152 + pub fn setProxyServiceId(value: []const u8) void { 153 + proxy_service_id_value = value; 154 + } 155 + 156 + pub fn setProxyServiceUrl(value: []const u8) void { 157 + proxy_service_url_value = trimTrailingSlash(value); 158 + } 159 + 133 160 pub fn setJwtSecret(value: []const u8) void { 134 161 jwt_secret_value = value; 135 162 } ··· 165 192 setPublicUrl("https://example.com/"); 166 193 try std.testing.expectEqualStrings("https://example.com", publicUrl()); 167 194 } 195 + 196 + test "trims configured proxy service URL slash" { 197 + const before = proxyServiceUrl(); 198 + defer setProxyServiceUrl(before); 199 + setProxyServiceUrl("https://api.example.com/"); 200 + try std.testing.expectEqualStrings("https://api.example.com", proxyServiceUrl()); 201 + }
+25
src/internal/cli.zig
··· 15 15 blobstore_path: ?[]const u8 = null, 16 16 handle_domains: ?[]const u8 = null, 17 17 crawlers: ?[]const u8 = null, 18 + proxy_service_did: ?[]const u8 = null, 19 + proxy_service_id: ?[]const u8 = null, 20 + proxy_service_url: ?[]const u8 = null, 18 21 jwt_secret: ?[]const u8 = null, 19 22 admin_token: ?[]const u8 = null, 20 23 invite_required: bool = false, ··· 27 30 MissingBlobUploadLimit, 28 31 MissingBlobstorePath, 29 32 MissingCrawlers, 33 + MissingProxyServiceDid, 34 + MissingProxyServiceId, 35 + MissingProxyServiceUrl, 30 36 MissingDatabasePath, 31 37 MissingEmailFrom, 32 38 MissingHandleDomains, ··· 58 64 .blobstore_path = env("ZDS_BLOBSTORE_PATH"), 59 65 .handle_domains = env("ZDS_HANDLE_DOMAINS"), 60 66 .crawlers = env("ZDS_CRAWLERS"), 67 + .proxy_service_did = env("ZDS_PROXY_SERVICE_DID"), 68 + .proxy_service_id = env("ZDS_PROXY_SERVICE_ID"), 69 + .proxy_service_url = env("ZDS_PROXY_SERVICE_URL"), 61 70 .jwt_secret = env("ZDS_JWT_SECRET"), 62 71 .admin_token = env("ZDS_ADMIN_TOKEN"), 63 72 .invite_required = envBool("ZDS_INVITE_REQUIRED"), ··· 83 92 \\ [--plc-rotation-key KEY] [--recovery-did-key DIDKEY] 84 93 \\ [--blob-upload-limit BYTES] [--blobstore-path PATH] 85 94 \\ [--handle-domains DOMAINS] [--crawlers URLS] [--jwt-secret SECRET] 95 + \\ [--proxy-service-did DID] [--proxy-service-id ID] [--proxy-service-url URL] 86 96 \\ [--admin-token TOKEN] [--invite-required] 87 97 \\ [--log-level error|info|debug] [--debug] 88 98 \\ ··· 158 168 options.crawlers = args.next() orelse return error.MissingCrawlers; 159 169 return true; 160 170 } 171 + if (std.mem.eql(u8, arg, "--proxy-service-did")) { 172 + options.proxy_service_did = args.next() orelse return error.MissingProxyServiceDid; 173 + return true; 174 + } 175 + if (std.mem.eql(u8, arg, "--proxy-service-id")) { 176 + options.proxy_service_id = args.next() orelse return error.MissingProxyServiceId; 177 + return true; 178 + } 179 + if (std.mem.eql(u8, arg, "--proxy-service-url")) { 180 + options.proxy_service_url = args.next() orelse return error.MissingProxyServiceUrl; 181 + return true; 182 + } 161 183 if (std.mem.eql(u8, arg, "--jwt-secret")) { 162 184 options.jwt_secret = args.next() orelse return error.MissingJwtSecret; 163 185 return true; ··· 209 231 .{ .flag = "--blobstore-path=", .field = "blobstore_path" }, 210 232 .{ .flag = "--handle-domains=", .field = "handle_domains" }, 211 233 .{ .flag = "--crawlers=", .field = "crawlers" }, 234 + .{ .flag = "--proxy-service-did=", .field = "proxy_service_did" }, 235 + .{ .flag = "--proxy-service-id=", .field = "proxy_service_id" }, 236 + .{ .flag = "--proxy-service-url=", .field = "proxy_service_url" }, 212 237 .{ .flag = "--jwt-secret=", .field = "jwt_secret" }, 213 238 .{ .flag = "--admin-token=", .field = "admin_token" }, 214 239 .{ .flag = "--log-level=", .field = "log_level" },
+3
src/main.zig
··· 33 33 if (options.blobstore_path) |value| zds.core.config.setBlobstorePath(value); 34 34 if (options.handle_domains) |value| zds.core.config.setHandleDomains(value); 35 35 if (options.crawlers) |value| zds.core.config.setCrawlers(value); 36 + if (options.proxy_service_did) |value| zds.core.config.setProxyServiceDid(value); 37 + if (options.proxy_service_id) |value| zds.core.config.setProxyServiceId(value); 38 + if (options.proxy_service_url) |value| zds.core.config.setProxyServiceUrl(value); 36 39 if (options.jwt_secret) |value| zds.core.config.setJwtSecret(value); 37 40 zds.core.config.setAdminToken(options.admin_token); 38 41 zds.core.config.setInviteRequired(options.invite_required);