1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
|
// Foundation/URLSession/Configuration.swift - URLSession & libcurl
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
// -----------------------------------------------------------------------------
///
/// These are libcurl helpers for the URLSession API code.
/// - SeeAlso: https://curl.haxx.se/libcurl/c/
/// - SeeAlso: URLSession.swift
///
// -----------------------------------------------------------------------------
#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
import SwiftFoundation
#else
import Foundation
#endif
internal extension URLSession {
/// This is an immutable / `struct` version of `URLSessionConfiguration`.
struct _Configuration : Sendable {
/// identifier for the background session configuration
let identifier: String?
/// default cache policy for requests
let requestCachePolicy: URLRequest.CachePolicy
/// default timeout for requests. This will cause a timeout if no data is transmitted for the given timeout value, and is reset whenever data is transmitted.
let timeoutIntervalForRequest: TimeInterval
/// default timeout for requests. This will cause a timeout if a resource is not retrievable within a given timeout.
let timeoutIntervalForResource: TimeInterval
/// type of service for requests.
let networkServiceType: URLRequest.NetworkServiceType
/// allow request to route over cellular.
let allowsCellularAccess: Bool
/// allows background tasks to be scheduled at the discretion of the system for optimal performance.
let isDiscretionary: Bool
/// The proxy dictionary, as described by <CFNetwork/CFHTTPStream.h>
// TODO: It would be nice to have the type not be AnyHashable, but for now we need this for source compatibility.
nonisolated(unsafe) let connectionProxyDictionary: [AnyHashable : Any]?
/// Allow the use of HTTP pipelining
let httpShouldUsePipelining: Bool
/// Allow the session to set cookies on requests
let httpShouldSetCookies: Bool
/// Policy for accepting cookies. This overrides the policy otherwise specified by the cookie storage.
let httpCookieAcceptPolicy: HTTPCookie.AcceptPolicy
/// Specifies additional headers which will be set on outgoing requests.
/// Note that these headers are added to the request only if not already present.
let httpAdditionalHeaders: [String : String]?
/// The maximum number of simultaneous persistent connections per host
let httpMaximumConnectionsPerHost: Int
/// The cookie storage object to use, or nil to indicate that no cookies should be handled
let httpCookieStorage: HTTPCookieStorage?
/// The credential storage object, or nil to indicate that no credential storage is to be used
let urlCredentialStorage: URLCredentialStorage?
/// The URL resource cache, or nil to indicate that no caching is to be performed
let urlCache: URLCache?
/// Enable extended background idle mode for any tcp sockets created.
let shouldUseExtendedBackgroundIdleMode: Bool
let protocolClasses: [AnyClass]?
}
}
internal extension URLSession._Configuration {
init(URLSessionConfiguration config: URLSessionConfiguration) {
identifier = config.identifier
requestCachePolicy = config.requestCachePolicy
timeoutIntervalForRequest = config.timeoutIntervalForRequest
timeoutIntervalForResource = config.timeoutIntervalForResource
networkServiceType = config.networkServiceType
allowsCellularAccess = config.allowsCellularAccess
isDiscretionary = config.isDiscretionary
connectionProxyDictionary = config.connectionProxyDictionary
httpShouldUsePipelining = config.httpShouldUsePipelining
httpShouldSetCookies = config.httpShouldSetCookies
httpCookieAcceptPolicy = config.httpCookieAcceptPolicy
httpAdditionalHeaders = config.httpAdditionalHeaders.map { convertToStringString(dictionary: $0) }
httpMaximumConnectionsPerHost = config.httpMaximumConnectionsPerHost
httpCookieStorage = config.httpCookieStorage
urlCredentialStorage = config.urlCredentialStorage
urlCache = config.urlCache
shouldUseExtendedBackgroundIdleMode = config.shouldUseExtendedBackgroundIdleMode
protocolClasses = config.protocolClasses
}
}
// Configure NSURLRequests
internal extension URLSession._Configuration {
func configure(request: URLRequest) -> URLRequest {
return setCookies(on: request)
}
func setCookies(on request: URLRequest) -> URLRequest {
var request = request
if httpShouldSetCookies {
if let cookieStorage = self.httpCookieStorage, let url = request.url, let cookies = cookieStorage.cookies(for: url) {
let cookiesHeaderFields = HTTPCookie.requestHeaderFields(with: cookies)
if let cookieValue = cookiesHeaderFields["Cookie"], cookieValue != "" {
request.setValue(cookieValue, forHTTPHeaderField: "Cookie")
}
}
}
return request
}
}
// Cache Management
private extension URLSession._Configuration {
func cachedResponse(forRequest request: URLRequest) -> CachedURLResponse? {
//TODO: Check the policy & consult the cache.
// There's more detail on how this should work here:
// <https://developer.apple.com/library/prerelease/ios/documentation/Cocoa/Reference/Foundation/Classes/NSURLRequest_Class/index.html#//apple_ref/swift/enum/c:@E@URLRequestCachePolicy>
switch requestCachePolicy {
default: return nil
}
}
}
private func convertToStringString(dictionary: [AnyHashable:Any]) -> [String: String] {
//TODO: There's some confusion about [NSObject:AnyObject] vs. [String:String] for headers.
// C.f. <https://github.com/apple/swift-corelibs-foundation/pull/287>
var r: [String: String] = [:]
dictionary.forEach {
let k = getString(from: $0.key)
let v = getString(from: $0.value)
r[k] = v
}
return r
}
private func getString(from obj: Any) -> String {
if let string = obj as? String {
return string
} else {
return String(describing: obj as! NSString)
}
}
|