You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@@ -20,40 +22,178 @@ Inspired by **Swift** & **SwiftUI**’s design philosophy, it allows you to defi
20
22
21
23
22
24
23
-
## 📦 Installation
25
+
## 🚀 Getting Started
24
26
25
-
Add via **Swift Package Manager**:
27
+
This guide walks you through the core building blocks:
28
+
1. Defining a request.
29
+
2. Adding headers, parameters, and body.
30
+
3. Building a client.
31
+
4. Sending a request.
32
+
33
+
34
+
### 1. Defining a request
35
+
To define a request, use the [`@Request`](https://swiftpackageindex.com/swiftyjoeyy/swift-networking/main/documentation/networking/request(_:)) macro. This adds conformance to the [`Request`](https://swiftpackageindex.com/swiftyjoeyy/swift-networking/main/documentation/networking/request) protocol, which requires a `request` property similar to SwiftUI’s body.
36
+
Inside that property, you start with an [`HTTPRequest`](https://swiftpackageindex.com/swiftyjoeyy/swift-networking/main/documentation/networking/httprequest), which represents the core of the request.
37
+
38
+
You can:
39
+
40
+
- Provide a url to override the client’s base URL
41
+
- Add an optional path
42
+
- Set the HTTP method using [`method(_:)`](https://swiftpackageindex.com/swiftyjoeyy/swift-networking/main/documentation/networking/request/method(_:))
43
+
- Append extra path components using [`appending(_:)`](https://swiftpackageindex.com/swiftyjoeyy/swift-networking/main/documentation/networking/request/appending(_:))
This creates a simple GET request to `https://www.google.com/test/cats/images`.
30
56
31
-
Then add `"Networking"` to your target dependencies.
57
+
You can also compose and override requests:
58
+
59
+
```swift
60
+
@Request
61
+
structTestRequest {
62
+
@Headervar test: String {
63
+
return"Computed"
64
+
}
65
+
var request: some Request {
66
+
TestingRequest() // TestingRequest instead of HTTPRequest
67
+
.timeout(90)
68
+
.method(.post)
69
+
}
70
+
}
71
+
```
32
72
33
73
74
+
### 2. Adding Headers, Parameters, and Body
34
75
35
-
## 🚀 Example
76
+
`Networking` offers multiple ways to add headers, query parameters, and request bodies. You can use macros for top level values or chaining modifiers for inline customization.
36
77
37
-
Here's what a full request flow looks like — from client configuration to building a reusable, composable request:
78
+
#### 🧩 Adding Parameters
79
+
80
+
Use [`Parameter`](https://swiftpackageindex.com/swiftyjoeyy/swift-networking/main/documentation/networking/parameter) to create parameters from `String`, `Int`, `Double`, or `Bool` values, including arrays of those types.
81
+
You can also use [`ParametersGroup`](https://swiftpackageindex.com/swiftyjoeyy/swift-networking/main/documentation/networking/parametersgroup) to group multiple parameters into one modifier.
82
+
83
+
To add parameters to a request, you use the [`@Parameter`](https://swiftpackageindex.com/swiftyjoeyy/swift-networking/main/documentation/networking/parameter(_:)) macro, or dynamically through modifier methods:
38
84
39
85
```swift
40
-
let client =MyClient()
86
+
@RequeststructSearchRequest {
87
+
@Parametervar query: String// Using the name of the property
88
+
@Parameter("search_query") var query: String// Using a custom name.
let data =tryawait client.dataTask(TestingRequest())
44
-
.decode(with: JSONDecoder())
45
-
.retryPolicy(.doNotRetry)
46
-
.decode(as: String.self)
47
-
48
-
print(data)
103
+
#### 📬 Adding Headers
104
+
105
+
Use [`Header`](https://swiftpackageindex.com/swiftyjoeyy/swift-networking/main/documentation/networking/header) to define headers from `String`, `Int`, `Double`, or `Bool` values.
106
+
You can also use [`HeadersGroup`](https://swiftpackageindex.com/swiftyjoeyy/swift-networking/main/documentation/networking/headersgroup) if you want to group multiple headers in a single modifier, or inject a raw dictionary `[String: String]`.
107
+
You also get convenience types like: [`AcceptLanguage`](https://swiftpackageindex.com/swiftyjoeyy/swift-networking/main/documentation/networking/acceptlanguage), [`ContentDisposition`](https://swiftpackageindex.com/swiftyjoeyy/swift-networking/main/documentation/networking/contentdisposition) & [`ContentType`](https://swiftpackageindex.com/swiftyjoeyy/swift-networking/main/documentation/networking/contenttype).
108
+
Similar to parameters, headers can also be declared statically using the [`@Header`](https://swiftpackageindex.com/swiftyjoeyy/swift-networking/main/documentation/networking/header(_:)) macro or applied dynamically using modifiers:
109
+
110
+
```swift
111
+
@RequeststructAuthenticatedRequest {
112
+
@Headervar token: String// Using the name of the property.
113
+
@Header("Authorization") var token: String// Using a custom name.
114
+
let includeLang: Bool
115
+
var request: some Request {
116
+
HTTPRequest(path: "me")
117
+
.additionalHeaders {
118
+
Header("Custom-Header", value: "value")
119
+
if includeLang {
120
+
AcceptLanguage("en")
121
+
}
122
+
}.additionalHeader("version", value: "1.0")
123
+
}
124
+
}
125
+
```
126
+
127
+
#### 📦 Adding a Request Body
128
+
129
+
Currently, `Networking` supports [`JSON`](https://swiftpackageindex.com/swiftyjoeyy/swift-networking/main/documentation/networking/json) and [`FormData`](https://swiftpackageindex.com/swiftyjoeyy/swift-networking/main/documentation/networking/formdata) request bodies.
130
+
To apply a body to a request, you can use the [`body(_:)`](https://swiftpackageindex.com/swiftyjoeyy/swift-networking/main/documentation/networking/request/body(_:)) modifier, or convenience modifiers for `json`:
131
+
132
+
##### ✅ Using .body(...) Modifier
133
+
134
+
```swift
135
+
HTTPRequest(path: "upload")
136
+
.body {
137
+
// JSON
138
+
JSON(["dict":"data"]) // Dictionary
139
+
JSON(Data()) // Raw data.
140
+
JSON(EncodableUser()) // Encodable types.
141
+
142
+
// FormData
143
+
FormData {
144
+
FormDataBody( /// Raw data
145
+
"Image",
146
+
data: Data(),
147
+
fileName: "image.png",
148
+
mimeType: .png
149
+
)
150
+
FormDataFile( // Data from a file.
151
+
"File",
152
+
fileURL: URL(filePath: "filePath"),
153
+
fileName: "file",
154
+
mimeType: .fileURL
155
+
)
156
+
}
157
+
}
158
+
```
159
+
160
+
##### ✅ Using JSON Convenience Modifiers
161
+
```swift
162
+
HTTPRequest(path: "create")
163
+
.json(["name":"John", "age":30]) // Dictionary.
164
+
.json(Data()) // Raw data.
165
+
.json(EncodableUser()) // Encodable types.
166
+
```
167
+
> [!CAUTION]
168
+
> If multiple `.body()` or `.json()` modifiers are used, the last one overrides the previous. This applies to all modifiers, modifier order matters.
169
+
170
+
#### 🧱 Inline Modifiers with HTTPRequest
171
+
172
+
You can also include modifiers directly in the `HTTPRequest` initializer. This gives you a clean, SwiftUI style declaration for most common request scenarios.
173
+
174
+
```swift
175
+
HTTPRequest(path: "submit") {
176
+
Header("X-Token", value: "123")
177
+
Parameter("query", value: "swift")
178
+
JSON(["key":"value"])
49
179
}
50
180
```
51
181
52
-
### 🧩 Declarative Client Configuration
182
+
183
+
### 3. Building a client
184
+
185
+
To define a networking client, use the [`@Client`](https://swiftpackageindex.com/swiftyjoeyy/swift-networking/main/documentation/networking/client()) macro. This macro adds conformance to the [`NetworkClient`](https://swiftpackageindex.com/swiftyjoeyy/swift-networking/main/documentation/networking/networkclient) protocol, which requires a `session` property. This property returns a [`Session`](https://swiftpackageindex.com/swiftyjoeyy/swift-networking/main/documentation/networking/session) instance that describes how your requests should be configured and executed.
186
+
187
+
> [!IMPORTANT]
188
+
> Do not call the session property directly. It’s a computed property that creates a new session each time it’s accessed.
189
+
> Always send requests using the client instance itself (e.g. try await client.dataTask(...)).
190
+
> You should also hold on to the client instance created either using a singleton or by dependency injection to avoid creating multiple instances.
191
+
192
+
Inside the session property, you can create and customize a `Session` using a closure that returns a configured `URLSessionConfiguration`.
193
+
From there, you can apply additional behaviors such as Base URL, Logging, Retry policy, Authorization, Response validation, Encoding/decoding strategies.
53
194
54
195
```swift
55
-
@Client
56
-
structMyClient {
196
+
@ClientstructMyClient {
57
197
var session: Session {
58
198
Session {
59
199
URLSessionConfiguration.default
@@ -66,34 +206,32 @@ struct MyClient {
66
206
.headers {
67
207
Header("Key", value: "Value")
68
208
}
69
-
}.onRequest { request, task, session in
70
-
// handle request creation
71
-
return request
72
-
}.enableLogs(true)
73
-
.validate(for: [.accepted, .ok])
74
-
.retry(limit: 2, for: [.conflict, .badRequest])
75
-
.baseURL(URL(string: "example.com"))
76
-
.encode(with: JSONEncoder())
209
+
}
210
+
.authorization(BearerAuthProvider())
211
+
.baseURL("https://example.com")
77
212
.decode(with: JSONDecoder())
213
+
.encode(with: JSONEncoder())
214
+
.retry(limit: 2, delay: 2)
215
+
.enableLogs(true)
216
+
.validate(for: [.badGateway, .created])
78
217
}
79
218
}
80
219
```
81
220
82
-
### ⚙️ Custom Configuration Values
221
+
####⚙️ Custom Configuration Values
83
222
84
-
You can define custom configuration keys using the `ConfigurationValues` extension:
223
+
You can define custom configuration keys using the [`@Config`](https://swiftpackageindex.com/swiftyjoeyy/swift-networking/main/documentation/networking/config(forceunwrapped:)) macro & extending [`ConfigurationValues`](https://swiftpackageindex.com/swiftyjoeyy/swift-networking/main/documentation/networking/configurationvalues):
85
224
86
225
```swift
87
226
extensionConfigurationValues {
88
227
@Configvar customConfig =CustomValue()
89
228
}
90
229
```
91
230
92
-
Then, you can set it on a task or on the session using:
231
+
Then, you can set it on a task or on the session using the modifier [`configuration(_:_:)`](https://swiftpackageindex.com/swiftyjoeyy/swift-networking/main/documentation/networking/configurable/configuration(_:_:)):
93
232
94
233
```swift
95
-
@Client
96
-
structMyClient {
234
+
@ClientstructMyClient {
97
235
var session: Session {
98
236
Session()
99
237
.configuration(\.customConfig, CustomValue())
@@ -107,74 +245,53 @@ let data = try await client.dataTask(TestingRequest())
107
245
108
246
This allows you to define project-specific config values and inject them anywhere in your request or session pipeline.
109
247
110
-
### 🧾 Declarative Request Definitions
111
248
112
-
```swift
113
-
@Request("test-request-id")
114
-
structTestingRequest {
115
-
@Header("customKey") var test ="test"
116
-
@Parametervar testing =1
249
+
### 4. Sending a request
117
250
118
-
var request: some Request {
119
-
HTTPRequest(url: "https://www.google.com") {
120
-
Header("test", value: "value")
121
-
Parameter("some", values: ["1", "2"])
122
-
JSON("value")
123
-
}.body {
124
-
FormData {
125
-
FormDataBody(
126
-
"Image",
127
-
data: Data(),
128
-
fileName: "image.png",
129
-
mimeType: .png
130
-
)
131
-
FormDataFile(
132
-
"File",
133
-
fileURL: URL(filePath: "filePath"),
134
-
fileName: "file",
135
-
mimeType: .fileURL
136
-
)
137
-
}
138
-
}.method(.get)
139
-
.timeout(90)
140
-
.cachePolicy(.reloadIgnoringLocalCacheData)
141
-
.appending(path: "v1")
142
-
.additionalHeaders {
143
-
Header("Header", value: "10")
144
-
AcceptLanguage("en")
145
-
}.additionalParameters {
146
-
Parameter("Item", value: "value")
147
-
}
148
-
}
149
-
}
251
+
To send a request, you start by creating a task from a client. The framework provides two main types of tasks:
252
+
-[`dataTask`](https://swiftpackageindex.com/swiftyjoeyy/swift-networking/main/documentation/networking/session/datatask(_:)) — for requests that return data.
253
+
-[`downloadTask`](https://swiftpackageindex.com/swiftyjoeyy/swift-networking/main/documentation/networking/session/downloadtask(_:)) — for file downloads.
254
+
255
+
Each task can be configured individually using the same modifiers available on `Session` (e.g. retry, decoding, etc.), giving you full control per request.
256
+
257
+
```swift
258
+
let task =MyClient()
259
+
.dataTask(MyRequest())
260
+
.retry(limit: 2)
261
+
.validate(for: [.ok, .notModified])
150
262
```
151
263
152
-
### 🔁 Composing and Overriding Requests
264
+
To start a task you either call [`resume()`](https://swiftpackageindex.com/swiftyjoeyy/swift-networking/main/documentation/networking/networkingtask/resume()) manually, or access the response directly (recommended) using [`response()`](https://swiftpackageindex.com/swiftyjoeyy/swift-networking/main/documentation/networking/networktask/response()) or decode it to a specific type using [`decode(as:)`](https://swiftpackageindex.com/swiftyjoeyy/swift-networking/main/documentation/networking/datatask/decode(as:))
153
265
154
266
```swift
155
-
@Request
156
-
structTestRequest {
157
-
@Headervar test: String {
158
-
return"Computed"
159
-
}
160
-
var timeout: TimeInterval =90
267
+
let task =MyClient().dataTask(MyRequest())
161
268
162
-
var request: some Request {
163
-
TestingRequest()
164
-
.timeout(timeout)
165
-
.method(.post)
166
-
.additionalHeaders {
167
-
Header("Additional", value: "value")
168
-
}.appending(paths: "v3")
169
-
}
170
-
}
269
+
task.resume()
270
+
let result =tryawait task.response()
271
+
let user =tryawait task.decode(as: User.self)
171
272
```
172
273
274
+
> [!NOTE]
275
+
> A task will only send the request once.
276
+
> If `response()` or `decode(as:)` is called multiple times, the framework will await the result of the first call instead of resending the request.
Then add `"Networking"` to your target dependencies.
289
+
173
290
174
291
175
292
## 📖 Documentation
176
293
177
-
WIP: Full documentation and guides will be available soon.
294
+
The [documentation](https://swiftpackageindex.com/SwiftyJoeyy/swift-networking/main/documentation/networking) is provided by [swiftpackageindex](https://swiftpackageindex.com).
0 commit comments