如何在 swift 中 http 发布特殊字符

2023-12-22

我使用以下命令将电子邮件和密码发布到我的服务器(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可能会百分比转义有问题的字符,&,它没有%转义+字符(PHP 将其解释为空格,符合W3C 规范x-www-form-urlencoded http://www.w3.org/TR/html5/forms.html#application/x-www-form-urlencoded-encoding-algorithm). As the queryItems文档 https://developer.apple.com/documentation/foundation/nsurlcomponents/1407752-queryitems says:

Note

RFC 3986 https://www.ietf.org/rfc/rfc3986.txt指定 URL 的查询组件中哪些字符必须进行百分比编码,但不指定应如何解释这些字符。使用分隔键值对是一种常见约定,但并未由规范标准化。因此,您可能会遇到与遵循此约定的其他实现的互操作性问题。

潜在互操作性问题的一个值得注意的例子是加号 (+) 字符的处理:

根据 RFC 3986,加号是查询中的有效字符,不需要进行百分比编码。然而,根据W3C 对 URI 寻址的建议 https://www.w3.org/Addressing/URL/4_URI_Recommentations.html,加号被保留作为查询字符串中空格的速记符号(例如,?greeting=hello+world).

如果您的值可能包含+特点:

  1. 您可以构建自己的CharacterSet要转义的字符然后使用addingPercentEncodingForURLQueryValue在斯威夫特 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字符集(很接近,但不太正确),并取出 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)

对于上述内容的 Swift 2 版本,请参阅此答案的先前修订版 https://stackoverflow.com/revisions/35912606/2.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 swift 中 http 发布特殊字符 的相关文章

  • 在 PHP 中模拟 jQuery.ajax 请求

    我必须在 PHP 中模拟 AJAX 请求 就像在 jQuery 中一样 我当前的代码在这里 原始 AJAX 调用 不得修改 ajax type POST url someFile php data data success function
  • 文件修改时间检查的成本

    对于Linux下包含少量字节的文件 我只需要处理自上次处理以来发生更改的时间 我通过调用 PHP 检查文件是否被更改clearstatcache filemtime 定期 由于整个文件总是很小 因此删除对 filemtime 的调用并通过将
  • 包含包含文件的 php 文件

    这是目录结构 global php includes class bootstrap php includes init php plugins myplugin php 这是这些文件中的代码 start php require inclu
  • 如何将粘在一起的单词分开?

    我有很多命名不好的文件 videoofmegoingtoschool avi 是否有一个库或某种算法可以正确地将其分离 video of me going to school avi 我不认为那里有什么 我可以想象一个程序 它使用单词词典并
  • 用于字数计算的 Swift String 中的字数

    我想做一个程序来找出字符串中有多少个单词 用空格 逗号或其他字符分隔 然后把总数加起来 我正在制作一个平均计算器 所以我想要数据总数 然后将所有单词相加 update Xcode 10 2 x Swift 5 或更高版本 使用基础方法enu
  • 当 UITextField 已满或空时显示警报 Swift

    下面的代码中 如果 userNameTF 或 passwordTF 已满或为空 则会显示警报 IBAction func LoginBtn sender AnyObject let userName userNameTF text let
  • 创建 Facebook 测试用户时访问令牌出现问题

    我正在尝试为我的 Facebook 应用程序创建测试用户 他们在 11 月份的博客文章 http developers facebook com blog post 429 中宣布了此功能 并在此处记录了该功能 http developer
  • 如何处理 AJAX 请求中的会话超时

    我相信你们都熟悉使用 AJAX 的投票系统 嗯 看那边 我有类似的东西 当你投票赞成或反对时 它使用 AJAX 从 votes php 请求新值 问题是我正在使用会话来获取用户 ID 因此一个人只能投票一次 如果他们在页面上坐了一个小时然后
  • 所需框架与静态库

    构建现代框架 https developer apple com videos play wwdc2014 416 says 每个应用程序都有自己的自定义框架副本 https stackoverflow com a 15262463 242
  • 选取散列第 N 个元素的最快方法

    我有一个大哈希表 带有字符串索引的数组 并正在寻找一个函数quickly从中选取第一个 理想情况下也是第 N 个 元素 array shift and reset 对于我的需求来说太慢了 UPDATE 我也不是在寻找基于引用的解决方案 该函
  • 在真实设备上展示测试广告

    这是我的代码 let request GADRequest request testDevices kGADSimulatorID XXXX2F32d69CCA859FFB559D0FEA3CF6483D08A6 adView load r
  • iOS 中的构建对象文件扩展名是什么?

    当我在项目中构建java对象类时 将创建带有 class扩展名的构建文件 并且人类不可读 快速构建文件怎么样 example car java gt build gt car class 构建后会是什么 car swift gt build
  • PHP 错误警告:参数 1 应该是引用

    我 熟悉 PHP 我的朋友的网站因错误而崩溃 Warning Parameter 1 to Some function name expected to be a reference value given in public html i
  • 更改API数据输出的布局

    我是 API 集成和 PHP 的新手 我最近将 VIN 解码器集成到我的应用程序中 在输入框中输入车辆的 VIN 选择提交 然后就会显示 API 数据库中有关该车辆的所有信息 数据存储为关联数组 其中包含类别及其相应元素 例如 对于 VIN
  • 在现有 iOS 应用程序中集成 React-native(0.40.0) 后找不到 Yoga/Yoga.h 头文件

    在我的 Swift iOS 应用程序中集成 React Native 后 我无法构建 yoga Yoga h file cannot be found 我已经浏览了文档 查看了react native github页面 检查了类似问题的SO
  • 如何确保在 PHP 的“foreach”循环中重置该值?

    我正在写一个简单的 PHP 页面和一些foreach使用了循环 以下是脚本 arrs array a b c foreach arrs as arr if substr arr 0 1 b echo This is b End of fir
  • 为什么我的视图仍然以横向呈现?

    我的视图是由导航控制器控制的 因此我将导航控制器支持的方向设置为明确的纵向和纵向UpSideDown 这可以工作 但是如果调用视图时前一个视图处于横向状态 它将以横向方式呈现并保持横向状态 直到设备旋转 如何防止这种情况发生 这是我的代码
  • HTML 代码中的 PHP [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我用 HTML 代码编写了 PHP div div 但这出现在输出页面中 else print 我怎样才能让PHP执行 你的文件有一个 p
  • 使用“INSERT ... ON DUPLICATE KEY UPDATE”插入多条记录

    我的表结构 table marks 我的目标 我想用条件插入或更新多条记录 我目前正在通过此查询进行检查 第一步 SELECT FROM marks WHERE student 115 AND param 1 第二步 if records
  • 如何使用配置文件 (.ebextensions) 在 AWS Elastic Beanstalk 上安装 PHP IMAP 扩展?

    有谁知道如何使用配置文件 ebextensions 在 AWS Elastic Beanstalk 上安装和启用 PHP IMAP 扩展 我使用的是 64 位 Amazon Linux 2017 03 v2 4 0 运行 PHP 7 0 1

随机推荐

  • Windows 8.1 x64 上 Eclipse windowbuilder pugin 的设计视图提示“未知 GUI 工具包”

    我在 Windows 4 pro x64 上使用 Eclipse Kepler Release 1 x64 和 Java 7 x64 并且 Eclipse WindowBuilder 插件没有任何问题 但自从我升级到 Windows 8 1
  • 奇怪的行为动态渲染输入类型复选框的类型 Angular 2+

    Need 创建类型属性为dynamic的输入 像这样的东西
  • wpf中的字符串格式

    我有一个TextBox on WPF这与我的模型中的 float 变量有关 在 TextxBox 之后
  • 从 Bash shell 脚本发送邮件

    我正在写一个Bash http en wikipedia org wiki Bash 28Unix shell 29Mac 的 shell 脚本 通过打开自动应用程序发送电子邮件通知 该自动应用程序使用 Mail app 中的默认邮件帐户发
  • 将模块包含到项目后出现“不受支持的类文件版本 52.0”

    在 Android Studio 中创建一个空项目并包含一个纯 java 模块 该模块可以自行编译并完美运行 后 我在该模块中的每个类上都收到以下错误 Error PARSE ERROR Error unsupported class fi
  • 使用 HTML5 拖放,有没有一种方法可以在保持拖放流的同时从视图中隐藏元素

    我正在努力通过创建一个指示器 拖动元素的轮廓 来改进拖放实现 当您在网格中拖动和移动时 该指示器沿着设置的柔性网格移动 在当前的实现中 拖动的元素就位 当我放在放置目标上时 它会更新弹性顺序 我想要做的是完全隐藏元素 以便更好地视觉提示元素
  • Oracle(空间几何)查询的问题

    我正在尝试使用 SDO WITHIN DISTANCE 形成一个查询 返回给定矩形内的实体列表 我所做的查询似乎应该有效 但 Oracle 给了我一些奇怪的错误 这是查询 SELECT FROM TBLENTITYLOCATION TL I
  • 使对象的属性可迭代

    我返回一个包含具有多个属性的对象的列表 如下所示 results q fetch 5 for p in results print s s d inches tall p first name p last name p height 是否
  • Xcode 错误:Outlet 无法连接到重复内容

    经过一些搜索和编辑后 我似乎找不到解决此错误的解决方案 我正在尝试将位置搜索结果与表格链接起来 以列表形式显示搜索结果 我的地图上有详细信息按钮 该按钮与名为 FirstViewController 的 UIViewController 链
  • Google Native Client,将二进制数据从 NACL 发送到前端

    如何发送二进制数据 例如mp3 mp4数据返回前端 我知道有两种方法可以做到这一点 利用NACL提供的沙箱文件系统并在前端获取url 将数据通过PostMessage using VarArrayBuffer 如果有人能给我一个如何传递二进
  • 数据流程图和流程图有什么区别?

    我想知道为什么我们使用数据流程图而不是流程图 流程图详细说明了流程跟随 DFD 详细说明了流程data通过一个系统 在流程图中 箭头表示元素之间的控制 而不是数据 转移 元素是指令或决策 或I O等 在 DFD 中 箭头实际上是元素之间的数
  • QImage 在 PNG 中设置 alpha 透明度

    我正在尝试在另一个图像上绘制图像 并且该部分有效 但在绘制覆盖图像之前我想降低它的不透明度 这就是我遇到麻烦的地方 我的叠加图像是PNG的 它们本身有透明区域 否则它们的内容是黑色的 在 Qt 中 我循环遍历每个像素 但无法确定像素是否透明
  • 下拉值未使用 ajax 传递到控制器

    我需要使用 ajax 将下拉列表中的值传递到控制器 但显然 这不起作用 该值显示为空 我需要传递的值 kodeCabang到控制器 我该如何做这份工作 HTML代码如下 div class dropdown div
  • 具有多种形式的 Django-TinyMCE

    我正在尝试创建一个包含多个 TinyMCE 编辑器实例的 HTML 页面 编辑的数量根据要求而变化 所以我无法枚举它们并单独初始化它们 这是我的代码 视图 py from tinymce widgets import TinyMCE cla
  • 将 ASP.NET vNext 应用程序部署到 Azure 云服务

    是否可以将 ASP NET vNext Web 应用程序部署到 Azure 云服务 如果是 那么它是构建在 aspnet50 还是 aspnetcore50 框架上有什么关系吗 Azure 云服务 Visual Studio 模板即使在 2
  • git 无法拉取远程更改

    由于以下错误 我无法从远程存储库中提取更改 我正在尝试从该存储库的主分支中提取数据 c supportal gt git pull error cannot lock ref refs remotes origin KANBAN unabl
  • Jaxb 解组不起作用

    我有这个 xml 文件
  • 如何为 iOS 分发创建 P12 证书

    我们有一款 iOS 应用程序 其推送通知证书已过期 我们正在尝试创建一个新的证书 我已在配置门户 ios developer cer ios distribution cer 中创建了新证书并下载了它们 我按照指示进行在 Stack Ove
  • 如何禁用 EditText 软件键盘上的“下一步”按钮(替换为“完成”按钮)

    我的 Android 应用程序中有一堆 EditText 每个 EditText 的 InputMethod 设置为 numberSigned 我的目标设备没有硬件键盘 而是使用软件键盘进行数字输入 Android 将输入框右侧的标准 完成
  • 如何在 swift 中 http 发布特殊字符

    我使用以下命令将电子邮件和密码发布到我的服务器 php 脚本 我遇到的问题是密码包含一个特殊字符 特别是 符号 似乎正在被剥离 我认为是因为它认为它的分隔变量被传递 我怎样才能传递这个字符而不剥离它 let myURL NSURL stri