@@ -40,11 +40,7 @@ public struct NetworkInterface {
4040 successClosure: @escaping ( [ String : Any ] ) -> Void ,
4141 errorClosure: @escaping ( SlackError ) -> Void
4242 ) {
43- var components = URLComponents ( string: " \( apiUrl) \( endpoint. rawValue) " )
44- if parameters. count > 0 {
45- components? . queryItems = filterNilParameters ( parameters) . map { URLQueryItem ( name: $0. 0 , value: " \( $0. 1 ) " ) }
46- }
47- guard let url = components? . url else {
43+ guard let url = self . url ( for: endpoint, parameters: parameters) else {
4844 errorClosure ( SlackError . clientNetworkError)
4945 return
5046 }
@@ -61,11 +57,7 @@ public struct NetworkInterface {
6157
6258 //Adapted from https://gist.github.com/erica/baa8a187a5b4796dab27
6359 internal func synchronusRequest( _ endpoint: Endpoint , parameters: [ String : Any ? ] ) -> [ String : Any ] ? {
64- var components = URLComponents ( string: " \( apiUrl) \( endpoint. rawValue) " )
65- if parameters. count > 0 {
66- components? . queryItems = filterNilParameters ( parameters) . map { URLQueryItem ( name: $0. 0 , value: " \( $0. 1 ) " ) }
67- }
68- guard let url = components? . url else {
60+ guard let url = self . url ( for: endpoint, parameters: parameters) else {
6961 return nil
7062 }
7163 let request = URLRequest ( url: url)
@@ -114,12 +106,8 @@ public struct NetworkInterface {
114106 parameters: [ String : Any ? ] ,
115107 successClosure: @escaping ( [ String : Any ] ) -> Void , errorClosure: @escaping ( SlackError ) -> Void
116108 ) {
117- var components = URLComponents ( string: " \( apiUrl) \( Endpoint . filesUpload. rawValue) " )
118- if parameters. count > 0 {
119- components? . queryItems = filterNilParameters ( parameters) . map { URLQueryItem ( name: $0. 0 , value: " \( $0. 1 ) " ) }
120- }
121109 guard
122- let url = components ? . url,
110+ let url = self . url ( for : Endpoint . filesUpload , parameters : parameters ) ,
123111 let filename = parameters [ " filename " ] as? String ,
124112 let filetype = parameters [ " filetype " ] as? String
125113 else {
@@ -176,6 +164,24 @@ public struct NetworkInterface {
176164 }
177165 }
178166
167+ private func url( for endpoint: Endpoint , parameters: [ String : Any ? ] ) -> URL ? {
168+ var components = URLComponents ( string: " \( apiUrl) \( endpoint. rawValue) " )
169+ if parameters. count > 0 {
170+ components? . queryItems = filterNilParameters ( parameters) . map { URLQueryItem ( name: $0. 0 , value: " \( $0. 1 ) " ) }
171+ }
172+
173+ // As discussed http://www.openradar.me/24076063 and https://stackoverflow.com/a/37314144/407523, Apple considers
174+ // a + and ? as valid characters in a URL query string, but Slack has recently started enforcing that they be
175+ // encoded when included in a query string. As a result, we need to manually apply the encoding after Apple's
176+ // default encoding is applied.
177+ var encodedQuery = components? . percentEncodedQuery
178+ encodedQuery = encodedQuery? . replacingOccurrences ( of: " ? " , with: " %3F " )
179+ encodedQuery = encodedQuery? . replacingOccurrences ( of: " + " , with: " %2B " )
180+ components? . percentEncodedQuery = encodedQuery
181+
182+ return components? . url
183+ }
184+
179185 private func requestBodyData( data: Data , boundaryConstant: String , filename: String , filetype: String ) -> Data ? {
180186 let boundaryStart = " -- \( boundaryConstant) \r \n "
181187 let boundaryEnd = " -- \( boundaryConstant) -- \r \n "
0 commit comments