Skip to content

Add form-url-encoding support #8

@bcapps

Description

@bcapps

Engineering Task

Add a convenience for form-url-encoding keys and values in an HTTP body. Here's how the code could look:

extension NetworkRequest {
    /// Returns form-encoded data for use in an HTTP body on a POST or PUT request. Based loosely on this answer from an Apple engineer:  https://developer.apple.com/forums/thread/113632?answerId=349535022#349535022
    /// - Parameter items: The keys and values to form-encode.
    /// - Returns: Form-encoded data for use in an HTTP body on a POST or PUT request.
    func formEncodedHTTPBodyData(for items: [String: String]) -> Data? {
        let formEncodedString = items.map { key, value in
            return "\(key.formEncodingEscaped())=\(value.formEncodingEscaped())"
        }.joined(separator: "&")
        
        return formEncodedString.data(using: .utf8)
    }
}

private extension String {
    private var formEncodingAllowedCharacters: CharacterSet {
        var allowed = CharacterSet.urlQueryAllowed
        allowed.insert(" ") // Allow this character to later replace it with `+`
        allowed.remove("+")
        allowed.remove("/")
        allowed.remove("?")
        return allowed
    }

    func formEncodingEscaped() -> String {
        let escapedString = replacingOccurrences(of: "\n", with: "\r\n")
            .addingPercentEncoding(withAllowedCharacters: formEncodingAllowedCharacters)?
            .replacingOccurrences(of: " ", with: "+")
        guard let escapedString = escapedString else {
            assertionFailure("String that was escaped could not be percent encoded, likely because it is not UTF-8.")
            return self
        }
        
        return escapedString
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions