Search code examples
iosswiftencodingnsurlrequest

URLRequest encoding not catching special characters


I am using the code below to make a URLRequest but specials characters, like &, aren't being encoded correctly. What am I doing wrong?

  var request = URLRequest(url: URL(string: "http://\(hostToUse)/user/login")!)
    request.httpMethod = "POST"
    request.timeoutInterval = 120.0
    var postString = "data={\"userName\":\"\(username)\",\"password\":\"\(password)\"}"
    postString = postString.addingPercentEncoding(withAllowedCharacters: .alphanumerics)!
    postString = postString.replacingOccurrences(of: " ", with: "")
    request.httpBody = postString.data(using: .utf8, allowLossyConversion: false)
    request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")

Solution

  • This code has a number of likely problems:

    • You're uploading a blob of JSON data in a single URL-encoded form field and not using any other fields. Why not just make the upload format be JSON and ditch the URL encoding entirely?
    • You're trying to URL-encode the whole "fieldname=value" when you should just be URL-encoding the value part.
    • The alphanumerics character set is WAY too broad, including anything that looks like a number. The legal character set for a URL is much, much smaller than that.

    BTW, I'm fairly certain that even URLQueryAllowedCharacterSet is too broad for a single query string field, because it allows characters like equals signs and ampersands that are reserved as field delimiters in the normal use of query strings.

    For maximum safety, you should instead use your own character set that contains only the unreserved characters:

        [NSCharacterSet characterSetWithCharactersInString:@"abcdefghijklmnopqrstuv"
            "wxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~"]
    

    Or better yet, use NSURLComponents. It has properties specifically for constructing query strings.