2017-02-02 4 views
2

Ich habe eine URL wie dieWie Alamofire von Codierung von URL-Parameter

https://www.mysite/v1/search?N=4249847587+1798040122

Ich benutze Alamofire wie die

Almofire.request(.GET, "https://www.mysite/v1/search", parameters: ["N","4249847587+1798040122"], encoding: .URL) 

Protokollierung der Anforderung zu blockieren, erhalte ich

https://www.mysite/v1/search?N=4249847587%2B1798040122 

dh

"% 2B" statt "+"

Aber ich muss mit

"+"

Wie kann ich vermeiden, bleiben diese Codierung Alamofire mit?

+1

https://github.com/Alamofire/Alamofire/pull/167/commits/570ed7e8fee36106c93a3251fbb1a97d818e7f09 – Sahil

+2

Nein, Sie möchten, dass das '+' als '% 2B' codiert wird. Andernfalls behandelt der Server das '+' als Codierung eines Leerzeichen. – rmaddy

+0

Danke, Leute, ich habe das Problem gelöst. Du hast mir sehr geholfen –

Antwort

2

Generell @rmaddy ist richtig in seinem Kommentar. Aber wir können diese Codierung als eine lustige Übung abschalten.

Wir müssen dafür einen benutzerdefinierten Encoder verwenden. Alamofire unterstützt jeden benutzerdefinierten Encoder, der das ParameterEncoding Protokoll anstelle von encoding: .URL implementiert.

So habe ein wenig Kopie & eingefügt Code von den ursprünglichen Alamofire Codebasis verwenden kann, und erstellen Sie eigenen Encoder

public struct NOURLEncoding: ParameterEncoding { 

    //protocol implementation 
    public func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest { 
     var urlRequest = try urlRequest.asURLRequest() 

     guard let parameters = parameters else { return urlRequest } 

     if HTTPMethod(rawValue: urlRequest.httpMethod ?? "GET") != nil { 
      guard let url = urlRequest.url else { 
       throw AFError.parameterEncodingFailed(reason: .missingURL) 
      } 

      if var urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: false), !parameters.isEmpty { 
       let percentEncodedQuery = (urlComponents.percentEncodedQuery.map { $0 + "&" } ?? "") + query(parameters) 
       urlComponents.percentEncodedQuery = percentEncodedQuery 
       urlRequest.url = urlComponents.url 
      } 
     } 

     return urlRequest 
    } 

    //append query parameters 
    private func query(_ parameters: [String: Any]) -> String { 
     var components: [(String, String)] = [] 

     for key in parameters.keys.sorted(by: <) { 
      let value = parameters[key]! 
      components += queryComponents(fromKey: key, value: value) 
     } 

     return components.map { "\($0)=\($1)" }.joined(separator: "&") 
    } 

    //Alamofire logic for query components handling 
    public func queryComponents(fromKey key: String, value: Any) -> [(String, String)] { 
     var components: [(String, String)] = [] 

     if let dictionary = value as? [String: Any] { 
      for (nestedKey, value) in dictionary { 
       components += queryComponents(fromKey: "\(key)[\(nestedKey)]", value: value) 
      } 
     } else if let array = value as? [Any] { 
      for value in array { 
       components += queryComponents(fromKey: "\(key)[]", value: value) 
      } 
     } else if let value = value as? NSNumber { 
      if value.isBool { 
       components.append((escape(key), escape((value.boolValue ? "1" : "0")))) 
      } else { 
       components.append((escape(key), escape("\(value)"))) 
      } 
     } else if let bool = value as? Bool { 
      components.append((escape(key), escape((bool ? "1" : "0")))) 
     } else { 
      components.append((escape(key), escape("\(value)"))) 
     } 

     return components 
    } 

    //escaping function where we can select symbols which we want to escape 
    //(I just removed + for example) 
    public func escape(_ string: String) -> String { 
     let generalDelimitersToEncode = ":#[]@" // does not include "?" or "/" due to RFC 3986 - Section 3.4 
     let subDelimitersToEncode = "!$&'()*,;=" 

     var allowedCharacterSet = CharacterSet.urlQueryAllowed 
     allowedCharacterSet.remove(charactersIn: "\(generalDelimitersToEncode)\(subDelimitersToEncode)") 

     var escaped = "" 

     escaped = string.addingPercentEncoding(withAllowedCharacters: allowedCharacterSet) ?? string 

     return escaped 
    } 

} 

extension NSNumber { 
    fileprivate var isBool: Bool { return CFBooleanGetTypeID() == CFGetTypeID(self) } 
} 

I Idee nicht, warum es sinnvoll sein kann. Aber benutzerdefinierte Codierung kann einfach hinzugefügt werden. Jetzt können Sie nur Alamofire Anfrage mit unserem neuen Encoder

Alamofire.request("http://www.mysite/v1/search", method: .get, parameters: ["N": "4249847587+1798040122"], encoding: NOURLEncoding()) 
1

verwenden Obwohl die Frage nur für diejenige beantwortet wurde, die neu in einem schnellen und wahrscheinlich Alamofire zum ersten Mal und mit Blick auf Probleme mit.

Hier

baseUrl = "https://www.baseUrl.com/",

path = "user/etwas/Status? Current = Single" Das ist, was ich tat (Swift 3.0, Alamofire v4.4)

let completeUrl = baseUrl.appending(path) 
let urlWithoutPercent = completeUrl.removingPercentEncoding 
let finalUrl = URL(string: urlWithoutPercent!) 
var URLRequest = Foundation.URLRequest(url: finalUrl!) 

oder

let wholeURL = baseUrl.appending(path) 
let urlwithPercent = wholeURL.addingPercentEncoding(withAllowedCharacters: NSCharacterSet.urlQueryAllowed) 
var URLRequest = Foundation.URLRequest(url: URL(string: urlwithPercent!)!) 

Nun ist die Geschichte ist:

https://www.baseUrl.com/user/anything/status% 3F Strom = als 403

die Antwort Einzel kommen würde:

wurde meine URL zu so etwas wie dieses Converted zu werden. nach einer Online-Suche für ca. 4 Stunden konnte ich keine einfache und kleine Lösung finden. Durch Entfernen der prozentualen Codierung wurde das Problem gelöst. Dies ist auch nicht der richtige Ansatz wie in den Kommentaren von @rmaddy.

Und das gilt für alle Sonderzeichencodierung unabhängig davon, ob es sich um ein Fragezeichen, Ausrufezeichen oder irgendetwas ..

Hoffe, dass es jemand hilft.

+0

HAFTUNGSAUSSCHLUSS: Es kann passieren, dass deine anderen api-Aufrufe nicht die gewünschte Antwort geben ... kurz gesagt, sie können scheitern .. dieser Trick funktioniert nur, wenn die URL Parameter mit speziellen Zeichen hat .. –