Adds the presigned-upload plumbing Outline's own web client uses for any file upload, not just avatars: attachments.create requests an upload target (server-assigned key, ACL, a short-lived signed form), then a direct multipart POST to that target (uploadUrl/form) actually uploads the bytes — confirmed against a live server's own request/ response shapes pulled from network capture. MultipartFormDataBuilder is a pure, fully-tested function (no network) building that S3-style presigned-POST body. uploadAttachmentFile deliberately sends no Bearer/CSRF header — the presigned form's `sig` field is what authorizes that specific request, same as an S3 presigned POST; flagged as best-effort pending live confirmation, cheap to add if the server turns out to also want one. UpdateUserAvatarRequest (users.update, avatar only) needed a custom encode(to:) — Swift's synthesized Encodable omits nil Optional keys via encodeIfPresent, but removing an avatar needs a literal "avatarUrl": null in the body, not the key missing. Confirmed the request shape (id + avatarUrl) from the captured request's Content-Length matching that shape and no shorter alternative. 6 new tests (multipart body structure/field ordering, explicit-null encoding, create/upload/update round trip) — 63/63 passing.
20 lines
716 B
Swift
20 lines
716 B
Swift
import Foundation
|
|
|
|
/// Requests an upload target for a new file — not the upload itself, see
|
|
/// `OutlineAPIClient.uploadAttachmentFile`. `documentId: nil` is what a
|
|
/// user-avatar upload sends (confirmed live); a real value scopes the
|
|
/// attachment to a document instead (e.g. an inline image embed).
|
|
public struct CreateAttachmentRequest: Encodable, Sendable {
|
|
public let name: String
|
|
public let contentType: String
|
|
public let size: Int
|
|
public let documentId: String?
|
|
|
|
public init(name: String, contentType: String, size: Int, documentId: String? = nil) {
|
|
self.name = name
|
|
self.contentType = contentType
|
|
self.size = size
|
|
self.documentId = documentId
|
|
}
|
|
}
|