Encode "+" with URLComponents in Swift

This is how I add the request parameters to the base URL:

let baseURL: URL = ...
let queryParams: [AnyHashable: Any] = ...
var components = URLComponents(url: baseURL, resolvingAgainstBaseURL: false)
components?.queryItems = queryParams.map { URLQueryItem(name: $0, value: "\($1)") }
let finalURL = components?.url

A problem occurs when one of the values ​​contains a character +. For some reason, it is not encoded to %2Bthe final URL, instead it remains +. If I myself encode and transmit %2B, NSURLencodes %, but 'plus' becomes %252B.

The question is, how can I %2Bin an instance NSURL?

PS I know, I would not even have this problem if I built the query string myself, and then just passed the result to the constructor NSURL init?(string:).

+4
source share
3

, "+" , query​Items .

, W3C URI ,

. , . URI , .

"" , :

let queryParams = ["foo":"a+b", "bar": "a-b", "baz": "a b"]
var components = URLComponents()

var cs = CharacterSet.urlQueryAllowed
cs.remove("+")

components.scheme = "http"
components.host = "www.example.com"
components.path = "/somepath"
components.percentEncodedQuery = queryParams.map {
    $0.addingPercentEncoding(withAllowedCharacters: cs)!
    + "=" + $1.addingPercentEncoding(withAllowedCharacters: cs)!
}.joined(separator: "&")

let finalURL = components.url
// http://www.example.com/somepath?bar=a-b&baz=a%20b&foo=a%2Bb

- "-" :

let queryParams = ["foo":"a+b", "bar": "a-b", "baz": "a b"]
var components = URLComponents()
components.scheme = "http"
components.host = "www.example.com"
components.path = "/somepath"
components.queryItems = queryParams.map { URLQueryItem(name: $0, value: $1) }
components.percentEncodedQuery = components.percentEncodedQuery?
    .replacingOccurrences(of: "+", with: "%2B")

let finalURL = components.url
print(finalURL!)
// http://www.example.com/somepath?bar=a-b&baz=a%20b&foo=a%2Bb
+4

addingPercentEncoding(withAllowedCharacters: .alphanumerics)?

, , :

//: Playground - noun: a place where people can play

let baseURL: URL = URL(string: "http://example.com")!
let queryParams: [AnyHashable: Any] = ["test": 20, "test2": "+thirty"]
var components = URLComponents(url: baseURL, resolvingAgainstBaseURL: false)

var escapedComponents = [String: String]()
for item in queryParams {
    let key = item.key as! String
    let paramString = "\(item.value)"

    // percent-encode any non-alphanumeric character.  This is NOT something you typically need to do.  User discretion advised.
    let escaped = paramString.addingPercentEncoding(withAllowedCharacters: .alphanumerics)

    print("escaped: \(escaped)")

    // add the newly escaped components to our dictionary
    escapedComponents[key] = escaped
}


components?.queryItems = escapedComponents.map { URLQueryItem(name: ($0), value: "\($1)") }
let finalURL = components?.url
+2

URLComponents : + , . + , .alphanumerics, ( , , !).

. OP value: "\($1)" , ; value:$1. URL- .

, , , , Forest Kunecke, , , , :

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 It’s rather better, perhaps, after the proposed correction from Martin R: we form the entire request and quote the fragments themselves and tell URLComponents that we did this:

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 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
+2
source

Source: https://habr.com/ru/post/1673333/


All Articles