Intereting Posts
Данные из трех таблиц дублируются при использовании оператора JOIN Преобразование сокращений чисел (5.2k, 1.7m и т. Д.) В действительные целые числа с PHP Как отправить таблицу html в тело электронной почты в php? PHP Dynamic Include Help на Index.php? Асинхронная обработка или очереди сообщений в PHP (CakePHP) Вызов функции PHP, определенной в другом пространстве имен без префикса Производительность: запрос JSON и визуализация в JS или запрос всего HTML? PHP PDO: Charset = UTF8: недопустимая фраза chacheet была указана в строке dsn Печать многомерного массива с использованием одного цикла Foreach 'file_get_contents' Содержимое зашифровано? Пользовательское событие для WordPress Cron Job Не выполняется Почему функция PHP htmlentities (…) возвращает неверные результаты? Есть встроенный способ в PHP для синтаксического анализа такой строки: '/path/to/../../up/something.txt' PHP – сравнение даты, проверка, если в течение последнего часа Записанные файлы потеряны, когда пользователь повесил трубку в Asterisk

Как быстро настроить HTTP-сообщение

Я использую следующее, чтобы отправить электронное письмо и пароль на мой сервер (php-скрипт). Проблема, с которой я столкнулся, – это пароль, содержащий специальный символ (в частности символ & ), который, кажется, лишается. Я полагаю, потому что он думает, что передаются его разделительные переменные. Как я могу передать этот символ без его удаления?

 let myURL = NSURL(string: "my script url here") let request = NSMutableURLRequest(URL: myURL!) request.HTTPMethod = "POST" let postString = "email=\(userEmailText)&password=\(userPasswordText)" request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding) 

Вы должны с осторожностью относиться к использованию NSURLComponents потому что NSURLQueryItem может уклониться от указанного символа, & не имеет процентного NSURLComponents от NSURLQueryItem + (который PHP будет интерпретировать как пространство в соответствии со спецификацией W3C для x-www-form-urlencoded ). Поскольку документация queryItems гласит:

Заметка

RFC 3986 указывает, какие символы должны быть закодированы в процентах в компоненте запроса URL-адреса, но не должны интерпретировать эти символы. Использование разделительных пар ключ-значение является общим соглашением, но не стандартизировано спецификацией. Таким образом, вы можете столкнуться с проблемами совместимости с другими реализациями, которые следуют этому соглашению.

Одним из примечательных примеров потенциальных проблем взаимодействия является то, как обрабатывается символ знака плюс ( + ):

Согласно RFC 3986 знак плюса является допустимым символом в запросе и не нуждается в процентном кодировании. Однако, согласно рекомендациям W3C для адресации URI , знак плюса зарезервирован как сокращенная запись для пробела в строке запроса (например, « ?greeting=hello+world ).

Это оставляет несколько альтернатив для процента, ускоряя значения, которые вы добавляете к запросу URL-адреса, если ваше значение может включать символ + :

  1. Вы можете создать свой собственный CharacterSet символов для экранирования, а затем использовать addingPercentEncodingForURLQueryValue в Swift 3:

     extension String { /// Returns a new string made from the `String` by replacing all characters not in the unreserved /// character set (as defined by RFC3986) with percent encoded characters. func addingPercentEncodingForURLQueryValue() -> String? { let allowedCharacters = CharacterSet.urlQueryValueAllowed() return addingPercentEncoding(withAllowedCharacters: allowedCharacters) } } extension CharacterSet { /// Returns the character set for characters allowed in the individual parameters within a query URL component. /// /// The query component of a URL is the component immediately following a question mark (?). /// For example, in the URL `http://www.example.com/index.php?key1=value1#jumpLink`, the query /// component is `key1=value1`. The individual parameters of that query would be the key `key1` /// and its associated value `value1`. /// /// According to RFC 3986, the set of unreserved characters includes /// /// `ALPHA / DIGIT / "-" / "." / "_" / "~"` /// /// In section 3.4 of the RFC, it further recommends adding `/` and `?` to the list of unescaped characters /// for the sake of compatibility with some erroneous implementations, so this routine also allows those /// to pass unescaped. static func urlQueryValueAllowed() -> CharacterSet { return CharacterSet(charactersIn: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~/?") } } 
  2. Alamofire использует аналогичный подход, но подходит к этому с другого направления, а именно к .urlQueryAllowed набора символов .urlQueryAllowed (который является близким, но не совсем правильным) и извлекает зарезервированные символы, идентифицированные в RFC 3986. В Swift 3:

     /// Returns a percent-escaped string following RFC 3986 for a query string key or value. /// /// RFC 3986 states that the following characters are "reserved" characters. /// /// - General Delimiters: ":", "#", "[", "]", "@", "?", "/" /// - Sub-Delimiters: "!", "$", "&", "'", "(", ")", "*", "+", ",", ";", "=" /// /// In RFC 3986 - Section 3.4, it states that the "?" and "/" characters should not be escaped to allow /// query strings to include a URL. Therefore, all "reserved" characters with the exception of "?" and "/" /// should be percent-escaped in the query string. /// /// - parameter string: The string to be percent-escaped. /// /// - returns: The percent-escaped string. 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 = "" //========================================================================================================== // // Batching is required for escaping due to an internal bug in iOS 8.1 and 8.2. Encoding more than a few // hundred Chinese characters causes various malloc error crashes. To avoid this issue until iOS 8 is no // longer supported, batching MUST be used for encoding. This introduces roughly a 20% overhead. For more // info, please refer to: // // - https://github.com/Alamofire/Alamofire/issues/206 // //========================================================================================================== if #available(iOS 8.3, *) { escaped = string.addingPercentEncoding(withAllowedCharacters: allowedCharacterSet) ?? string } else { let batchSize = 50 var index = string.startIndex while index != string.endIndex { let startIndex = index let endIndex = string.index(index, offsetBy: batchSize, limitedBy: string.endIndex) ?? string.endIndex let range = startIndex..<endIndex let substring = string.substring(with: range) escaped += substring.addingPercentEncoding(withAllowedCharacters: allowedCharacterSet) ?? substring index = endIndex } } return escaped } 

Затем вы можете использовать приведенное выше значение для процента, чтобы избежать нажатия клавиши и значения в теле запроса, например:

 let parameters = ["email" : email, "password" : password] request.httpBody = parameters .map { (key, value) in let escapedKey = key.addingPercentEncodingForURLQueryValue()! let escapedValue = value.addingPercentEncodingForURLQueryValue()! return "\(escapedKey)=\(escapedValue)" } .joined(separator: "&") .data(using: .utf8) 

Для Свифт 2 изложения вышеизложенного см. Предыдущую ревизию этого ответа .

Вам необходимо уклониться от пароля, прежде чем добавлять его в URL-адрес. Еще лучше, используйте NSURLComponents для создания вашего URL-адреса и добавления строки запроса.

Вот пример кода, который вы можете попробовать на игровой площадке.

 //: Playground - noun: a place where people can play import UIKit var n = NSURLComponents() let s = "blah" // Note that the values here should not be % encoded let item1 = NSURLQueryItem(name: "password1", value: "ab%&") let item2 = NSURLQueryItem(name: "password2", value: "ab%&%#$%^&*(") n.queryItems = [item1, item2] n.URL?.query n.queryItems?.count n.queryItems![0].name n.queryItems![0].value n.queryItems![1].name n.queryItems![1].value n.URL