Quando si costruisce una richiesta GET
, non c'è il corpo alla richiesta, ma tutto va sull'URL. Per creare un URL (e percorrerlo correttamente per percorrerlo), puoi anche utilizzare URLComponents
.
var url = URLComponents(string: "https://www.google.com/search/")!
url.queryItems = [
URLQueryItem(name: "q", value: "War & Peace")
]
L'unico trucco è che la maggior parte dei servizi web hanno bisogno +
carattere di percentuale sfuggito (perché ti interpretano che, come un carattere di spazio come dettato dalla application/x-www-form-urlencoded
specification). Ma lo URLComponents
non lo sfugge per cento. Apple sostiene che +
è un carattere valido in una query e pertanto non deve essere scappato. Tecnicamente, sono corretti, è consentito in una query di un URI, ma ha un significato speciale nelle richieste application/x-www-form-urlencoded
e in realtà non dovrebbe essere passato senza caratteri di escape.
di Apple riconosce che dobbiamo cento sfuggire alle +
personaggi, ma consiglia che lo facciamo manualmente:
var url = URLComponents(string: "https://www.wolframalpha.com/input/")!
url.queryItems = [
URLQueryItem(name: "i", value: "1+2")
]
url.percentEncodedQuery = url.percentEncodedQuery?.replacingOccurrences(of: "+", with: "%2B")
Questo è un poco elegante work-around, ma funziona, ed è quello che Apple consiglia se il vostro le query possono includere un carattere +
e si dispone di un server che li interpreta come spazi.
Quindi, combinando che con la vostra sendRequest
di routine, si finisce con qualcosa di simile:
func sendRequest(_ url: String, parameters: [String: String], completion: @escaping ([String: Any]?, Error?) -> Void) {
var components = URLComponents(string: url)!
components.queryItems = parameters.map { (key, value) in
URLQueryItem(name: key, value: value)
}
components.percentEncodedQuery = components.percentEncodedQuery?.replacingOccurrences(of: "+", with: "%2B")
let request = URLRequest(url: components.url!)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data, // is there data
let response = response as? HTTPURLResponse, // is there HTTP response
(200 ..< 300) ~= response.statusCode, // is statusCode 2XX
error == nil else { // was there no error, otherwise ...
completion(nil, error)
return
}
let responseObject = (try? JSONSerialization.jsonObject(with: data)) as? [String: Any]
completion(responseObject, nil)
}
task.resume()
}
E che ci si chiami come:
sendRequest("someurl", parameters: ["foo": "bar"]) { responseObject, error in
guard let responseObject = responseObject, error == nil else {
print(error ?? "Unknown error")
return
}
// use `responseObject` here
}
Personalmente, mi piacerebbe utilizzare JSONDecoder
al giorno d'oggi e restituire un numero personalizzato struct
anziché un dizionario, ma non è molto pertinente qui. Si spera che questo illustri l'idea di base su come codificare per percentuale i parametri nell'URL di una richiesta GET.
Vedi previous revision of this answer per Swift 2 e cento manuale di fuga rendition.
Grazie per la risposta fantastica. Ho solo una domanda, sono ancora un po 'confuso su cosa sta facendo la stringa di estensione ai valori? Inoltre quando dovrei usare 'HttpBody' allora? – MrSSS16
L'estensione della stringa è percentuale che sfugge ai valori per RFC 3986. Ci sono determinati caratteri che hanno significati speciali negli URL (es. '&' Separa un parametro dal successivo, quindi se '&' si verifica in valore, non puoi lasciarlo andare senza caratteri di escape). Per quanto riguarda 'HTTPBody', dovresti _non_ usarlo nella richiesta' GET'; È usato in 'POST' ma non' GET'. – Rob
Sembra così semplice, quali sono i vantaggi di utilizzare qualcosa come https://github.com/xyyc/SwiftSocket/ invece di questo? Mi dispiace, sono nuovo di tutto questo. – Jigzat