vapor / multipart-kit

🏞 Parses and serializes multipart-encoded data with Codable support.
MIT License
138 stars 41 forks source link
codable formdata multipart server-side-swift swift vapor

MultipartKit

Documentation Team Chat MIT License Continuous Integration Swift 5.7+

🏞 Multipart parser and serializer with `Codable` support for Multipart Form Data. ### Installation Use the SPM string to easily include the dependency in your `Package.swift` file. Add MultipartKit to your package dependencies: ```swift dependencies: [ // ... .package(url: "https://github.com/vapor/multipart-kit.git", from: "4.0.0"), ] ``` Add MultipartKit to your target's dependencies: ```swift targets: [ .target(name: "MyAppTarget", dependencies: [ // ... .product(name: "MultipartKit", package: "multipart-kit"), ]) ] ``` ### Supported Platforms MultipartKit supports the following platforms: - All Linux distributions supported by Swift 5.7+ - macOS 10.15+ ## Overview MultipartKit is a multipart parsing and serializing library. It provides `Codable` support for the special case of the `multipart/form-data` media type through a `FormDataEncoder` and `FormDataDecoder`. The parser delivers its output as it is parsed through callbacks suitable for streaming. ### Multipart Form Data Let's define a `Codable` type and a choose a boundary used to separate the multipart parts. ```swift struct User: Codable { let name: String let email: String } let user = User(name: "Ed", email: "ed@example.com") let boundary = "abc123" ``` We can encode this instance of a our type using a `FormDataEncoder`. ```swift let encoded = try FormDataEncoder().encode(foo, boundary: boundary) ``` The output looks then looks like this. ``` --abc123 Content-Disposition: form-data; name="name" Ed --abc123 Content-Disposition: form-data; name="email" ed@example.com --abc123-- ``` In order to _decode_ this message we feed this output and the same boundary to a `FormDataDecoder` and we get back an identical instance to the one we started with. ```swift let decoded = try FormDataDecoder().decode(User.self, from: encoded, boundary: boundary) ``` ### A note on `null` As there is no standard defined for how to represent `null` in Multipart (unlike, for instance, JSON), FormDataEncoder and FormDataDecoder do not support encoding or decoding `null` respectively. ### Nesting and Collections Nested structures can be represented by naming the parts such that they describe a path using square brackets to denote contained properties or elements in a collection. The following example shows what that looks like in practice. ```swift struct Nested: Encodable { let tag: String let flag: Bool let nested: [Nested] } let boundary = "abc123" let nested = Nested(tag: "a", flag: true, nested: [Nested(tag: "b", flag: false, nested: [])]) let encoded = try FormDataEncoder().encode(nested, boundary: boundary) ``` This results in the content below. ``` --abc123 Content-Disposition: form-data; name="tag" a --abc123 Content-Disposition: form-data; name="flag" true --abc123 Content-Disposition: form-data; name="nested[0][tag]" b --abc123 Content-Disposition: form-data; name="nested[0][flag]" false --abc123-- ``` Note that the array elements always include the index (as opposed to just `[]`) in order to support complex nesting.