Skip to content

Commit 2b5cf48

Browse files
authored
Merge pull request #1676 from maksimorlovich/sr-7338
2 parents 99e10bb + 739b29b commit 2b5cf48

File tree

6 files changed

+52
-8
lines changed

6 files changed

+52
-8
lines changed

Foundation/URLSession/Configuration.swift

+13-3
Original file line numberDiff line numberDiff line change
@@ -100,19 +100,29 @@ internal extension URLSession._Configuration {
100100

101101
// Configure NSURLRequests
102102
internal extension URLSession._Configuration {
103-
func configure(request: URLRequest) {
103+
func configure(request: URLRequest) -> URLRequest {
104104
var request = request
105105
httpAdditionalHeaders?.forEach {
106106
guard request.value(forHTTPHeaderField: $0.0) == nil else { return }
107107
request.setValue($0.1, forHTTPHeaderField: $0.0)
108108
}
109+
return setCookies(on: request)
109110
}
110-
func setCookies(on request: URLRequest) {
111+
112+
func setCookies(on request: URLRequest) -> URLRequest {
113+
var request = request
111114
if httpShouldSetCookies {
112-
//TODO: Ask the cookie storage what cookie to set.
115+
if let cookieStorage = self.httpCookieStorage, let url = request.url, let cookies = cookieStorage.cookies(for: url) {
116+
let cookiesHeaderFields = HTTPCookie.requestHeaderFields(with: cookies)
117+
if let cookieValue = cookiesHeaderFields["Cookie"], cookieValue != "" {
118+
request.addValue(cookieValue, forHTTPHeaderField: "Cookie")
119+
}
120+
}
113121
}
122+
return request
114123
}
115124
}
125+
116126
// Cache Management
117127
private extension URLSession._Configuration {
118128
func cachedResponse(forRequest request: URLRequest) -> CachedURLResponse? {

Foundation/URLSession/URLSession.swift

+2-3
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ fileprivate func nextSessionIdentifier() -> Int32 {
185185
public let NSURLSessionTransferSizeUnknown: Int64 = -1
186186

187187
open class URLSession : NSObject {
188-
fileprivate let _configuration: _Configuration
188+
internal let _configuration: _Configuration
189189
fileprivate let multiHandle: _MultiHandle
190190
fileprivate var nextTaskIdentifier = 1
191191
internal let workQueue: DispatchQueue
@@ -384,8 +384,7 @@ fileprivate extension URLSession {
384384
}
385385
func createConfiguredRequest(from request: URLSession._Request) -> URLRequest {
386386
let r = request.createMutableURLRequest()
387-
_configuration.configure(request: r)
388-
return r
387+
return _configuration.configure(request: r)
389388
}
390389
}
391390
extension URLSession._Request {

Foundation/URLSession/URLSessionConfiguration.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ open class URLSessionConfiguration : NSObject, NSCopying {
4343
self.httpShouldSetCookies = true
4444
self.httpCookieAcceptPolicy = .onlyFromMainDocumentDomain
4545
self.httpMaximumConnectionsPerHost = 6
46-
self.httpCookieStorage = nil
46+
self.httpCookieStorage = HTTPCookieStorage.shared
4747
self.urlCredentialStorage = nil
4848
self.urlCache = nil
4949
self.shouldUseExtendedBackgroundIdleMode = false

Foundation/URLSession/http/HTTPURLProtocol.swift

+3
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,9 @@ internal class _HTTPURLProtocol: _NativeProtocol {
7878
fatalError("No URL in request.")
7979
}
8080
easyHandle.set(url: url)
81+
let session = task?.session as! URLSession
82+
let _config = session._configuration
83+
easyHandle.set(sessionConfig: _config)
8184
easyHandle.setAllowedProtocolsToHTTPAndHTTPS()
8285
easyHandle.set(preferredReceiveBufferSize: Int.max)
8386
do {

Foundation/URLSession/libcurl/EasyHandle.swift

+29-1
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ internal final class _EasyHandle {
5757
fileprivate var pauseState: _PauseState = []
5858
internal var timeoutTimer: _TimeoutSource!
5959
internal lazy var errorBuffer = [UInt8](repeating: 0, count: Int(CFURLSessionEasyErrorSize))
60+
internal var _config: URLSession._Configuration? = nil
61+
internal var _url: URL? = nil
6062

6163
init(delegate: _EasyHandleDelegate) {
6264
self.delegate = delegate
@@ -154,10 +156,16 @@ extension _EasyHandle {
154156
/// URL to use in the request
155157
/// - SeeAlso: https://curl.haxx.se/libcurl/c/CURLOPT_URL.html
156158
func set(url: URL) {
159+
_url = url
157160
url.absoluteString.withCString {
158161
try! CFURLSession_easy_setopt_ptr(rawHandle, CFURLSessionOptionURL, UnsafeMutablePointer(mutating: $0)).asError()
159162
}
160163
}
164+
165+
func set(sessionConfig config: URLSession._Configuration) {
166+
_config = config
167+
}
168+
161169
/// Set allowed protocols
162170
///
163171
/// - Note: This has security implications. Not limiting this, someone could
@@ -512,8 +520,8 @@ fileprivate extension _EasyHandle {
512520
///
513521
/// - SeeAlso: <https://curl.haxx.se/libcurl/c/CURLOPT_HEADERFUNCTION.html>
514522
func didReceive(headerData data: UnsafeMutablePointer<Int8>, size: Int, nmemb: Int, contentLength: Double) -> Int {
523+
let buffer = Data(bytes: data, count: size*nmemb)
515524
let d: Int = {
516-
let buffer = Data(bytes: data, count: size*nmemb)
517525
switch delegate?.didReceive(headerData: buffer, contentLength: Int64(contentLength)) {
518526
case .some(.proceed): return size * nmemb
519527
case .some(.abort): return 0
@@ -525,8 +533,28 @@ fileprivate extension _EasyHandle {
525533
return 0
526534
}
527535
}()
536+
setCookies(headerData: buffer)
528537
return d
529538
}
539+
540+
fileprivate func setCookies(headerData data: Data) {
541+
guard let config = _config, config.httpCookieAcceptPolicy != HTTPCookie.AcceptPolicy.never else { return }
542+
guard let headerData = String(data: data, encoding: String.Encoding.utf8) else { return }
543+
//Convert headerData from a string to a dictionary.
544+
//Ignore headers like 'HTTP/1.1 200 OK\r\n' which do not have a key value pair.
545+
let headerComponents = headerData.split { $0 == ":" }
546+
var headers: [String: String] = [:]
547+
//Trim the leading and trailing whitespaces (if any) before adding the header information to the dictionary.
548+
if headerComponents.count > 1 {
549+
headers[String(headerComponents[0].trimmingCharacters(in: .whitespacesAndNewlines))] = headerComponents[1].trimmingCharacters(in: .whitespacesAndNewlines)
550+
}
551+
let cookies = HTTPCookie.cookies(withResponseHeaderFields: headers, for: _url!)
552+
guard cookies.count > 0 else { return }
553+
if let cookieStorage = config.httpCookieStorage {
554+
cookieStorage.setCookies(cookies, for: _url, mainDocumentURL: nil)
555+
}
556+
}
557+
530558
/// This callback function gets called by libcurl when it wants to send data
531559
/// it to the network.
532560
///

TestFoundation/TestURLSession.swift

+4
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ class TestURLSession : LoopbackServerTest {
3838
("test_dataTaskWithSharedDelegate", test_dataTaskWithSharedDelegate),
3939
// ("test_simpleUploadWithDelegate", test_simpleUploadWithDelegate), - Server needs modification
4040
("test_concurrentRequests", test_concurrentRequests),
41+
("test_disableCookiesStorage", test_disableCookiesStorage),
42+
("test_cookiesStorage", test_cookiesStorage),
43+
("test_setCookies", test_setCookies),
44+
("test_dontSetCookies", test_dontSetCookies),
4145
]
4246
}
4347

0 commit comments

Comments
 (0)