A Swift implementation of RFC 2183 - Communicating Presentation Information in Internet Messages: The Content-Disposition Header Field.
This package provides type-safe Swift types for working with Content-Disposition headers in MIME messages and HTTP responses. It follows the RFC 2183 specification exactly while providing convenient, Swift-friendly APIs.
- âś… RFC 2183 Compliant: Implements the full specification
- âś… Type-Safe: Strong typing for disposition types and parameters
- âś… Extensible: Supports custom disposition types
- âś… Parameter Validation: Proper escaping and quoting per RFC
- âś… Swift 6 Concurrency: Full Sendable support
- âś… Zero Dependencies: Standalone implementation
Add this package to your Package.swift:
dependencies: [
.package(url: "https://github.com/swift-standards/swift-rfc-2183.git", from: "0.1.0")
]import RFC_2183
// Inline content
let inline = RFC_2183.ContentDisposition.inline()
// Content-Disposition: inline
// Attachment with filename
let attachment = RFC_2183.ContentDisposition.attachment(filename: "document.pdf")
// Content-Disposition: attachment; filename="document.pdf"
// Form data
let formData = RFC_2183.ContentDisposition.formData(
name: "avatar",
filename: "photo.jpg"
)
// Content-Disposition: form-data; name="avatar"; filename="photo.jpg"// Parse from header value
let disposition = try RFC_2183.ContentDisposition(
parsing: #"attachment; filename="report.pdf""#
)
print(disposition.type) // .attachment
print(disposition.filename) // Optional("report.pdf")// Create with multiple parameters
let disposition = RFC_2183.ContentDisposition(
type: .attachment,
parameters: [
"filename": "data.bin",
"size": "1048576",
"creation-date": "Mon, 01 Jan 2024 12:00:00 GMT"
]
)
// Access typed parameters
print(disposition.filename) // Optional("data.bin")
print(disposition.size) // Optional(1048576)
print(disposition.creationDate) // Optional("Mon, 01 Jan 2024...")// RFC 2183 allows extension types
let custom = RFC_2183.ContentDisposition(
type: RFC_2183.DispositionType(rawValue: "x-custom"),
parameters: ["param": "value"]
)// Create from string literal
let disposition: RFC_2183.ContentDisposition = "attachment; filename=\"test.txt\""
// Create type from string literal
let type: RFC_2183.DispositionType = "inline"inline: Content should be displayed automaticallyattachment: Content should be saved/downloaded (requires user action)
form-data: Used in multipart/form-data (RFC 7578)
Per RFC 2183, the following parameters are defined:
filename: Suggested filename for saving contentcreation-date: When file was created (RFC 822 date-time)modification-date: When file was last modifiedread-date: When file was last readsize: File size in octets
name: Form field name in multipart/form-data
public struct ContentDisposition {
public let type: DispositionType
public let parameters: [String: String]
// Initializers
public init(type: DispositionType, parameters: [String: String] = [:])
public init(parsing headerValue: String) throws
// Properties
public var headerValue: String
public var filename: String?
public var creationDate: String?
public var modificationDate: String?
public var readDate: String?
public var size: Int?
public var name: String? // form-data extension
// Convenience constructors
public static func inline() -> Self
public static func attachment(filename: String? = nil) -> Self
public static func formData(name: String, filename: String? = nil) -> Self
}public struct DispositionType {
public let rawValue: String
public static let inline: DispositionType
public static let attachment: DispositionType
public static let formData: DispositionType // RFC 7578 extension
}// Download file
let disposition = RFC_2183.ContentDisposition.attachment(filename: "report.pdf")
response.headers.add(name: "Content-Disposition", value: disposition.headerValue)// Email with attachment
let disposition = RFC_2183.ContentDisposition(
type: .attachment,
parameters: [
"filename": "invoice.pdf",
"size": "524288",
"creation-date": "Wed, 12 Feb 1997 16:29:51 -0500"
]
)// File upload field
let fileField = RFC_2183.ContentDisposition.formData(
name: "document",
filename: "contract.pdf"
)
// Text field
let textField = RFC_2183.ContentDisposition.formData(name: "username")The package automatically handles escaping and quoting per RFC 2183:
// Filenames with quotes are escaped
let disposition = RFC_2183.ContentDisposition.attachment(
filename: #"file"with"quotes.txt"#
)
// Content-Disposition: attachment; filename="file\"with\"quotes.txt"
// Filenames with spaces are quoted
let disposition = RFC_2183.ContentDisposition.attachment(
filename: "my document.pdf"
)
// Content-Disposition: attachment; filename="my document.pdf"- RFC 2045: MIME Part One - Format of Internet Message Bodies
- RFC 2046: MIME Part Two - Media Types
- RFC 2183: Content-Disposition Header (this package)
- RFC 7578: Returning Values from Forms: multipart/form-data
Apache License 2.0
See LICENSE.txt for details.