Skip to content

Commit 5e3e21a

Browse files
committed
added fasttrack requests
1 parent 0f02a1d commit 5e3e21a

File tree

7 files changed

+323
-124
lines changed

7 files changed

+323
-124
lines changed

README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,26 @@ Network layer for running requests like GET, POST, PUT, DELETE etc customizable
1717

1818
![Http requests](https://github.com/The-Igor/async-http-client-example/blob/main/async-http-client-example/img/image11.gif)
1919

20+
## Fast track
21+
22+
## 1. Use
23+
```swift
24+
try await Http.Get.from(url, retry: 5)
25+
```
26+
```swift
27+
try await Http.Post.from(url, taskDelegate : TaskDelegate())
28+
```
29+
30+
```swift
31+
try await Http.Put.from(url, body: data)
32+
```
33+
34+
```swift
35+
try await Http.Delete.from(url)
36+
```
37+
38+
## Extended track
39+
2040
## 1. Create
2141
```swift
2242
let url = URL(string: "http://localhost:3000")
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
//
2+
// RequestHelper.swift
3+
//
4+
//
5+
// Created by Igor on 11.03.2023.
6+
//
7+
8+
import Foundation
9+
10+
/// A URL load request builder method
11+
/// - Parameters:
12+
/// - baseURL: Base url
13+
/// - path: Path
14+
/// - method: The HTTP request method
15+
/// - query: An array of name-value pairs
16+
/// - body: The data sent as the message body of a request, such as for an HTTP POST or PUT requests
17+
/// - headers: A dictionary containing all of the HTTP header fields for a request
18+
/// - Returns: A URL load request
19+
func buildURLRequest(
20+
_ baseURL : URL,
21+
for path: String,
22+
method : Http.Method = .get,
23+
query : Http.Query? = nil,
24+
body : Data? = nil,
25+
headers : Http.Headers?
26+
) throws -> URLRequest {
27+
//url + query
28+
let url = try buildURL(baseURL: baseURL, for: path, query: query)
29+
30+
var request = URLRequest(url: url)
31+
32+
//headers
33+
if let headers{
34+
request.allHTTPHeaderFields = headers
35+
}
36+
37+
// method
38+
request.httpMethod = method.rawValue
39+
40+
//body
41+
if let body = body{
42+
request.httpBody = body
43+
44+
}
45+
46+
return request
47+
}
48+
49+
/// A URL load request builder method
50+
/// - Parameters:
51+
/// - url: Base url
52+
/// - method: The HTTP request method
53+
/// - query: An array of name-value pairs
54+
/// - body: The data sent as the message body of a request, such as for an HTTP POST or PUT requests
55+
/// - headers: A dictionary containing all of the HTTP header fields for a request
56+
/// - Returns: A URL load request
57+
func buildURLRequest(
58+
for url : URL,
59+
method : Http.Method = .get,
60+
query : Http.Query? = nil,
61+
body : Data? = nil,
62+
headers : Http.Headers?
63+
64+
) throws -> URLRequest {
65+
66+
var request = URLRequest(url: url)
67+
68+
//headers
69+
if let headers{
70+
request.allHTTPHeaderFields = headers
71+
}
72+
73+
// method
74+
request.httpMethod = method.rawValue
75+
76+
//body
77+
if let body = body{
78+
request.httpBody = body
79+
80+
}
81+
82+
return request
83+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
//
2+
// SendHelper.swift
3+
//
4+
//
5+
// Created by Igor on 11.03.2023.
6+
//
7+
8+
import Foundation
9+
import retry_policy_service
10+
11+
/// - Parameters:
12+
/// - request: A URL load request that is independent of protocol or URL scheme
13+
/// - retry: ``RetryService`` strategy
14+
/// - taskDelegate: A protocol that defines methods that URL session instances call on their delegates to handle task-level events
15+
func sendRetry(
16+
with request : URLRequest,
17+
retry strategy : RetryService.Strategy,
18+
_ taskDelegate: ITaskDelegate? = nil,
19+
_ session : URLSession = .shared
20+
) async throws -> (Data, URLResponse)
21+
{
22+
let service = RetryService(strategy: strategy)
23+
24+
for delay in service.dropLast(){
25+
do{
26+
return try await session.data(for: request, delegate: taskDelegate)
27+
}catch{
28+
#if DEBUG
29+
print("retry send \(delay)")
30+
#endif
31+
}
32+
33+
try? await Task.sleep(nanoseconds: delay)
34+
}
35+
36+
#if DEBUG
37+
//print("retry send last")
38+
#endif
39+
40+
/// one more time to let the error to propagate if it fails the last time
41+
return try await session.data(for: request, delegate: taskDelegate)
42+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
//
2+
// UrlHelper.swift
3+
//
4+
//
5+
// Created by Igor on 11.03.2023.
6+
//
7+
8+
import Foundation
9+
import retry_policy_service
10+
11+
/// Url builder method
12+
/// - Parameters:
13+
/// - url: url
14+
/// - query: An array of name-value pairs
15+
/// - Returns: A value that identifies the location of a resource
16+
public func append(_ url: URL,with query : Http.Query? = nil) throws -> URL{
17+
18+
guard var components = URLComponents(url: url, resolvingAgainstBaseURL: true)else{
19+
throw URLError(.badURL)
20+
}
21+
22+
if let query = query, query.isEmpty == false {
23+
components.queryItems = query.map(URLQueryItem.init) }
24+
25+
guard let url = components.url else { throw URLError(.badURL) }
26+
27+
return url
28+
}
29+
30+
/// Url builder method
31+
/// - Parameters:
32+
/// - baseURL: Base url
33+
/// - path: Path
34+
/// - query: An array of name-value pairs
35+
/// - Returns: A value that identifies the location of a resource
36+
func buildURL(baseURL: URL, for path: String, query : Http.Query? = nil) throws -> URL{
37+
38+
guard let url = URL(string: path, relativeTo: baseURL)else{
39+
throw URLError(.badURL)
40+
}
41+
42+
return try append(url, with: query)
43+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
//
2+
// Direct.swift
3+
//
4+
//
5+
// Created by Igor on 11.03.2023.
6+
//
7+
8+
import Foundation
9+
import retry_policy_service
10+
11+
public extension Http{
12+
13+
struct Get{
14+
public static func from(
15+
_ url : URL,
16+
query : Http.Query? = nil,
17+
headers : Http.Headers? = nil,
18+
retry : UInt = 1,
19+
taskDelegate: ITaskDelegate? = nil
20+
) async throws -> (Data, URLResponse){
21+
let request = try buildURLRequest(for: url, query: query, headers: headers)
22+
let strategy = RetryService.Strategy.exponential(retry: retry)
23+
24+
return try await sendRetry(with: request, retry: strategy)
25+
}
26+
}
27+
28+
struct Post{
29+
public static func from(
30+
_ url : URL,
31+
query : Http.Query? = nil,
32+
body : Data? = nil,
33+
headers : Http.Headers? = nil,
34+
retry : UInt = 1,
35+
taskDelegate: ITaskDelegate? = nil
36+
) async throws -> (Data, URLResponse){
37+
let request = try buildURLRequest(for: url, method: .post, query: query, body: body, headers: headers)
38+
let strategy = RetryService.Strategy.exponential(retry: retry)
39+
40+
return try await sendRetry(with: request, retry: strategy)
41+
}
42+
}
43+
44+
struct Put{
45+
public static func from(
46+
_ url : URL,
47+
query : Http.Query? = nil,
48+
body : Data? = nil,
49+
headers : Http.Headers? = nil,
50+
retry : UInt = 1,
51+
taskDelegate: ITaskDelegate? = nil
52+
) async throws -> (Data, URLResponse){
53+
let request = try buildURLRequest(for: url, method: .put, query: query, body: body, headers: headers)
54+
let strategy = RetryService.Strategy.exponential(retry: retry)
55+
56+
return try await sendRetry(with: request, retry: strategy)
57+
}
58+
}
59+
60+
struct Delete{
61+
public static func from(
62+
_ url : URL,
63+
query : Http.Query? = nil,
64+
headers : Http.Headers? = nil,
65+
retry : UInt = 1,
66+
taskDelegate: ITaskDelegate? = nil
67+
) async throws -> (Data, URLResponse){
68+
let request = try buildURLRequest(for: url, method: .delete, query: query, headers: headers)
69+
let strategy = RetryService.Strategy.exponential(retry: retry)
70+
71+
return try await sendRetry(with: request, retry: strategy)
72+
}
73+
}
74+
}

Sources/async-http-client/proxy/http/Http.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,10 @@ import Foundation
1111
@available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *)
1212
public struct Http{
1313

14+
/// An array of name-value pairs for a request
15+
public typealias Query = [(String, String?)]
1416

17+
/// A dictionary containing all of the HTTP header fields for a request
18+
public typealias Headers = [String: String]
19+
1520
}

0 commit comments

Comments
 (0)