Last week, I encountered another interesting case of something I didn't know.

I worked on the implementation of one API call that requires sending some data as url query params. One of these params was an email.

Everything is fine unless you have a + sign in the string. RFC3986 specifies which characters must be percent-encoded but not how to be interpreted.

According to RFC3986 the + sign is a valid character that could be included in the query params, however according to the W3C recommendations for URI addressing, it is reserved as short hand notation for a space within a query string like this: ?greeting=hello+world.

For more information, go to the Apple's Documentation: queryItems.

Solution

The solution was pretty simple - just encoded the + sign by hand like this:

components.queryItems = params.map { URLQueryItem(name: $0, value: $1) }
components.percentEncodedQuery =
  components.percentEncodedQuery!.replacingOccurrences(of: "+", with: "%2B")

So what basically happens here is that we add the query items to the URLComponents and after that replacing all the occurrences of the + sign with its encoded value %2B in the percentEncodedQuery.

Another way is to not encode it by hand as @jasamer suggested in here, but like this:

let string = "hello+world"
let encoded = string.addingPercentEncoding(
  withAllowedCharacters: CharacterSet(charactersIn: "+").inverted
)

I hope that it will save some time for anyone wondering why their apps are sending query params with spaces instead of + signs. 🙏🏻