kean/Get

Encode '+' in query string

Closed this issue · 5 comments

Hello @kean. Thank you for this library, I really admire the elegant API you achieved with this.

I've been using Get in a side project and stumbled into an issue where an explicitly written + character was not encoded when used in a query string (e.g. domain.tld?query=value1+value2). This resulted in an unexpected response from the API i was using.

According to a note in this Apple Doc which also refers to RFC 3986 and W3C, the + sign is a valid character for representing a space in a query string. Due to this fact it seems, the character is not automatically encoded when reading the url from a URLComponents instance. The same note suggests to preemptively encode the + character as well if needed.

I think it would be reasonable to add this behavior to Get, what are your thoughts?

I made a sample implementation in a fork here. Heavily inspired by Alamofire.

kean commented

Hi,

Depending on the implementation receiving this URL, you may need to preemptively percent-encode the plus sign character. As an alternative, consider encoding complex and/or potentially problematic data in a more robust data-interchange format, such as JSON or XML.

The recommendation seems to be to preemptively encode it if needed, which can be done from the client code. I would prefer to avoid adding workarounds that are only needed for specific servers and/or requests. Get is consistent with the native behavior and this note applies to it as well.

I attempted to perform the encoding in my own code without luck. Am I missing something here?

Example:

// encoded version of "value1+value2".
let queryValue = "value1%2Bvalue2"

let queryItem = URLQueryItem(name: "query", value: queryValue)
var urlComponents = URLComponents()
urlComponents.queryItems = [queryItem]

// This is the query value of the final request being sent
urlComponents.percentEncodedQuery
// "query=value1%252Bvalue2"

As you can see, the percentEncodedQuery ends up being double encoded if you will. %2B becomes %252B and thus not decoded into a + when reaching the server.

kean commented

Yeah, you are absolutely right – it double-encodes it. I didn't think it through.

URLComponents allows you to set percentEncodedQuery in case you want to encode the query yourself, but Get, of course, doesn't allow you to do it currently.

Are there any scenarios in which you don't want percent-encoding + by default? I think yes, in case someone uses + as a "space" shorthand – the way it's specified.

What do you think about adding a new delegate method to allow users to customize how URL and/or URLRequest are created?

Adding a delegate would be a fine way to do it and in line with other customization points!

My initial suggestion is absolutely too rigid/hardcoded and I respect that Get should stay as lean and close to the native behavior.

kean commented

I added the new delegate method in Get 1.0 (RC1)