Encode '+' using URLComponents in Swift

前端 未结 4 794
死守一世寂寞
死守一世寂寞 2020-12-11 00:56

This is how I add query params to a base URL:

let baseURL: URL = ...
let queryParams: [AnyHashable: Any] = ...
var components = URLComponents(url: baseURL, r         


        
4条回答
  •  天命终不由人
    2020-12-11 01:26

    URLComponents is behaving correctly: the + is not being percent-encoded because it is legal as it stands. You can force the + to be percent-encoded by using .alphanumerics, as explained already by Forest Kunecke (I got the same result independently but he was well ahead of me in submitting his answer!).

    Just a couple of refinements. The OP's value: "\($1)" is unnecessary if this is a string; you can just say value:$1. And, it would be better to form the URL from all its components.

    This, therefore, is essentially the same solution as Forest Kunecke, but I think it is more canonical and it is certainly more compact ultimately:

    let queryParams = ["hey":"ho+ha"]
    var components = URLComponents()
    components.scheme = "http"
    components.host = "www.example.com"
    components.path = "/somepath"
    components.queryItems = queryParams.map { 
      URLQueryItem(name: $0, 
        value: $1.addingPercentEncoding(withAllowedCharacters: .alphanumerics)!) 
    }
    let finalURL = components.url
    

    EDIT Rather better, perhaps, after suggested correction from Martin R: we form the entire query and percent-encode the pieces ourselves, and tell the URLComponents that we have done so:

    let queryParams = ["hey":"ho+ha", "yo":"de,ho"]
    var components = URLComponents()
    components.scheme = "http"
    components.host = "www.example.com"
    components.path = "/somepath"
    var cs = CharacterSet.urlQueryAllowed
    cs.remove("+")
    components.percentEncodedQuery = queryParams.map {
        $0.addingPercentEncoding(withAllowedCharacters: cs)! + 
        "=" + 
        $1.addingPercentEncoding(withAllowedCharacters: cs)!
    }.joined(separator:"&")
    
    // ---- Okay, let's see what we've got ----
    components.queryItems
    // [{name "hey", {some "ho+ha"}}, {name "yo", {some "de,ho"}}]
    components.url
    // http://www.example.com/somepath?hey=ho%2Bha&yo=de,ho
    

提交回复
热议问题