Skip to content

Commit

Permalink
Feature/merge core http (#77)
Browse files Browse the repository at this point in the history
* feat: move CoreHTTP contents to Sources folder

Resolves: none.

* Update Package.swift

* Update Package.swift

* Update Package.resolved

* Update Package.resolved

* Update Completable+Retry.swift

* feat: update dummy

Resolves: none.
  • Loading branch information
loay-ashraf committed May 17, 2024
1 parent 3fdaeba commit cf3c665
Show file tree
Hide file tree
Showing 27 changed files with 677 additions and 60 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/SPMDummy/SPMDummy.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,7 @@
SUPPORTED_PLATFORMS = "appletvos appletvsimulator iphoneos iphonesimulator macosx";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2,3";
Expand Down Expand Up @@ -372,6 +373,7 @@
SUPPORTED_PLATFORMS = "appletvos appletvsimulator iphoneos iphonesimulator macosx";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2,3";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,6 @@
{
"object": {
"pins": [
{
"package": "CoreHTTP",
"repositoryURL": "https://github.com/loay-ashraf/CoreHTTP",
"state": {
"branch": null,
"revision": "17b030a4a10ac9449e6c107bce13f112280aae6b",
"version": "1.0.0"
}
},
{
"package": "RxSwift",
"repositoryURL": "https://github.com/ReactiveX/RxSwift.git",
Expand Down
2 changes: 2 additions & 0 deletions Examples/iOS/iOS Example.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,7 @@
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
Expand Down Expand Up @@ -375,6 +376,7 @@
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
Expand Down
2 changes: 2 additions & 0 deletions Examples/macOS/macOS Example.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@

/* Begin PBXFileReference section */
C623E7182AD6117200A20A0A /* macOS Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "macOS Example.app"; sourceTree = BUILT_PRODUCTS_DIR; };
C625C4D92BF7791A00761FD6 /* CoreHTTP.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = CoreHTTP.framework; sourceTree = BUILT_PRODUCTS_DIR; };
C63975182A95166A00D0AC13 /* TableCellView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableCellView.swift; sourceTree = "<group>"; };
C63EEB3D2AD7C29F003A64CA /* CoreExample.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = CoreExample.framework; sourceTree = BUILT_PRODUCTS_DIR; };
C63EEB402AD7C2A4003A64CA /* RxNetworkKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = RxNetworkKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
Expand Down Expand Up @@ -92,6 +93,7 @@
C63EEAFF2AD7A40E003A64CA /* Frameworks */ = {
isa = PBXGroup;
children = (
C625C4D92BF7791A00761FD6 /* CoreHTTP.framework */,
C63EEB402AD7C2A4003A64CA /* RxNetworkKit.framework */,
C63EEB3D2AD7C29F003A64CA /* CoreExample.framework */,
);
Expand Down
9 changes: 0 additions & 9 deletions Package.resolved
Original file line number Diff line number Diff line change
@@ -1,15 +1,6 @@
{
"object": {
"pins": [
{
"package": "CoreHTTP",
"repositoryURL": "https://github.com/loay-ashraf/CoreHTTP",
"state": {
"branch": null,
"revision": "17b030a4a10ac9449e6c107bce13f112280aae6b",
"version": "1.0.0"
}
},
{
"package": "RxSwift",
"repositoryURL": "https://github.com/ReactiveX/RxSwift.git",
Expand Down
5 changes: 2 additions & 3 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,10 @@ let package = Package(
],
dependencies: [
.package(url: "https://github.com/ReactiveX/RxSwift.git", .upToNextMajor(from: "6.6.0")),
.package(url: "https://github.com/RxSwiftCommunity/RxSwiftExt", .upToNextMajor(from: "6.2.0")),
.package(url: "https://github.com/loay-ashraf/CoreHTTP", .upToNextMajor(from: "2.0.0"))
.package(url: "https://github.com/RxSwiftCommunity/RxSwiftExt", .upToNextMajor(from: "6.2.0"))
],
targets: [
.target(name: "RxNetworkKit", dependencies: ["RxSwift", "RxSwiftExt", .product(name: "RxCocoa", package: "RxSwift"), "CoreHTTP"], path: "Source"),
.target(name: "RxNetworkKit", dependencies: ["RxSwift", "RxSwiftExt", .product(name: "RxCocoa", package: "RxSwift")], path: "Source"),
],
swiftLanguageVersions: [.v5]
)
151 changes: 130 additions & 21 deletions RxNetworkKit.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

10 changes: 1 addition & 9 deletions RxNetworkKit.xcworkspace/xcshareddata/swiftpm/Package.resolved
Original file line number Diff line number Diff line change
@@ -1,14 +1,6 @@
{
"originHash" : "0de4ac07bf4deb2bff179bbf81665f083753da360913fe8b8ff4a56936e57591",
"pins" : [
{
"identity" : "corehttp",
"kind" : "remoteSourceControl",
"location" : "https://github.com/loay-ashraf/CoreHTTP",
"state" : {
"revision" : "d38c3063412e7121bbb5a1fcef3089d847865266",
"version" : "2.0.1"
}
},
{
"identity" : "rxdatasources",
"kind" : "remoteSourceControl",
Expand Down
2 changes: 2 additions & 0 deletions Shared/CoreExample/CoreExample.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,7 @@
SUPPORTED_PLATFORMS = "appletvos appletvsimulator iphoneos iphonesimulator macosx watchos watchsimulator";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
Expand Down Expand Up @@ -420,6 +421,7 @@
SUPPORTED_PLATFORMS = "appletvos appletvsimulator iphoneos iphonesimulator macosx watchos watchsimulator";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2,3,4";
Expand Down
14 changes: 14 additions & 0 deletions Source/Common/Request/Error/DefaultHTTPAPIError.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//
// DefaultHTTPAPIError.swift
// RxNetworkKit
//
// Created by Loay Ashraf on 19/02/2023.
//

/// Default type used for decoding internal api error bodies.
public struct DefaultHTTPAPIError: HTTPAPIError {

/// error message.
let message: String

}
20 changes: 20 additions & 0 deletions Source/Common/Request/Error/DefaultHTTPBodyError.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//
// DefaultHTTPBodyError.swift
// RxNetworkKit
//
// Created by Loay Ashraf on 21/08/2023.
//

import Foundation

/// Default type used for decoding http error bodies.
public struct DefaultHTTPBodyError: HTTPBodyError {

/// response status code.
let statusCode: Int?
/// error message.
let message: String?
/// support identifier.
let supportId: String?

}
9 changes: 9 additions & 0 deletions Source/Common/Request/Error/HTTPAPIError.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
//
// HTTPAPIError.swift
// RxNetworkKit
//
// Created by Loay Ashraf on 20/03/2023.
//

/// Internal api error body type.
public protocol HTTPAPIError: Error, Decodable { }
11 changes: 11 additions & 0 deletions Source/Common/Request/Error/HTTPBodyError.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
//
// HTTPErrorBody.swift
// RxNetworkKit
//
// Created by Loay Ashraf on 21/08/2023.
//

import Foundation

/// HTTP body error type.
public protocol HTTPBodyError: Decodable { }
13 changes: 13 additions & 0 deletions Source/Common/Request/Error/HTTPClientError.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//
// HTTPClientError.swift
// RxNetworkKit
//
// Created by Loay Ashraf on 19/02/2023.
//

/// Client-side (transport) http error.
public enum HTTPClientError: Error {
case response(HTTPStatusCode, HTTPBodyError?)
case serialization(Error)
case transport(Error)
}
41 changes: 41 additions & 0 deletions Source/Common/Request/Error/HTTPError.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//
// HTTPError.swift
// RxNetworkKit
//
// Created by Loay Ashraf on 19/02/2023.
//

import Foundation

/// Generic http error (client, server or api).
public enum HTTPError: Error {
case client(HTTPClientError)
case server(HTTPServerError)
case api(HTTPAPIError)

/// Creates `NetworkError` instance.
///
/// - Parameter response: `HTTPURLResponse` used to get response status code.
public init?<E: HTTPBodyError>(_ response: HTTPURLResponse?, data: Data?, errorType: E.Type) {
if let response = response,
let httpStatusCode = response.status {
// Get Error body from response data if possible.
var httpErrorBody: E?
if let data = data {
httpErrorBody = try? JSONDecoder().decode(errorType.self, from: data)
}
// Get Error from response status code
switch httpStatusCode.responseType {
case .clientError:
self = .client(.response(httpStatusCode, httpErrorBody))
case .serverError:
self = .server(.response(httpStatusCode, httpErrorBody))
default:
return nil
}
} else {
return nil
}
}

}
12 changes: 12 additions & 0 deletions Source/Common/Request/Error/HTTPServerError.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
//
// HTTPServerError.swift
// RxNetworkKit
//
// Created by Loay Ashraf on 19/02/2023.
//

/// Server-side http error.
public enum HTTPServerError: Error {
case response(HTTPStatusCode, HTTPBodyError?)
case generic(Error)
}
22 changes: 22 additions & 0 deletions Source/Common/Request/Interceptor/HTTPRequestAdapter.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//
// HTTPRequestAdapter.swift
// RxNetworkKit
//
// Created by Loay Ashraf on 27/03/2023.
//

import Foundation

/// Adapts outgoing requests.
public protocol HTTPRequestAdapter: AnyObject {

/// Adapts a given request for a given session.
///
/// - Parameters:
/// - request: current `URLRequest`
/// - session: current `URLSession`
///
/// - Returns: `URLRequest` adapted request for a given session.
func adapt(_ request: URLRequest, for session: URLSession) -> URLRequest

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
//
// HTTPRequestInterceptor.swift
// RxNetworkKit
//
// Created by Loay Ashraf on 27/03/2023.
//

/// Request adapter and retrier.
public typealias HTTPRequestInterceptor = HTTPRequestAdapter & HTTPRequestRetrier
41 changes: 41 additions & 0 deletions Source/Common/Request/Interceptor/HTTPRequestRetrier.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//
// HTTPRequestRetrier.swift
// RxNetworkKit
//
// Created by Loay Ashraf on 27/03/2023.
//

import Foundation

/// Retries requests upon failure.
public protocol HTTPRequestRetrier: AnyObject {

/// Provides maximum retry attempts for a given request and session.
///
/// - Parameters:
/// - request: current `URLRequest`
/// - session: current `URLSession`
///
/// - Returns: `Int` maximum retry attempts for given request and session.
func retryMaxAttempts(_ request: URLRequest, for session: URLSession) -> Int

/// Provides retry policy for a given request and session.
///
/// - Parameters:
/// - request: current `URLRequest`
/// - session: current `URLSession`
///
/// - Returns: `NetworkRequestRetryPolicy` retry policy for given request and session.
func retryPolicy(_ request: URLRequest, for session: URLSession) -> HTTPRequestRetryPolicy

/// Decides if a given request should be reried for a given session and error.
///
/// - Parameters:
/// - request: current `URLRequest`
/// - session: current `URLSession`
/// - error: encountered `NetworkError`
///
/// - Returns: `NetworkRequestRetryPolicy` retry policy for given request and session.
func shouldRetry(_ request: URLRequest, for session: URLSession, dueTo error: HTTPError) -> Bool

}
38 changes: 38 additions & 0 deletions Source/Common/Request/Interceptor/HTTPRequestRetryPolicy.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
//
// HTTPRequestRetryPolicy.swift
// RxNetworkKit
//
// Created by Loay Ashraf on 27/03/2023.
//

import Foundation

// This enum is inspired by Alex Grebenyuk excellent blog https://kean.blog/post/smart-retry
// Here's Alex's twitter: https://twitter.com/a_grebenyuk

/// Policy for retrying failed requests.
public enum HTTPRequestRetryPolicy {
case immediate
case constant(time: Double)
case exponential(initial: Double, multiplier: Double, maxDelay: Double)
case custom(closure: (Int) -> Double)
}

public extension HTTPRequestRetryPolicy {
/// Creates time interavel (`Double`) from current policy and given attempt count.
///
/// - Parameter attempt: current attempt count.
///
/// - Returns: Time interval `Double` for delay.
func makeTimeInterval(_ attempt: Int) -> Double {
switch self {
case .immediate: return 0.0
case .constant(let time): return time
case .exponential(let initial, let multiplier, let maxDelay):
// if it's first attempt, simply use initial delay, otherwise calculate delay
let delay = attempt == 1 ? initial : initial * pow(multiplier, Double(attempt - 1))
return min(maxDelay, delay)
case .custom(let closure): return closure(attempt)
}
}
}
18 changes: 18 additions & 0 deletions Source/Common/Request/Parameters/HTTPMethod.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//
// HTTPMethod.swift
// RxNetworkKit
//
// Created by Loay Ashraf on 20/03/2023.
//

/// An enumeration of the types of http methods.
public enum HTTPMethod: String {
case get = "GET"
case put = "PUT"
case post = "POST"
case delete = "DELETE"
case head = "HEAD"
case options = "OPTIONS"
case trace = "TRACE"
case connect = "CONNECT"
}
12 changes: 12 additions & 0 deletions Source/Common/Request/Parameters/HTTPScheme.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
//
// HTTPScheme.swift
// RxNetworkKit
//
// Created by Loay Ashraf on 20/03/2023.
//

/// An enumeration of the types of http schemes.
public enum HTTPScheme: String {
case http = "http://"
case https = "https://"
}
Loading

0 comments on commit cf3c665

Please sign in to comment.