Networking
SAPURLSession
SAPURLSession
is an HTTP networking library.
The SAPURLSession
component provides an API around the native URLSession, which is similar to the URLSession data task convenience methods.
The SAPURLSession
component can be used to communicate with an HTTP server.
It also provides support for modifying the HTTP request before it is sent, and the HTTP response prior to being returned to the caller.
You can register multiple request and response observers to support various scenarios, like authentication, for example.
The primary usage scenario and workflow for this component is that the application:
- Creates an
SAPURLSession
instance - Uses other SDK components to register observers, to handle authentication, for example.
- Passes the configured
SAPURLSession
to SDK components that require HTTP communication, but do not handle aspects such as authentication. In addition, the application can also exchange HTTP messages with this component if required.
Note: The SAPURLSession
component does not replace URLSession, but adds additional functionality to it.
To use it efficiently, first familiarize yourself with the URLSession API.
Note: The streamTask
APIs are not supported through SAPURLSession
.
For additional information, see: Using URL Session.
Usage
To use the SAPURLSession
component:
- Create an
SAPURLSession
instance. - Exchange HTTP messages with an HTTP server.
- Use observers to modify the HTTP request or the response.
Create an SAPURLSession
You have different options to create an SAPURLSession
instance. The simplest way is to initialize it using defaults.
let sapSession = SAPURLSession()
Note: When using the default initializer, the SAPURLSession
initializes the underlying URLSession
with the following parameters:
- configuration:
URLSessionConfiguration.default
- delegate: nil
- delegateQueue: nil
You can provide your own URLSessionConfiguration
object to configure the SAPURLSession
for your needs.
This allows tweaking the connectivity of your app on the networking layer, including network timeouts, supported TLS version, etc.
You can also use this to indicate the desired quality of service for your app (or parts of the network traffic of your app) in your enterprise WiFi network and prioritize network traffic across your apps and networks in a Fastlane enabled infrastructure.
If you need to be informed about URLSession
events, implement the SAPURLSessionDelegate
APIs, and pass this delegate as a parameter.
You can register this delegate also to obtain the backing URLSessionTask
once it is initialized.
let sapSession = SAPURLSession(delegate: self)
Exchange HTTP messages
Once you have created an SAPURLSession
you can use it to exchange messages.
Depending on your use case, you can either directly use this session or pass it to other SDK components that require an SAPURLSession
instance for communication.
The SAPURLSession
class exposes methods for sending short requests to the server, and it supports the downloading and uploading of large payloads as well
Sending short requests
To send short requests to the server, use the func dataTask(with:completionHandler:)
method to instantiate
an SAPURLSessionTask
instance. You must start the task by calling its resume()
method.
let sapSession = SAPURLSession()
let url = URL(string: "<#URL String#>")!
let task = sapSession.dataTask(with: url) { data, response, error in
if let httpResponse = response as? HTTPURLResponse {
// process response, inspect error message
}
}
task.resume()
Downloading
You can download large amounts of data using the func dataTask(with:receivedResponseHandler:receivedDataHandler:completionHandler:)
.
The downloaded data is retrieved in batches via the receivedDataHandler
handler.
let sapSession = SAPURLSession()
let url = URL(string: "<#URL String#>")!
let request = URLRequest(url: url)
let dataTask = sapSession.dataTask(with: request, receivedResponseHandler: { response in
// process response
}, receivedDataHandler: { data in
// process data batches
}) { error in
// error handling
}
dataTask.resume()
Uploading
To upload larger amounts of data to a server, use the func uploadTask(withStreamedRequest:needNewBodyStream:completionHandler:)
as follows:
let sapSession = SAPURLSession()
let url = URL(string: "<#URL String#>")!
var request = URLRequest(url: url)
request.httpMethod = SAPURLSession.HTTPMethod.put
let uploadTask = sapSession.uploadTask(withStreamedRequest: request, needNewBodyStream: {
return InputStream(fileAtPath: path)
}) { data, response, error in
// error handling, response processing
if let httpResponse = response as? HTTPURLResponse {
// process response
}
}
uploadTask.resume()
Using Observers
You can use observers to modify the HTTP requests before they are sent, and to modify the HTTP responses after they have been received.
For that you can register the SAPURLSessionObserving
implementations on the SAPURLSession
, so that the registered observers are called each time this session is used to exchange HTTP messages:
class MySAPURLSessionObserver: SAPURLSessionObserving {
func sapURLSession(_ session: SAPURLSession, task: SAPURLSessionTask, willSend request: URLRequest, completionHandler: @escaping (SAPURLSession.RequestDisposition) -> Void) -> Void {
var updatedRequest = request
updatedRequest.addValue("MyHeaderValue", forHTTPHeaderField: "MyHeaderKey")
completionHandler(.allow(updatedRequest))
}
func func sapURLSession(_ session: SAPURLSession, dataTask: SAPURLSessionTask, didReceive response: URLResponse, completionHandler: @escaping (SAPURLSession.ResponseDisposition) -> Void) {
completionHandler(.allow(response))
}
}
let sapSession = SAPURLSession()
let observer = MySAPURLSessionObserver()
sapSession.register(observer)
Note: When implementing the SAPURLSessionObserving
protocol you have the option to implement only the methods you want to use. This is possible because all of them have default implementation via protocol extension. The compiler will not signal errors if you have a typo in the method implementation! Because there is a default implementation, it will call the one that matches. The best way to implement these methods is to use Xcode’s code completion.
The observers have all of the delegate methods (except URLSessionStreamDelegate
) on them, with completion handler. See the API documentation for further information.
The registered observers are called in the registration order. They contain asynchronous methods, which means that their completionHandler
must be called. The SAPURLSessionDelegate
is called after the observers.
When a delegate with completionHandler
is called, the SAPURLSession
will start to call the observers in the registration order. This iteration continues until one of the observer responds with a non-default value (such as an error response or authentication challenge response). After a non-default response from an observer, the iteration is stopped, and the rest of the observers, including the delegate (SAPURLSessionDelegate
), will not be called.
The registered observer can be called multiple times during a single request. This is because of the possibility of one observer starting an internal request. Use the SAPURLSession.context
to mark your requests or find a different way to identify whether or not your observer has to run for the given iteration. (The SAPURLSession.context
is a simple [String: Any]
dictionary.)
Calling the completionHandler
There are different dispositions for different observer methods with which the completionHandler must be called. See the API documentation for more information.
SAPURLSession.RequestDisposition
SAPURLSession.ResponseDisposition
SAPURLSession.CancellableDisposition
SAPURLSession.DataDisposition
SAPURLSession.AuthChallengeDisposition
SAPURLSession.HTTPRedirectDisposition
SAPURLSession.InputStreamDisposition
SAPURLSession.CacheResponseDisposition
SAPURLSession.DelayedRequestDisposition
Authentication challenge
The existing SAPURLSession
implementation augments URLSession
. URLSession
provides the means for basic authentication, therefore the SDK does not expose any new functionality (API, observers, etc.).
To receive authentication challenges, clients must pass in an SAPURLSessionDelegate
when initializing the SAPURLSession
.
let sapSession = SAPURLSession(delegate: self)
The provided delegate implements the func sapURLSession(session:dataTask:didReceive:completionHandler:)
delegate method, and handles the challenge accordingly.
For more information about this delegate, please see the Apple Reference: https://developer.apple.com/reference/foundation/urlsessiontaskdelegate/1411595-urlsession
Basic Authentication
The credential is based on username/password in the func sapURLSession(session:dataTask:didReceive:completionHandler:)
delegate method.
This example creates a URLCredential
from a username and password:
let urlCredential = URLCredential(user: "<#Username#>", password: "<#Password#>", persistence: .none)
Certificate Authentication
The credential is based on a certificate in the func sapURLSession(session:dataTask:didReceive:completionHandler:)
delegate method.
This example creates a URLCredential
from a PKCS#12
file:
let path = Bundle.main.path(forResource: <#Filename#>, ofType: "p12")!
let data = NSData(contentsOfFile:path)! as Data
var items: CFArray?
let certOptions:NSDictionary = [kSecImportExportPassphrase as NSString:<#password#> as NSString]
var urlCredential: URLCredential!
var securityError = errSecSuccess
securityError = SecPKCS12Import(data as NSData, certOptions, &items)
switch securityError {
case errSecDecode:
// Either the PKCS#12 formatted blob can't be read or it is malformed.
case errSecAuthFailed:
// An incorrect password was passed, or data in the container got damaged.
default:
let certItems = (items! as Array)
let dict = certItems.first! as! Dictionary<String, AnyObject>
let certChain = dict[kSecImportItemCertChain as String] as? Array<SecTrust>
let identity = dict[kSecImportItemIdentity as String] as! SecIdentity?
urlCredential = URLCredential(identity: identity!, certificates: certChain!, persistence: URLCredential.Persistence.forSession)
}
return urlCredential
Communicating with SAPcpms services
SAPcpms services need a X-SMP-APPID
header for the requests, which sets up the session to identify the app that is connecting to SAPcpms.
In addition, an optional device ID can also be sent in a X-SMP-DEVICEID
header.
These headers can be set using SAPcpmsObserver
.
The code sample below demonstrates how to register the observer to an SAPURLSession
instance.
let applicationID = <#Application ID#>
let deviceID = <#Device ID#>
let applicationVersion = <#Application version#>
let sapcpmsObserver = SAPcpmsObserver(applicationID: applicationID, deviceID: deviceID, applicationVersion: applicationVersion)
sapSession.register(sapcpmsObserver)
CSRF protection of SAPcpms services
Note: If you want to use CSRF protection for your application, you must first enable this feature in the SAP Mobile Services cockpit. See: Defining Applications.
If the CSRF protection is enabled on SAPcpms, you need to send a X-CSRF-Token
header for the modifying HTTP requests. The CSRFTokenObserver
can automatically handle this for every request.
Basic usage
The code sample below demonstrates how to register the observer to an SAPURLSession
instance if you have one root URL for every CSRF token request.
The rootUrl
parameter is the URL from which the CSRF token will be requested.
let urlSession: SAPURLSession = <#SAPURLSession instance#>
let rootUrl: URL = <#your root URL#>
let csrfTokenObserver = CSRFTokenObserver(rootUrl: rootUrl)
urlSession.register(csrfTokenObserver)
Advanced usage
If you have multiple CSRF protected backends and these backends accept different CSRF tokens, you must implement the CSRFTokenURLProviding
protocol to provide a CSRF URL for different request URLs. For token storing, the CSRFTokenStoring
protocol is used.
class myCSRFTokenURLProvider: CSRFTokenURLProviding {
func csrfTokenURL(for: URL) -> URL {
// TODO: implement custom logic to create token URL from the request URL
return <#token URL#>
}
}
public class myCSRFTokenStore: CSRFTokenStoring {
/// Stores the CSRF token for the given URL.
public func store(token: String, for url: URL) {
// TODO: implement
}
/// Retrieves the CSRF token for the given URL.
public func token(for url: URL) -> String? {
// TODO: implement
return <#token URL#>
}
/// Deletes the CSRF token for the given URL.
public func deleteToken(for url: URL) {
// TODO: implement
}
}
let csrfTokenObserver = CSRFTokenObserver(tokenUrlProvider: myCSRFTokenURLProvider, tokenStore: myCSRFTokenStore)
urlSession.register(csrfTokenObserver)
For more information on how this protection works, see: Using Custom Header Protection
NetworkActivityIndicatorController
Controls whether the Network Activity Indicator should be showed or hidden.
When you use NetworkActivityIndicatorObserver
, never modify the NetworkActivityIndicatorController
directly, but use the observer class instead.
The component uses an internal counter. When this counter has a positive value, the indicator is visible.
NetworkActivityIndicatorObserver
Shows and hides the Network Activity Indicator automatically based on the states of requests in the URLSession. It presents the indicator when a request starts, and hides it when the request finished.
The state of the ActivityIndicator is shared among all the URLSession and observer instances.
The observer uses the NetworkActivityIndicatorController
to control the presentation of the indicator.
When you use this observer, never modify the Network Activity Indicator
directly, but use the NetworkActivityIndicatorController
instead.
For example:
let indicatorObserver = NetworkActivityIndicatorObserver()
sapURLSession.register(indicatorObserver)
Add correlation ID to requests
Correlation IDs are used to identify and track requests on the server side.
Adding CorrelationObserver
to an SAPURLSession
will automatically generate a unique correlation ID and add it to each request. In case the SAPURLSessionTask
is resent, the same correlation ID will be used.
The code sample below demonstrates how to register the observer to an SAPURLSession
instance.
let correlationObserver = CorrelationObserver()
sapURLSession.register(correlationObserver)
Detect blocked users
You can block users using SAP Mobile Services if you don’t want them to have further access to your resources.
To be able to detect such action in your application, use the SAPcpmsUserBlockedObserver
.
let blockDetectionObserver = SAPcpmsUserBlockedObserver { error in
// This block of code is invoked when a blocked response is detected.
// The error is a `SAPcpmsUserBlockedError` describing the specific case.
<#Notify the user about the blocking and run some clean-up code.#>
}
sapURLSession.register(blockDetectionObserver)
Add Accept-Language header to requests
Adding LanguageObserver
to an SAPURLSession
will automatically set the Accept-Language
headers to each HTTP request. By default it uses the device language, but you can also force a language by adding the language
parameter to the initializer.
let urlSession: SAPURLSession = <#SAPURLSession instance#>
let languageObserver = LanguageObserver()
urlSession.register(languageObserver)
Clear all authentication credentials
There are several steps required to remove all authentication credentials.
After onboarding remove cookies from HTTPCookieStorage and remove all cached responses from URLCache
sapURLSession.configuration.urlCache?.removeAllCachedResponses()
sapURLSession.configuration.httpCookieStorage?.removeCookies(since: .distantPast)
Credential store
Remove all keys with the prefix of the authentication process.
Web Content Based CPms Destinations
This section highlights how each iOS web view can be used with SAP CPms destinations that contain web-based contents (e.g. an HTML web page). SAPURLSession
provides the following APIs for this purpose:
public func configure(_ request: URLRequest, completionHandler: @escaping (URLRequest?, Error?) -> Void)
public func configure(_ webView: WKWebView, completionHandler: @escaping (Error?) -> Void)
public func configure(_ cookieStore: HTTPCookieStorage, completionHandler: @escaping (Error?) -> Void)
public func configure(_ cookieStore: WKHTTPCookieStore, completionHandler: @escaping (Error?) -> Void)
public func close(completionHandler: @escaping () -> Void)
A convenience API is also available on WKWebView
:
public func configure(with urlSession: SAPURLSession, completionHandler: @escaping () -> Void)
WKWebView
WKWebView
supports both custom cookie configuration and loading URL requests.
Customizing cookies can be useful for web session management. The code snippet below shows how to do this using the convenience API.
let sapURLSession = SAPURLSession()
let webView = WKWebView(frame: .zero)
webView.configure(from: sapURLSession) {
// cookies have been set
}
Configuring a URLRequest
instance should be used at all times because CPms destinations require special headers in the requests.
let sapURLSession = SAPURLSession()
sapURLSession.configure(request) { newRequest, error in
switch (newRequest, error) {
case (nil, let error?):
// error handling
case (let newRequest?, nil):
// load newRequest
default:
fatalError("Invalid state!")
}
}
ASWebAuthenticationSession, SFSafariViewController
Neither ASWebAuthenticationSession
nor SFSafariViewController
were designed to be customized. Both of these web views support loading URLs – not URLRequest
s. Manual cookie configuration is a bit tricky as well. Both web views use the shared cookie storage, which leads to the conclusion that if cookie management is a requirement, the shared store should be configured. Use the corresponding configure(_:)
API for this purpose. After a web session is over (the web view is closed), the original cookies should be reset for security reasons: use the close(completionHandler:)
API in this case.
SFAuthenticationSession, UIWebView
Both UIWebView
and SFAuthenticationSession
are removed.
Using Combine DataTaskPublisher in SAPURLSession
Similar to URLSession, SAPURLSession offers a Combine publisher, SAPURLSession.DataTaskPublisher, which publishes the results of fetching data from a URL or URLRequest. You create this publisher with the method dataTaskPublisher(for:).
public func dataTaskPublisher(for urlRequest: URLRequest) -> DataTaskPublisher
public func dataTaskPublisher(for url: URL) -> DataTaskPublisher
When the task completes, it publishes either:
A tuple that contains the fetched data and a URLResponse, if the task succeeds.
An error, if the task fails.
Unlike the completion handler passed to dataTask(with:completionHandler:), the types received by your code aren’t optionals, since the publisher has already unwrapped the data or error.
When using SAPURLSession’s completion handler-based code, you need to do all your work in the handler closure: error-handling, data parsing, and so on. When you instead use the data task publisher, you can move many of these responsibilities to Combine operators.
When a data task completes successfully, it delivers a block of raw Data to your app. Most apps need to convert this data to their own types. Combine provides operators to perform these conversions, allowing you to declare a chain of processing operations.
The data task publisher produces a tuple that contains a Data and a URLResponse. You can use the map(:) operator to convert the contents of this tuple to another type. If you want to inspect the response before inspecing the data, use tryMap(:) and throw an error if the response is unacceptable.
To convert raw data to your own types that conform to the Decodable protocol, use Combine’s decode(type:decoder:) operator.
Once we’ve created a publisher, we can then attach subscriptions to it, for example by using the sink
API — which lets us pass a closure to be called whenever a new value was received, as well as one that’ll be called once the publisher was completed:
The following example combines both these operators to parse JSON data from a URL endpoint into a custom User type:
struct User: Codable {
let name: String
let userID: String
}
let url = URL(string: "https://example.com/endpoint")!
let sapurlSession = SAPURLSession()
cancellable = sapurlSession
.dataTaskPublisher(for: url)
.tryMap() { element -> Data in
guard let httpResponse = element.response as? HTTPURLResponse,
httpResponse.statusCode == 200 else {
throw URLError(.badServerResponse)
}
return element.data
}
.decode(type: User.self, decoder: JSONDecoder())
.sink(receiveCompletion: { print ("Received completion: \($0).") },
receiveValue: { user in print ("Received user: \(user).")})
Also the observers that you attach for SAPURLSession will also get called during its course, when dataTaskPublisher is used.
Additional Information
- URLSession https://developer.apple.com/reference/foundation/urlsession
- Authentication Challenges https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/URLLoadingSystem/Articles/AuthenticationChallenges.html
SAPURLSession component Logger ID
This component uses the following name prefix for logging: ‘SAP.Foundation.SAPURLSession’
-
This class represents a client that can be used to communicate with an HTTP server. It wraps the native
URLSession
.You have different options to create a
SAPURLSession
instance. The simplest way is to initialize it using defaults.let urlSession = SAPURLSession()
Note: When using the default initializer, the
SAPURLSession
initilizes the underlyingURLSession
with the following parameters:- configuration: URLSessionConfiguration.default
- delegate: nil
- delegateQueue: nil
If you need to be informed about
URLSession
events, implement theSAPURLSessionDelegate
APIs, and pass this delegate as a parameter. You can register this delegate also to obtain the backingURLSessionTask
once its initialized.let urlSession = SAPURLSession(delegate: self)
Once you have created an
SAPURLSession
you can use it to exchange messages. Depending on your use case you can either directly use this session or pass it to other SDK components that require anSAPURLSession
instance for communication.The
See moreSAPURLSession
class exposes methods for sending short requests to the server, and it supports downloading and uploading of large payloads as well.Declaration
Swift
public class SAPURLSession
-
This class is a wrapper class on top of
See moreURLSessionDownloadTask
.Declaration
Swift
public class SAPURLSessionDownloadTask : SAPURLSessionTask
-
This class is a wrapper class on top of
See moreURLSessionTask
.Declaration
Swift
public class SAPURLSessionTask
-
CorrelationObserver
Generates and adds a unique identifier to the requests of a
SAPURLSessionTask
. In case the task will resend the samecorrelationID
will be used. ThecorrelationID
will be logged out to the logs withLogger
under the componentSAP.Foundation.SAPURLSession.CorrelationObserver
‘ The code snippet below demonstrates how to use it:
See morelet correlationObserver = CorrelationObserver() sapURLSession.register(correlationObserver)
Declaration
Swift
open class CorrelationObserver : SAPURLSessionObserving
-
This observer is responsible to set the required X-CSRF-Token header for communication with services exposed by SAPcpms. To enable this functionality you need to register this observer to an
SAPURLSession
instance. For token storing theCSRFTokenStoring
protocol is used.This is an example for a basic usage of this observer if you have one root URL for every CSRF token request: The
rootUrl
parameter is the URL from which the CSRF token will be requested.let urlSession: SAPURLSession = <#SAPURLSession instance#> let rootUrl: URL = <#your root URL#> let csrfTokenObserver = CSRFTokenObserver(rootUrl: rootUrl) urlSession.register(csrfTokenObserver)
If you have multiple CSRF protected backends and these backends accept different CSRF tokens you must implement
CSRFTokenURLProviding
protocol to provide CSRF URL for different request URL’s. For token storing theCSRFTokenStoring
protocol is used.
See moreclass myCSRFTokenURLProvider: CSRFTokenURLProviding { func csrfTokenURL(for: URL) -> URL { // implement custom logic to create token URL from the request URL // ... return <#token URL#> } } let csrfTokenObserver = CSRFTokenObserver(tokenUrlProvider: myCSRFTokenURLProvider, tokenStore: myCSRFTokenStore) urlSession.register(csrfTokenObserver)
Declaration
Swift
public class CSRFTokenObserver : SAPURLSessionObserving
-
This observer is responsible to set the Accept-Language headers to each HTTP request of the
SAPURLSession
.To enable this functionality you need to register this observer to an
SAPURLSession
instance.This is an example for a typical usage of the observer:
See morelet urlSession: SAPURLSession = <#SAPURLSession instance#> let languageObserver = LanguageObserver() urlSession.register(languageObserver)
Declaration
Swift
open class LanguageObserver : SAPURLSessionObserving
-
NetworkActivityIndicatorObserver
Shows and hides the
Network Activity Indicator
automatically, based on the states of requests in theSAPURLSession
. It presents the indicator when a request starts and hides it when the request finished. The state of the ActivityIndicator is shared among all theSAPURLSession
andSAPURLSessionObserving
instances. The observer uses theNetworkActivityIndicatorController
to control the presentation of the indicator. When you use this observer never modify theNetwork Activity Indicator
directly but use theNetworkActivityIndicatorController
.The code snippet below demonstrates how to use it:
See morelet indicatorObserver = NetworkActivityIndicatorObserver() sapURLSession.register(indicatorObserver)
Declaration
Swift
open class NetworkActivityIndicatorObserver
extension NetworkActivityIndicatorObserver: SAPURLSessionObserving
-
This observer is responsible to set required headers for communication with services exposed by SAPcpms. This includes the
X-SMP-APPID
andX-SMP-DEVICEID
header fields, which are added to each HTTP request of theSAPURLSession
.To enable this functionality you need to register this observer to an
SAPURLSession
instance.This is an example for a typical usage of the observer:
See morelet urlSession: SAPURLSession = <#SAPURLSession instance#> let applicationID: String = <#application_ID#> let deviceID: String? = <#device_ID#> let applicationVersion: String? = <#application_Version#> let observer = SAPcpmsObserver(applicationID: applicationID, deviceID: deviceID, applicationVersion: applicationVersion) urlSession.register(observer)
Declaration
Swift
public class SAPcpmsObserver : SAPURLSessionObserving
-
Use this observer to detect user blocked errors from SAPcpms. When a blocked response is detected, the provided handler is called with the specific blocking case - see
See moreSAPcpmsUserBlockedError
for more information. The observer is in silent mode after this detection and will remain in this mode until a non-blocking response is detected. The observer will not call the provided handler while in silent mode. All requests that are detected as blocking ones will result in the appropriateSAPcpmsUserBlockedError
error.Declaration
Swift
open class SAPcpmsUserBlockedObserver : SAPURLSessionObserving
-
NetworkActivityIndicatorController
Controls whether the
See moreNetwork Activity Indicator
should be showed or hidden. When you useNetworkActivityIndicatorObserver
, never modify theNetwork Activity Indicator
directly - use this class instead. The component uses a counter internally. When this counter has a positive value the indicator is visible.Declaration
Swift
public class NetworkActivityIndicatorController
-
default implementation for CSRFTokenStoring protocol
See moreDeclaration
Swift
open class CSRFTokenStorage : CSRFTokenStoring
-
The SAP implemented
HTTPCookieStorage
which can be used with instances ofSAPURLSession
. The store can be initialized with aCodableStoring
instance which makes it capable to persist cookies between application runs. This implementation won’t share the non-session cookies among the other SAPHTTPCookieStorage instances.Example:
See morelet sessionConfiguration = URLSessionConfiguration.default sessionConfiguration.httpCookieStorage = sapCookieStorage let sapUrlSession = SAPURLSession(configuration: sessionConfiguration)
Declaration
Swift
public class SAPHTTPCookieStorage : HTTPCookieStorage
-
The SAPURLSessionDelegate protocol describes the methods that SAPURLSession objects call on their delegates to handle session- and task-level events.
See moreDeclaration
Swift
public protocol SAPURLSessionDelegate : AnyObject
-
Defines a protocol which is capable of storing CSRF tokens.
See moreDeclaration
Swift
public protocol CSRFTokenStoring
-
Defines a protocol which is capable of providing CSRF URL for every request URL.
See moreDeclaration
Swift
public protocol CSRFTokenURLProviding
-
Declares the methods which allow callers to modify the network request and the response.
See moreDeclaration
Swift
public protocol SAPURLSessionObserving : AnyObject, OptionalCopying
-
Set of errors to signal the blocked user.
- traffic: traffic is blocked
- trafficAndRegistration: traffic and registration both blocked
- registration: registration blocked
Declaration
Swift
public enum SAPcpmsUserBlockedError : Error
-
Describes SAPURLSession specific errors
See moreDeclaration
Swift
public enum SAPURLSessionError : Error
extension SAPURLSessionError: SAPError