Skip to content

Add support for multi-part form data #7

@bcapps

Description

@bcapps

Engineering Task

Add a convenience for multi-part form data in an HTTP body, the bane of many iOS developers' existence when integrating with APIs. Here's an example of how it could look:

/// An individual item in a multipart/form-data request.
struct NetworkFormData {
    /// The key associated with this item. For example, if you see `key=value` in sample documentation, this represents the left side of that assignment.
    let key: String
    
    /// The actual data to encode as the value.
    let data: Data
    
    /// The MIME type of the data.
    let mimeType: String
    
    /// The name of the file being uploaded. Will be excluded if `nil`
    let filename: String?
}

extension NetworkRequest {
    
    /// Returns HTTP body data formatted for a multipart/form-data request.
    /// - Parameters:
    ///   - boundary: The boundary to use between items and at the end of the body.
    ///   - items: The items to list in the body.
    /// - Returns: HTTP body data formatted for a multipart/form-data request.
    func multipartFormDataHTTPBody(boundary: String, for items: [NetworkFormData]) -> Data? {
        var data = Data()
        
        for item in items {
            let filenameString = item.filename.map { "; filename=\"\($0)\"" } ?? ""
            
            data.append("--\(boundary)\r\n")
            data.append("Content-Disposition: form-data; name=\"\(item.key)\"\(filenameString)\r\n")
            data.append("Content-Type: \(item.mimeType)\r\n")
            data.append("\r\n")
            data.append(item.data)
            data.append("\r\n")
        }
        
        data.append("--\(boundary)--")
        return data
    }
}

private extension Data {
    mutating func append(_ string: String) {
        guard let data = string.data(using: .utf8) else {
            assertionFailure("String could not be converted to UTF-8 data.")
            return
        }
        
        append(data)
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions