Percent encoding of "/" (forward slashes) in URLQueryItem

I am trying to figure out how to properly percent encode forward slashes in URL query items. If i use URLComponents with URLQueryItem, they do automatically escape a bunch of characters, e.g. "=" and "%". However, "/" is not escaped. But because "%" is escaped, manually escaping "/" means it will be escaped twice, resulting in "%252F".

As a workaround i have created a URL manually from a string with manually excaped URL parameters. But i feel like this should be possible with the proper APIs. Am i missing something?

Example code

var baseURLString = "https://www.foobar.com"
var baseURL = URL(string: baseURLString)!

var userID = "abc/def=="
var encodedUserID = userID.addingPercentEncoding(withAllowedCharacters: .alphanumerics)

var queryItem = URLQueryItem(name: "userID", value: userID)
var encodedQueryItem = URLQueryItem(name: "encodedUserID", value: encodedUserID)

var urlComponents = URLComponents(url: baseURL, resolvingAgainstBaseURL: false)!
urlComponents.queryItems = [queryItem, encodedQueryItem]

Output

https://www.foobar.com?userID=abc/def%3D%3D&encodedUserID=abc%252Fdef%253D%253D

You're using withAllowedCharacters: .alphanumerics. Have you tried withAllowedCharacters: CharacterSet.urlHostAllowed?

The problem is that URLQueryItem claims to handle the encoding. So you're encoding twice in some cases by also using addingPercentEncoding.

The other problem is that URLQueryItem doesn't really know how to encode HTTP parameters. For example, forward slashes are passed straight through, instead of encoding to %2F.

At some point you give up and just do it yourself from the spec.

Percent encoding of "/" (forward slashes) in URLQueryItem
 
 
Q