URLRequest 相等性不包括 httpBody
URLRequest equality doesn't include httpBody
概览
有2个URLRequest
,一个有httpBody
,一个没有httpBody
。
然而,当比较时,它表明两者是相等的。
问题
这是预期的行为还是我遗漏了什么?
代码
let url = URL(string: "www.somevalidURL.com")!
var r1 = URLRequest(url: url)
r1.addValue("Content-Type", forHTTPHeaderField: "application/json; charset=utf-8")
r1.httpBody = makeBody(withParameters: ["email" : "a@b.com"])
var r2 = URLRequest(url: url)
r2.addValue("Content-Type", forHTTPHeaderField: "application/json; charset=utf-8")
if r1 == r2 {
print("requests are equal")
}
else {
print("requests are not equal")
}
if r1.httpBody == r2.httpBody {
print("body is equal")
}
else {
print("body is not equal")
}
func makeBody(withParameters bodyParameters: [String : Any]?) -> Data? {
guard let bodyParameters = bodyParameters,
!bodyParameters.isEmpty else {
return nil
}
let body : Data?
do {
body = try JSONSerialization.data(withJSONObject: bodyParameters,
options: .prettyPrinted)
}
catch {
print("Error in creating Web Service Body = \(error)")
body = nil
}
return body
}
输出
requests are equal
body is not equal
Xcode 10
Swift版本:4.2
URLRequest
是Foundation类型NSURLRequest
的Swift覆盖类型,这样==
最终调用的isEqual()
方法
NSURLRequest
.
Foundation 库是针对非 Apple 平台的开源,并且在
NSURLRequest.swift#L252 我们发现:
open override func isEqual(_ object: Any?) -> Bool {
//On macOS this fields do not determine the result:
//allHTTPHeaderFields
//timeoutInterval
//httBody
//networkServiceType
//httpShouldUsePipelining
guard let other = object as? NSURLRequest else { return false }
return other === self
|| (other.url == self.url
&& other.mainDocumentURL == self.mainDocumentURL
&& other.httpMethod == self.httpMethod
&& other.cachePolicy == self.cachePolicy
&& other.httpBodyStream == self.httpBodyStream
&& other.allowsCellularAccess == self.allowsCellularAccess
&& other.httpShouldHandleCookies == self.httpShouldHandleCookies)
所以这似乎是故意的。
如果你来到这里想知道为什么你相同的 URLRequest
不像我一样彼此不相等,我发现原因是 URLRequest
equatable 实现区分 httpBody
设置为 nil 或默认为 nil。
如果我们执行以下操作:
let request = URLRequest(url: URL(string: "test.com"))
var expectedRequest = URLRequest(url: URL(string: "test.com"))
expectedRequest.httpBody = nil
然后:
request == expectedRequest //false
print(request.httpBody) // nil
request.httpBody = nil
request == expectedRequest //true
将 httpBody
显式设置为 nil
将解决此问题。事实上 body 是什么并不重要,重要的是它已经明确设置了。
request.httpBody = Data()
request == expectedRequest //true
可能的解释
正如 Martin 正确指出的那样 Swift's source code 不包括 httpBody。但是,所有属性(在 link 中)都是相等的(并且都可以作为 NSURLRequests 进行转换)不会 return true
(请参阅下面的 lldb 输出)。我只能假定 linked 代码被覆盖以包含另一个 属性 并且当 didSet
或 willSet
在 httpBody
上调用时会修改此代码
概览
有2个URLRequest
,一个有httpBody
,一个没有httpBody
。
然而,当比较时,它表明两者是相等的。
问题
这是预期的行为还是我遗漏了什么?
代码
let url = URL(string: "www.somevalidURL.com")!
var r1 = URLRequest(url: url)
r1.addValue("Content-Type", forHTTPHeaderField: "application/json; charset=utf-8")
r1.httpBody = makeBody(withParameters: ["email" : "a@b.com"])
var r2 = URLRequest(url: url)
r2.addValue("Content-Type", forHTTPHeaderField: "application/json; charset=utf-8")
if r1 == r2 {
print("requests are equal")
}
else {
print("requests are not equal")
}
if r1.httpBody == r2.httpBody {
print("body is equal")
}
else {
print("body is not equal")
}
func makeBody(withParameters bodyParameters: [String : Any]?) -> Data? {
guard let bodyParameters = bodyParameters,
!bodyParameters.isEmpty else {
return nil
}
let body : Data?
do {
body = try JSONSerialization.data(withJSONObject: bodyParameters,
options: .prettyPrinted)
}
catch {
print("Error in creating Web Service Body = \(error)")
body = nil
}
return body
}
输出
requests are equal
body is not equal
Xcode 10
Swift版本:4.2
URLRequest
是Foundation类型NSURLRequest
的Swift覆盖类型,这样==
最终调用的isEqual()
方法
NSURLRequest
.
Foundation 库是针对非 Apple 平台的开源,并且在 NSURLRequest.swift#L252 我们发现:
open override func isEqual(_ object: Any?) -> Bool {
//On macOS this fields do not determine the result:
//allHTTPHeaderFields
//timeoutInterval
//httBody
//networkServiceType
//httpShouldUsePipelining
guard let other = object as? NSURLRequest else { return false }
return other === self
|| (other.url == self.url
&& other.mainDocumentURL == self.mainDocumentURL
&& other.httpMethod == self.httpMethod
&& other.cachePolicy == self.cachePolicy
&& other.httpBodyStream == self.httpBodyStream
&& other.allowsCellularAccess == self.allowsCellularAccess
&& other.httpShouldHandleCookies == self.httpShouldHandleCookies)
所以这似乎是故意的。
如果你来到这里想知道为什么你相同的 URLRequest
不像我一样彼此不相等,我发现原因是 URLRequest
equatable 实现区分 httpBody
设置为 nil 或默认为 nil。
如果我们执行以下操作:
let request = URLRequest(url: URL(string: "test.com"))
var expectedRequest = URLRequest(url: URL(string: "test.com"))
expectedRequest.httpBody = nil
然后:
request == expectedRequest //false
print(request.httpBody) // nil
request.httpBody = nil
request == expectedRequest //true
将 httpBody
显式设置为 nil
将解决此问题。事实上 body 是什么并不重要,重要的是它已经明确设置了。
request.httpBody = Data()
request == expectedRequest //true
可能的解释
正如 Martin 正确指出的那样 Swift's source code 不包括 httpBody。但是,所有属性(在 link 中)都是相等的(并且都可以作为 NSURLRequests 进行转换)不会 return true
(请参阅下面的 lldb 输出)。我只能假定 linked 代码被覆盖以包含另一个 属性 并且当 didSet
或 willSet
在 httpBody
上调用时会修改此代码