URLSession integration
How to use the DataDome SDK with URLSession
Installation
Swift Package Manager
DataDomeSDK is available on Swift Package Manager. To get the SDK integrated in your project, follow the steps below:
- Go to "Xcode > File > Swift Packages > Add Package Dependency", select the target where to integrate DataDome
- Paste the following git URL in the search bar
https://github.com/DataDome/datadome-ios-package
- Select
DataDomeSDK
and pressAdd
CocoaPods
DataDomeSDK is available on CocoaPods. Simply add the following line in your Podfile:
pod "DataDomeSDK"
Run pod install
to download and integrate the framework into your project.
Carthage
DataDomeSDK is available on Carthage. To get the SDK integrated in your project, follow the steps below:
- Create a Cartfile if not already created.
- Add the following dependency in your project Cartfile
binary "https://raw.githubusercontent.com/DataDome/datadome-ios-package/refs/heads/master/DataDomeSDK.json" ~> 3.6.2
- Run the following command to fetch and integrate the package
carthage update --use-xcframeworks
Usage
Swizzling
The DataDomeSDK has an option to intercept all HTTP requests made from those URLSession
methods:
func dataTask(with url: URL, completionHandler: @escaping @Sendable (Data?, URLResponse?, Error?) -> Void) -> URLSessionDataTask
func dataTask(with request: URLRequest, completionHandler: @escaping @Sendable (Data?, URLResponse?, Error?) -> Void) -> URLSessionDataTask
We do that by swizzling, dynamically exchanging the implementation of those methods with our own.
Swizzling is activated by default, this means that if you wish to protect all of your HTTP request made by the above methods, you have nothing else to do.
Manually protecting requests
If you whish to handpick the HTTP requests you whish to protect, you will first need to deactivate the swizzling.
You can do that by adding this property to you project's info.plist
<key>DataDomeProxyEnabled</key>
<false/>
Then, to make a protected HTTP request, use one of the DataDomeSDK methods:
func protectedDataTask(with url: URL,
captchaDelegate: CaptchaDelegate?,
completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void)
-> URLSessionDataTask
func protectedDataTask(with request: URLSessionRequest,
captchaDelegate: CaptchaDelegate?,
completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void)
-> URLSessionDataTask
func protectedDataTask(withURL url: URL,
captchaDelegate: CaptchaDelegate?) async throws
-> (Data, URLResponse)
func protectedDataTask(withRequest request: URLRequest,
captchaDelegate: CaptchaDelegate?) async throws
-> (Data, URLResponse)
Combine
If you are using Combine
and DataTaskPublisher
to perform networking requests in your app, we have you covered.
Use the following apis to create a DataTaskPublisher
with the DataDome operators
/// Provides a publisher with downstream DataDome operators
/// - Parameters:
/// - url: The url to be requested
/// - captchaDelegate: The captcha delegate
/// - Returns: A publisher with the DataDome operators
func protectedDataTaskPublisher(forURL url: URL,
captchaDelegate: CaptchaDelegate?)
-> AnyPublisher<URLSession.DataTaskPublisher.Output, URLSession.DataTaskPublisher.Failure>
Or by using an URLRequest instance as parameter
/// Provides a publisher with downstream DataDome operators
/// - Parameters:
/// - request: The request to be processed
/// - captchaDelegate: The captcha delegate
/// - Returns: A publisher with the DataDome operators
func protectedDataTaskPublisher(forRequest request: URLRequest,
captchaDelegate: CaptchaDelegate?)
-> AnyPublisher<URLSession.DataTaskPublisher.Output, URLSession.DataTaskPublisher.Failure>
Here an example on how to use the DataDome protected publisher
import DataDomeSDK
URLSession
.shared
.protectedDataTaskPublisher(forURL: url, captchaDelegate: nil)
.sink(receiveCompletion: { completion in
switch completion {
case .finished:
break
case .failure(let error):
print(error.localizedDescription)
}
}, receiveValue: { response in
guard let httpResponse = response.response as? HTTPURLResponse else {
print("Invalid response")
return
}
print("Did receive response with code \(httpResponse.statusCode)")
}
})
You can use any other operators to validate or transform the publisher or part of its elements. For more details, please visit Apple Documentation
You can also implement the CaptchaDelegate
protocol to manage the navigation of the CaptchaViewController
import DataDomeSDK
extension MyViewController: CaptchaDelegate {
func present(captchaController controller: UIViewController) {
self.navigationController?.present(controller, animated: true, completion: nil)
}
func dismiss(captchaController controller: UIViewController) {
controller.dismiss(animated: true, completion: nil)
}
}
More
SFCC support
When calling an SFCC endpoint, the captcha will be displayed according to different rules.
You will need to implement this method from the URLSessionTaskDelegate
:
urlSession(_ session: URLSession, task: URLSessionTask, willPerformHTTPRedirection response: HTTPURLResponse, newRequest request: URLRequest, completionHandler: @escaping (URLRequest?) -> Void)
And return nil
if the URL inside the Location
HTTP header has a path containing DDUser-Challenge
as one of its components.
Example:
func urlSession(_ session: URLSession,
task: URLSessionTask,
willPerformHTTPRedirection response: HTTPURLResponse,
newRequest request: URLRequest,
completionHandler: @escaping (URLRequest?) -> Void) {
if let location = response.value(forHTTPHeaderField: "location"),
let url = URL(string: location),
url.pathComponents.contains("DDUser-Challenge") {
return completionHandler(nil)
}
return completionHandler(request)
}
On versions older than 3.6.0 only
You will also have to set
DataDomeSDK.bypassHTTPAccept = true
to display the captcha correctly.
Updated 2 days ago