mount public data from the atmosphere to a virtual filesystem (macos only) pdfs.at
0
fork

Configure Feed

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

feat(atproto): add getBlob typed endpoint with MIME extraction

+35
+18
Packages/ATProto/Sources/ATProto/XRPC/XRPCEndpoints.swift
··· 57 57 return try await get(nsid: "com.atproto.sync.listBlobs", params: params) 58 58 } 59 59 } 60 + 61 + // MARK: - getBlob 62 + 63 + public struct BlobDownload: Sendable, Equatable { 64 + public let data: Data 65 + public let mimeType: String? 66 + } 67 + 68 + public extension XRPCClient { 69 + func getBlob(did: String, cid: String) async throws -> BlobDownload { 70 + let (data, response) = try await getBytes( 71 + nsid: "com.atproto.sync.getBlob", 72 + params: ["did": did, "cid": cid] 73 + ) 74 + let mime = (response as? HTTPURLResponse)?.value(forHTTPHeaderField: "Content-Type") 75 + return BlobDownload(data: data, mimeType: mime) 76 + } 77 + }
+17
Packages/ATProto/Tests/ATProtoTests/XRPCEndpointsTests.swift
··· 87 87 #expect(out.cids == ["bafkreia", "bafkreib"]) 88 88 #expect(out.cursor == "c1") 89 89 } 90 + 91 + @Test("getBlob returns raw bytes + MIME from Content-Type") 92 + func getBlob() async throws { 93 + let bytes = Data([0xFF, 0xD8, 0xFF, 0xE0]) // JPEG magic 94 + let (client, session) = makeClient { request in 95 + #expect(request.url?.path == "/xrpc/com.atproto.sync.getBlob") 96 + let q = request.url?.query ?? "" 97 + #expect(q.contains("did=did:plc:abc")) 98 + #expect(q.contains("cid=bafkreia")) 99 + return .bytes(bytes, contentType: "image/jpeg") 100 + } 101 + defer { URLProtocolStub.reset(session: session) } 102 + 103 + let blob = try await client.getBlob(did: "did:plc:abc", cid: "bafkreia") 104 + #expect(blob.data == bytes) 105 + #expect(blob.mimeType == "image/jpeg") 106 + } 90 107 }