let str = "Привет Как дела" // Внутренняя кодировка Свифта utf-32
let cp1251Data = str.data(using: .windowsCP1251)
let utf8Data = str.data(using: .utf8)
cp1251Data.count // 15
utf8Data.count // 28
// ***********************************
let session = URLSession.shared
var URL = URL(string: "https://greatcomments.server/add")!
var request = URLRequest(url: URL)
request.httpMethod = "POST"
// Headers
request.addValue("application/x-www-form-urlencoded; charset=windows-1251", forHTTPHeaderField: "Content-Type")
// Form URL-Encoded Body
let bodyParameters = [
"comment": "Проверка",
]
let bodyString = bodyParameters.queryParameters
request.httpBody = bodyString.data(using: . win1251, allowLossyConversion: true)
let task = session.dataTask(with: request, completionHandler: { (data: Data?, response: URLResponse?, error: Error?) -> Void in
if (error == nil) {
// Success
let statusCode = (response as! HTTPURLResponse).statusCode
print("URL Session Task Succeeded: HTTP \(statusCode)")
}
else {
// Failure
print("URL Session Task Failed: %@", error!.localizedDescription);
}
})
task.resume()
session.finishTasksAndInvalidate()
// ***********************************
protocol URLQueryParameterStringConvertible {
var queryParameters: String {get}
}
extension Dictionary : URLQueryParameterStringConvertible {
var queryParameters: String {
var parts: [String] = []
for (key, value) in self {
let part = String(format: "%@=%@",
String(describing: key).win1251Encoded,
String(describing: value).win1251Encoded)
parts.append(part as String)
}
return parts.joined(separator: "&")
}
}
extension URL {
func appendingQueryParameters(_ parametersDictionary : [String: String]) -> URL {
let URLString : String = String(format: "%@?%@", self.absoluteString, parametersDictionary.queryParameters)
return URL(string: URLString)!
}
}
// Раньше Swift(Foundation) позволял любую строку закодировать в url-encode в любой кодировке.
// Сейчас же де факто это можно лишь сделать в utf-8.
// Видимо Apple аргументирует это тем, что utf-8 - это стандарт в вебе.
// Да всех остальных случаев нужно писать такую функцию самому.
// Ниже кодировка в url-encode в windows-1251
extension CharacterSet {
static let rfc3986Unreserved = CharacterSet(charactersIn: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~=&+")
}
extension String.Encoding {
static let win1251 = String.Encoding(rawValue: CFStringConvertEncodingToNSStringEncoding(CFStringEncoding(CFStringEncodings.windowsCyrillic.rawValue)))
}
extension String {
func addingPercentEncoding(withAllowedCharacters characterSet: CharacterSet, using encoding: String.Encoding) -> String {
let stringData = self.data(using: encoding, allowLossyConversion: true) ?? Data()
let percentEscaped = stringData.map {byte->String in
if characterSet.contains(UnicodeScalar(byte)) {
return String(UnicodeScalar(byte))
} else if byte == UInt8(ascii: " ") {
return "+"
} else {
return String(format: "%%%02X", byte)
}
}.joined()
return percentEscaped
}
var win1251Encoded: String {
return self.addingPercentEncoding(withAllowedCharacters: .rfc3986Unreserved, using: . win1251)
}
}