The DataDomeApollo SDK is available on Swift Package Manager. To get the SDK integrated to your project:
- In Xcode > File > Swift Packages > Add Package Dependency, select your target in which to integrate DataDomeApollo.
- Paste the following git url in the search bar
https://github.com/DataDome/datadome-Apollo-package
- Select
DataDomeApollo
and pressAdd
.
If your api is a GraphQL api, the chances are that you are using Apollo SDK. If so, we have a dedicated framework called DataDomeApollo designed to ease the DataDome SDK integration.
To install the plugin, use the following Cocoapods instruction: Alternatively, DataDomeAlamofire is available on CocoaPods. To get the SDK integrated to your project, simply add the following line to your Podfile:
pod "DataDomeApollo"
Run pod install
to download and integrate the framework to your project.
- Run your application. It is going to crash with the following log
Fatal error: [DataDome] Missing DataDomeKey (Your client side key) in your Info.plist
- In your Info.plist, add a new entry with String type, use DataDomeKey as key and your actual client side key as value.
- In your Info.plist, add a new entry with Boolean type, use DataDomeProxyEnabled as key and NO as value. This will disable method swizzling in the framework.
- You can run now the app, it won't crash. You should see a log confirming the SDK is running
[DataDome] Version x.y.z
Congrats, the DataDome and DataDomeAlamofire frameworks are well integrated
If you need to see the logs produced by the framework, you can set the log level to control the detail of logs you get
import DataDome
DataDome.setLogLevel(level: .verbose)
By default, the framework is completely silent.
The following table contains different logging levels that you may consider using
Level | Description |
---|---|
verbose | Everything is logged |
info | Info messages, warnings and errors are shown |
warning | Only warning and errors messages are printed |
error | Only errors are printed |
none | Silent mode (default) |
You can simulate a captcha display using the framework by providing a user agent with the value BLOCKUA
To do so:
- Edit your app scheme
- Under Run (Debug) > Arguments > Environment Variables, create a new variable
- Set the name to DATADOME_USER_AGENT and the value to BLOCKUA
The DataDome framework will inject the specified user agent in the requests the app will be sending. Using the BLOCKUA user agent value will hint our remote protection module installed on your servers to treat this request as if it is coming from a bot. Which will block it with a captcha response.
Since the DataDome framework retains the cookies after resolving the captcha, this test can be done only the first time you used the BLOCKUA user agent. To reproduce the test case, you can use the following code snippet to manually clear the cookies stored in your app
for cookie in HTTPCookieStorage.shared.cookies ?? [] {
HTTPCookieStorage.shared.deleteCookie(cookie)
}
We use the Interceptor pattern built in the Apollo SDK to make sure we intercept all requests and protect them. The following is the init of the DataDome Interceptor
let interceptor = DataDomeResponseInterceptor()
The interceptor could be used then in your pipeline. It will intercept all requests, catch requests blocked by DataDome, display the captcha and eventually retry the request automatically once the captcha is resolved.
####Important The order in defining the interceptors is important in Apollo. Make sure the DataDome response Interceptor is the first interceptor after the NetworkFetchInterceptor.
Alternatively, you can use the DataDomeInterceptorProvider which is a pre-built sequence of interceptors ready to be used by your app. This provider is providing the same interceptors as the Legacy Interceptor provider. You can customise the interceptors to be added in the provider or use the default set.
// Create your own store needed to init the DataDomeInterceptor provider
let cache = InMemoryNormalizedCache()
let store = ApolloStore(cache: cache)
// Use DataDomeURLSessionClient to enable updating the user-agent
let client = DataDomeURLSessionClient()
// Create the DataDome Interceptor Provider
let provider = DataDomeInterceptorProvider(store: store, client: client)
// Create your GraphQL URL
guard let url = URL(string: "YOUR_ENDPOINT") else {
fatalError("Unable to create url")
}
let requestChainTransport = RequestChainNetworkTransport(interceptorProvider: provider,
endpointURL: url)
// Create the client with the request chain transport
return ApolloClient(networkTransport: requestChainTransport,
store: store)
}()
In the above exemple we used the default configuration of DataDomeInterceptorProvider. You can specify custom interceptors using the following init method
/// - Parameters:
/// - store: The apollo store
/// - client: The URLSession client
/// - preFetchInterceptors: The list of interceptors to go before the fetch operation
/// - fetchInterceptor: The fetch operation
/// - postFetchInterceptors: The list of interceptors to go after the fetch operation
public init(store: ApolloStore,
client: URLSessionClient,
preFetchInterceptors: [ApolloInterceptor] = [],
fetchInterceptor: ApolloInterceptor? = nil,
postFetchInterceptors: [ApolloInterceptor] = [])
preFetchInterceptors
is a set of interceptors to be added before firing the request. By default we add:
CacheReadInterceptor
fetchInterceptor
is the interceptor that will execute the request. By default, we use:
NetworkFetchInterceptor
The DataDomeResponseInterceptor
is then added to the chain just after the fetch interceptor.
postFetchInterceptors
is a set of interceptors to be added after the fetch interceptor. By default we add:
- ResponseCodeInterceptor
- JSONResponseParsingInterceptor
- AutomaticPersistedQueryInterceptor
- CacheWriteInterceptor