Skip to content

Commit

Permalink
feat(swift5): add support for rate limit
Browse files Browse the repository at this point in the history
  • Loading branch information
ThibaultBee authored Apr 24, 2024
1 parent 5f133a4 commit 733b27f
Show file tree
Hide file tree
Showing 23 changed files with 1,145 additions and 419 deletions.
24 changes: 22 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ import ApiVideoClient
// If you rather like to use the sandbox environment:
// ApiVideoClient.basePath = Environment.sandbox.rawValue

try VideosAPI.uploadWithUploadToken(token: "MY_VIDEO_TOKEN", file: url) { video, error in
try VideosAPI.uploadWithUploadToken(token: "MY_UPLOAD_TOKEN", file: url) { video, error in
if let video = video {
// Manage upload with upload token success here
}
Expand Down Expand Up @@ -341,7 +341,27 @@ Method | HTTP request | Description
- [WebhooksListResponse](https://github.com/apivideo/api.video-swift-client/blob/main/docs/WebhooksListResponse.md)


### Documentation for Authorization
### Rate limiting

api.video implements rate limiting to ensure fair usage and stability of the service. The API provides the rate limit values in the response headers for any API requests you make. The /auth endpoint is the only route without rate limitation.

In this client, you can access these headers by using the methods with the `completion: @escaping (_ result: Swift.Result<Response<T>, ErrorResponse>) -> Void)` parameters. These methods return both the response body and the headers, allowing you to check the `X-RateLimit-Limit`, `X-RateLimit-Remaining`, and `X-RateLimit-Retry-After` headers to understand your current rate limit status.
Read more about these response headers in the [API reference](https://docs.api.video/reference#limitation).

```swift
try VideosAPI.uploadWithUploadToken(token: "MY_UPLOAD_TOKEN", file: url) { result in
switch result {
case .success(let response):
print("X-RateLimit-Limit: \(String(describing: response.header["X-RateLimit-Limit"]))")
print("X-RateLimit-Remaining: \(String(describing: response.header["X-RateLimit-Remaining"]))")
print("X-RateLimit-Retry-After: \(String(describing: response.header["X-RateLimit-Retry-After"]))")
case .failure(_):
break
}
}
```

### Authorization

#### API key

Expand Down
56 changes: 40 additions & 16 deletions Sources/APIs/AdvancedAuthenticationAPI.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,26 @@ open class AdvancedAuthenticationAPI {
*/
@discardableResult
open class func authenticate(authenticatePayload: AuthenticatePayload, apiResponseQueue: DispatchQueue = ApiVideoClient.apiResponseQueue, completion: @escaping ((_ data: AccessToken?, _ error: Error?) -> Void)) -> RequestTask {
return authenticateWithRequestBuilder(authenticatePayload: authenticatePayload).execute(apiResponseQueue) { result in
switch result {
case let .success(response):
completion(response.body, nil)
case let .failure(error):
completion(nil, error)
}
return authenticate(authenticatePayload: authenticatePayload, apiResponseQueue: apiResponseQueue) { result in
switch result {
case let .success(response):
completion(response.body, nil)
case let .failure(error):
completion(nil, error)
}
}
}

/**
Get Bearer Token

- parameter authenticatePayload: (body)
- parameter apiResponseQueue: The queue on which api response is dispatched.
- parameter completion: completion handler to receive the result of the request (incl. headers).
*/
@discardableResult
open class func authenticate(authenticatePayload: AuthenticatePayload, apiResponseQueue: DispatchQueue = ApiVideoClient.apiResponseQueue, completion: @escaping (_ result: Swift.Result<Response<AccessToken>, ErrorResponse>) -> Void) -> RequestTask {
return authenticateWithRequestBuilder(authenticatePayload: authenticatePayload).execute(apiResponseQueue, completion)
}


Expand All @@ -39,7 +51,7 @@ open class AdvancedAuthenticationAPI {
- parameter authenticatePayload: (body)
- returns: RequestBuilder<AccessToken>
*/
open class func authenticateWithRequestBuilder(authenticatePayload: AuthenticatePayload) -> RequestBuilder<AccessToken> {
internal class func authenticateWithRequestBuilder(authenticatePayload: AuthenticatePayload) -> RequestBuilder<AccessToken> {
let localVariablePath = "/auth/api-key"
let localVariableURLString = ApiVideoClient.basePath + localVariablePath
let localVariableParameters = JSONEncodingHelper.encodingParameters(forEncodableObject: authenticatePayload)
Expand Down Expand Up @@ -67,14 +79,26 @@ open class AdvancedAuthenticationAPI {
*/
@discardableResult
open class func refresh(refreshTokenPayload: RefreshTokenPayload, apiResponseQueue: DispatchQueue = ApiVideoClient.apiResponseQueue, completion: @escaping ((_ data: AccessToken?, _ error: Error?) -> Void)) -> RequestTask {
return refreshWithRequestBuilder(refreshTokenPayload: refreshTokenPayload).execute(apiResponseQueue) { result in
switch result {
case let .success(response):
completion(response.body, nil)
case let .failure(error):
completion(nil, error)
}
return refresh(refreshTokenPayload: refreshTokenPayload, apiResponseQueue: apiResponseQueue) { result in
switch result {
case let .success(response):
completion(response.body, nil)
case let .failure(error):
completion(nil, error)
}
}
}

/**
Refresh Bearer Token

- parameter refreshTokenPayload: (body)
- parameter apiResponseQueue: The queue on which api response is dispatched.
- parameter completion: completion handler to receive the result of the request (incl. headers).
*/
@discardableResult
open class func refresh(refreshTokenPayload: RefreshTokenPayload, apiResponseQueue: DispatchQueue = ApiVideoClient.apiResponseQueue, completion: @escaping (_ result: Swift.Result<Response<AccessToken>, ErrorResponse>) -> Void) -> RequestTask {
return refreshWithRequestBuilder(refreshTokenPayload: refreshTokenPayload).execute(apiResponseQueue, completion)
}


Expand All @@ -85,7 +109,7 @@ open class AdvancedAuthenticationAPI {
- parameter refreshTokenPayload: (body)
- returns: RequestBuilder<AccessToken>
*/
open class func refreshWithRequestBuilder(refreshTokenPayload: RefreshTokenPayload) -> RequestBuilder<AccessToken> {
internal class func refreshWithRequestBuilder(refreshTokenPayload: RefreshTokenPayload) -> RequestBuilder<AccessToken> {
let localVariablePath = "/auth/refresh"
let localVariableURLString = ApiVideoClient.basePath + localVariablePath
let localVariableParameters = JSONEncodingHelper.encodingParameters(forEncodableObject: refreshTokenPayload)
Expand Down
66 changes: 50 additions & 16 deletions Sources/APIs/AnalyticsAPI.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,31 @@ open class AnalyticsAPI {
*/
@discardableResult
open class func getLiveStreamsPlays(from: Date, dimension: DimensionGetLiveStreamsPlays, to: Date? = nil, filter: String? = nil, currentPage: Int? = nil, pageSize: Int? = nil, apiResponseQueue: DispatchQueue = ApiVideoClient.apiResponseQueue, completion: @escaping ((_ data: AnalyticsPlaysResponse?, _ error: Error?) -> Void)) -> RequestTask {
return getLiveStreamsPlaysWithRequestBuilder(from: from, dimension: dimension, to: to, filter: filter, currentPage: currentPage, pageSize: pageSize).execute(apiResponseQueue) { result in
switch result {
case let .success(response):
completion(response.body, nil)
case let .failure(error):
completion(nil, error)
}
return getLiveStreamsPlays(from: from, dimension: dimension, to: to, filter: filter, currentPage: currentPage, pageSize: pageSize, apiResponseQueue: apiResponseQueue) { result in
switch result {
case let .success(response):
completion(response.body, nil)
case let .failure(error):
completion(nil, error)
}
}
}

/**
Get play events for live stream

- parameter from: (query) Use this query parameter to set the start date for the time period that you want analytics for. - The API returns analytics data including the day you set in &#x60;from&#x60;. - The date you set must be **within the last 30 days**. - The value you provide must follow the &#x60;YYYY-MM-DD&#x60; format.
- parameter dimension: (query) Use this query parameter to define the dimension that you want analytics for. - &#x60;liveStreamId&#x60;: Returns analytics based on the public live stream identifiers. - &#x60;emittedAt&#x60;: Returns analytics based on the times of the play events. The API returns data in specific interval groups. When the date period you set in &#x60;from&#x60; and &#x60;to&#x60; is less than or equals to 2 days, the response for this dimension is grouped in hourly intervals. Otherwise, it is grouped in daily intervals. - &#x60;country&#x60;: Returns analytics based on the viewers&#39; country. The list of supported country names are based on the [GeoNames public database](https://www.geonames.org/countries/). - &#x60;deviceType&#x60;: Returns analytics based on the type of device used by the viewers during the play event. Possible response values are: &#x60;computer&#x60;, &#x60;phone&#x60;, &#x60;tablet&#x60;, &#x60;tv&#x60;, &#x60;console&#x60;, &#x60;wearable&#x60;, &#x60;unknown&#x60;. - &#x60;operatingSystem&#x60;: Returns analytics based on the operating system used by the viewers during the play event. Response values include &#x60;windows&#x60;, &#x60;mac osx&#x60;, &#x60;android&#x60;, &#x60;ios&#x60;, &#x60;linux&#x60;. - &#x60;browser&#x60;: Returns analytics based on the browser used by the viewers during the play event. Response values include &#x60;chrome&#x60;, &#x60;firefox&#x60;, &#x60;edge&#x60;, &#x60;opera&#x60;.
- parameter to: (query) Use this optional query parameter to set the end date for the time period that you want analytics for. - If you do not specify a &#x60;to&#x60; date, the API returns analytics data starting from the &#x60;from&#x60; date up until today, and excluding today. - The date you set must be **within the last 30 days**. - The value you provide must follow the &#x60;YYYY-MM-DD&#x60; format. (optional)
- parameter filter: (query) Use this query parameter to filter your results to a specific live stream in a project that you want analytics for. You must use the &#x60;liveStreamId:&#x60; prefix when specifying a live stream ID. (optional)
- parameter currentPage: (query) Choose the number of search results to return per page. Minimum value: 1 (optional, default to 1)
- parameter pageSize: (query) Results per page. Allowed values 1-100, default is 25. (optional, default to 25)
- parameter apiResponseQueue: The queue on which api response is dispatched.
- parameter completion: completion handler to receive the result of the request (incl. headers).
*/
@discardableResult
open class func getLiveStreamsPlays(from: Date, dimension: DimensionGetLiveStreamsPlays, to: Date? = nil, filter: String? = nil, currentPage: Int? = nil, pageSize: Int? = nil, apiResponseQueue: DispatchQueue = ApiVideoClient.apiResponseQueue, completion: @escaping (_ result: Swift.Result<Response<AnalyticsPlaysResponse>, ErrorResponse>) -> Void) -> RequestTask {
return getLiveStreamsPlaysWithRequestBuilder(from: from, dimension: dimension, to: to, filter: filter, currentPage: currentPage, pageSize: pageSize).execute(apiResponseQueue, completion)
}


Expand All @@ -62,7 +79,7 @@ open class AnalyticsAPI {
- parameter pageSize: (query) Results per page. Allowed values 1-100, default is 25. (optional, default to 25)
- returns: RequestBuilder<AnalyticsPlaysResponse>
*/
open class func getLiveStreamsPlaysWithRequestBuilder(from: Date, dimension: DimensionGetLiveStreamsPlays, to: Date? = nil, filter: String? = nil, currentPage: Int? = nil, pageSize: Int? = nil) -> RequestBuilder<AnalyticsPlaysResponse> {
internal class func getLiveStreamsPlaysWithRequestBuilder(from: Date, dimension: DimensionGetLiveStreamsPlays, to: Date? = nil, filter: String? = nil, currentPage: Int? = nil, pageSize: Int? = nil) -> RequestBuilder<AnalyticsPlaysResponse> {
let localVariablePath = "/analytics/live-streams/plays"
let localVariableURLString = ApiVideoClient.basePath + localVariablePath
let localVariableParameters: [String: Any]? = nil
Expand Down Expand Up @@ -115,14 +132,31 @@ open class AnalyticsAPI {
*/
@discardableResult
open class func getVideosPlays(from: Date, dimension: DimensionGetVideosPlays, to: Date? = nil, filter: String? = nil, currentPage: Int? = nil, pageSize: Int? = nil, apiResponseQueue: DispatchQueue = ApiVideoClient.apiResponseQueue, completion: @escaping ((_ data: AnalyticsPlaysResponse?, _ error: Error?) -> Void)) -> RequestTask {
return getVideosPlaysWithRequestBuilder(from: from, dimension: dimension, to: to, filter: filter, currentPage: currentPage, pageSize: pageSize).execute(apiResponseQueue) { result in
switch result {
case let .success(response):
completion(response.body, nil)
case let .failure(error):
completion(nil, error)
}
return getVideosPlays(from: from, dimension: dimension, to: to, filter: filter, currentPage: currentPage, pageSize: pageSize, apiResponseQueue: apiResponseQueue) { result in
switch result {
case let .success(response):
completion(response.body, nil)
case let .failure(error):
completion(nil, error)
}
}
}

/**
Get play events for video

- parameter from: (query) Use this query parameter to set the start date for the time period that you want analytics for. - The API returns analytics data including the day you set in &#x60;from&#x60;. - The date you set must be **within the last 30 days**. - The value you provide must follow the &#x60;YYYY-MM-DD&#x60; format.
- parameter dimension: (query) Use this query parameter to define the dimension that you want analytics for. - &#x60;videoId&#x60;: Returns analytics based on the public video identifiers. - &#x60;emittedAt&#x60;: Returns analytics based on the times of the play events. The API returns data in specific interval groups. When the date period you set in &#x60;from&#x60; and &#x60;to&#x60; is less than or equals to 2 days, the response for this dimension is grouped in hourly intervals. Otherwise, it is grouped in daily intervals. - &#x60;country&#x60;: Returns analytics based on the viewers&#39; country. The list of supported country names are based on the [GeoNames public database](https://www.geonames.org/countries/). - &#x60;deviceType&#x60;: Returns analytics based on the type of device used by the viewers during the play event. Possible response values are: &#x60;computer&#x60;, &#x60;phone&#x60;, &#x60;tablet&#x60;, &#x60;tv&#x60;, &#x60;console&#x60;, &#x60;wearable&#x60;, &#x60;unknown&#x60;. - &#x60;operatingSystem&#x60;: Returns analytics based on the operating system used by the viewers during the play event. Response values include &#x60;windows&#x60;, &#x60;mac osx&#x60;, &#x60;android&#x60;, &#x60;ios&#x60;, &#x60;linux&#x60;. - &#x60;browser&#x60;: Returns analytics based on the browser used by the viewers during the play event. Response values include &#x60;chrome&#x60;, &#x60;firefox&#x60;, &#x60;edge&#x60;, &#x60;opera&#x60;.
- parameter to: (query) Use this optional query parameter to set the end date for the time period that you want analytics for. - If you do not specify a &#x60;to&#x60; date, the API returns analytics data starting from the &#x60;from&#x60; date up until today, and excluding today. - The date you set must be **within the last 30 days**. - The value you provide must follow the &#x60;YYYY-MM-DD&#x60; format. (optional)
- parameter filter: (query) Use this query parameter to filter your results to a specific video in a project that you want analytics for. You must use the &#x60;videoId:&#x60; prefix when specifying a video ID. (optional)
- parameter currentPage: (query) Choose the number of search results to return per page. Minimum value: 1 (optional, default to 1)
- parameter pageSize: (query) Results per page. Allowed values 1-100, default is 25. (optional, default to 25)
- parameter apiResponseQueue: The queue on which api response is dispatched.
- parameter completion: completion handler to receive the result of the request (incl. headers).
*/
@discardableResult
open class func getVideosPlays(from: Date, dimension: DimensionGetVideosPlays, to: Date? = nil, filter: String? = nil, currentPage: Int? = nil, pageSize: Int? = nil, apiResponseQueue: DispatchQueue = ApiVideoClient.apiResponseQueue, completion: @escaping (_ result: Swift.Result<Response<AnalyticsPlaysResponse>, ErrorResponse>) -> Void) -> RequestTask {
return getVideosPlaysWithRequestBuilder(from: from, dimension: dimension, to: to, filter: filter, currentPage: currentPage, pageSize: pageSize).execute(apiResponseQueue, completion)
}


Expand All @@ -139,7 +173,7 @@ open class AnalyticsAPI {
- parameter pageSize: (query) Results per page. Allowed values 1-100, default is 25. (optional, default to 25)
- returns: RequestBuilder<AnalyticsPlaysResponse>
*/
open class func getVideosPlaysWithRequestBuilder(from: Date, dimension: DimensionGetVideosPlays, to: Date? = nil, filter: String? = nil, currentPage: Int? = nil, pageSize: Int? = nil) -> RequestBuilder<AnalyticsPlaysResponse> {
internal class func getVideosPlaysWithRequestBuilder(from: Date, dimension: DimensionGetVideosPlays, to: Date? = nil, filter: String? = nil, currentPage: Int? = nil, pageSize: Int? = nil) -> RequestBuilder<AnalyticsPlaysResponse> {
let localVariablePath = "/analytics/videos/plays"
let localVariableURLString = ApiVideoClient.basePath + localVariablePath
let localVariableParameters: [String: Any]? = nil
Expand Down
Loading

0 comments on commit 733b27f

Please sign in to comment.