Skip to content

Commit 0c617a4

Browse files
artemredkinYasumoto
authored andcommitted
document public API (#62)
Co-Authored-By: Joe Smith <[email protected]>
1 parent 8fa6c6f commit 0c617a4

File tree

4 files changed

+269
-11
lines changed

4 files changed

+269
-11
lines changed

‎Sources/AsyncHTTPClient/HTTPClient+HTTPCookie.swift‎

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,33 @@ import Foundation
1616
import NIOHTTP1
1717

1818
extensionHTTPClient{
19+
/// A representation of an HTTP cookie.
1920
publicstructCookie{
21+
/// The name of the cookie.
2022
publicvarname:String
23+
/// The cookie's string value.
2124
publicvarvalue:String
25+
/// The cookie's path.
2226
publicvarpath:String
27+
/// The domain of the cookie.
2328
publicvardomain:String?
29+
/// The cookie's expiration date.
2430
publicvarexpires:Date?
31+
/// The cookie's age in seconds.
2532
publicvarmaxAge:Int?
33+
/// Whether the cookie should only be sent to HTTP servers.
2634
publicvarhttpOnly:Bool
35+
/// Whether the cookie should only be sent over secure channels.
2736
publicvarsecure:Bool
2837

29-
publicinit?(from string:String, defaultDomain:String){
30-
letcomponents= string.components(separatedBy:";").map{
38+
/// Create a Cookie by parsing a `Set-Cookie` header.
39+
///
40+
/// - parameters:
41+
/// - header: String representation of the `Set-Cookie` response header.
42+
/// - defaultDomain: Default domain to use if cookie was sent without one.
43+
/// - returns: nil if the header is invalid.
44+
publicinit?(header:String, defaultDomain:String){
45+
letcomponents= header.components(separatedBy:";").map{
3146
$0.trimmingCharacters(in:.whitespaces)
3247
}
3348

@@ -90,6 +105,17 @@ extension HTTPClient{
90105
}
91106
}
92107

108+
/// Create HTTP cookie.
109+
///
110+
/// - parameters:
111+
/// - name: The name of the cookie.
112+
/// - value: The cookie's string value.
113+
/// - path: The cookie's path.
114+
/// - domain: The domain of the cookie, defaults to nil.
115+
/// - expires: The cookie's expiration date, defaults to nil.
116+
/// - maxAge: The cookie's age in seconds, defaults to nil.
117+
/// - httpOnly: Whether this cookie should be used by HTTP servers only, defaults to false.
118+
/// - secure: Whether this cookie should only be sent using secure channels, defaults to false.
93119
publicinit(name:String, value:String, path:String="/", domain:String?=nil, expires:Date?=nil, maxAge:Int?=nil, httpOnly:Bool=false, secure:Bool=false){
94120
self.name = name
95121
self.value = value
@@ -112,12 +138,13 @@ extension HTTPClient{
112138
}
113139
}
114140

115-
publicextensionHTTPClient.Response{
116-
internalvarcookieHeaders:[HTTPHeaders.Element]{
141+
extensionHTTPClient.Response{
142+
varcookieHeaders:[HTTPHeaders.Element]{
117143
return headers.filter{ $0.name.lowercased()=="set-cookie"}
118144
}
119145

120-
varcookies:[HTTPClient.Cookie]{
121-
returnself.cookieHeaders.compactMap{HTTPClient.Cookie(from: $0.value, defaultDomain:self.host)}
146+
/// List of HTTP cookies returned by the server.
147+
publicvarcookies:[HTTPClient.Cookie]{
148+
returnself.cookieHeaders.compactMap{HTTPClient.Cookie(header: $0.value, defaultDomain:self.host)}
122149
}
123150
}

‎Sources/AsyncHTTPClient/HTTPClient.swift‎

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,42 @@ import NIOConcurrencyHelpers
1818
import NIOHTTP1
1919
import NIOSSL
2020

21+
/// HTTPClient class provides API for request execution.
22+
///
23+
/// Example:
24+
///
25+
/// ```swift
26+
/// let client = HTTPClient(eventLoopGroupProvider = .createNew)
27+
/// client.get(url: "https://swift.org", deadline: .now() + .seconds(1)).whenComplete{result in
28+
/// switch result{
29+
/// case .failure(let error):
30+
/// // process error
31+
/// case .success(let response):
32+
/// if let response.status == .ok{
33+
/// // handle response
34+
/// } else{
35+
/// // handle remote error
36+
/// }
37+
/// }
38+
/// }
39+
/// ```
40+
///
41+
/// It is important to close the client instance, for example in a defer statement, after use to cleanly shutdown the underlying NIO `EventLoopGroup`:
42+
///
43+
/// ```swift
44+
/// try client.syncShutdown()
45+
/// ```
2146
publicclassHTTPClient{
2247
publicleteventLoopGroup:EventLoopGroup
2348
leteventLoopGroupProvider:EventLoopGroupProvider
2449
letconfiguration:Configuration
2550
letisShutdown=Atomic<Bool>(value:false)
2651

52+
/// Create an `HTTPClient` with specified `EventLoopGroup` provider and configuration.
53+
///
54+
/// - parameters:
55+
/// - eventLoopGroupProvider: Specify how `EventLoopGroup` will be created.
56+
/// - configuration: Client configuration.
2757
publicinit(eventLoopGroupProvider:EventLoopGroupProvider, configuration:Configuration=Configuration()){
2858
self.eventLoopGroupProvider = eventLoopGroupProvider
2959
switchself.eventLoopGroupProvider {
@@ -44,6 +74,7 @@ public class HTTPClient{
4474
}
4575
}
4676

77+
/// Shuts down the client and `EventLoopGroup` if it was created by the client.
4778
publicfunc syncShutdown()throws{
4879
switchself.eventLoopGroupProvider {
4980
case.shared:
@@ -58,6 +89,11 @@ public class HTTPClient{
5889
}
5990
}
6091

92+
/// Execute `GET` request using specified URL.
93+
///
94+
/// - parameters:
95+
/// - url: Remote URL.
96+
/// - deadline: Point in time by which the request must complete.
6197
publicfunc get(url:String, deadline:NIODeadline?=nil)->EventLoopFuture<Response>{
6298
do{
6399
letrequest=tryRequest(url: url, method:.GET)
@@ -67,6 +103,12 @@ public class HTTPClient{
67103
}
68104
}
69105

106+
/// Execute `POST` request using specified URL.
107+
///
108+
/// - parameters:
109+
/// - url: Remote URL.
110+
/// - body: Request body.
111+
/// - deadline: Point in time by which the request must complete.
70112
publicfunc post(url:String, body:Body?=nil, deadline:NIODeadline?=nil)->EventLoopFuture<Response>{
71113
do{
72114
letrequest=tryHTTPClient.Request(url: url, method:.POST, body: body)
@@ -76,6 +118,12 @@ public class HTTPClient{
76118
}
77119
}
78120

121+
/// Execute `PATCH` request using specified URL.
122+
///
123+
/// - parameters:
124+
/// - url: Remote URL.
125+
/// - body: Request body.
126+
/// - deadline: Point in time by which the request must complete.
79127
publicfunc patch(url:String, body:Body?=nil, deadline:NIODeadline?=nil)->EventLoopFuture<Response>{
80128
do{
81129
letrequest=tryHTTPClient.Request(url: url, method:.PATCH, body: body)
@@ -85,6 +133,12 @@ public class HTTPClient{
85133
}
86134
}
87135

136+
/// Execute `PUT` request using specified URL.
137+
///
138+
/// - parameters:
139+
/// - url: Remote URL.
140+
/// - body: Request body.
141+
/// - deadline: Point in time by which the request must complete.
88142
publicfunc put(url:String, body:Body?=nil, deadline:NIODeadline?=nil)->EventLoopFuture<Response>{
89143
do{
90144
letrequest=tryHTTPClient.Request(url: url, method:.PUT, body: body)
@@ -94,6 +148,11 @@ public class HTTPClient{
94148
}
95149
}
96150

151+
/// Execute `DELETE` request using specified URL.
152+
///
153+
/// - parameters:
154+
/// - url: Remote URL.
155+
/// - deadline: The time when the request must have been completed by.
97156
publicfunc delete(url:String, deadline:NIODeadline?=nil)->EventLoopFuture<Response>{
98157
do{
99158
letrequest=tryRequest(url: url, method:.DELETE)
@@ -103,11 +162,22 @@ public class HTTPClient{
103162
}
104163
}
105164

165+
/// Execute arbitrary HTTP request using specified URL.
166+
///
167+
/// - parameters:
168+
/// - request: HTTP request to execute.
169+
/// - deadline: Point in time by which the request must complete.
106170
publicfunc execute(request:Request, deadline:NIODeadline?=nil)->EventLoopFuture<Response>{
107171
letaccumulator=ResponseAccumulator(request: request)
108172
returnself.execute(request: request, delegate: accumulator, deadline: deadline).futureResult
109173
}
110174

175+
/// Execute arbitrary HTTP request and handle response processing using provided delegate.
176+
///
177+
/// - parameters:
178+
/// - request: HTTP request to execute.
179+
/// - delegate: Delegate to process response parts.
180+
/// - deadline: Point in time by which the request must complete.
111181
publicfunc execute<T:HTTPClientResponseDelegate>(request:Request, delegate:T, deadline:NIODeadline?=nil)->Task<T.Response>{
112182
leteventLoop=self.eventLoopGroup.next()
113183

@@ -187,10 +257,24 @@ public class HTTPClient{
187257
}
188258
}
189259

260+
/// `HTTPClient` configuration.
190261
publicstructConfiguration{
262+
/// TLS configuration, defaults to `TLSConfiguration.forClient()`.
191263
publicvartlsConfiguration:TLSConfiguration?
264+
/// Enables following 3xx redirects automatically, defaults to `false`.
265+
///
266+
/// Following redirects are supported:
267+
/// - `301: Moved Permanently`
268+
/// - `302: Found`
269+
/// - `303: See Other`
270+
/// - `304: Not Modified`
271+
/// - `305: Use Proxy`
272+
/// - `307: Temporary Redirect`
273+
/// - `308: Permanent Redirect`
192274
publicvarfollowRedirects:Bool
275+
/// Default client timeout, defaults to no timeouts.
193276
publicvartimeout:Timeout
277+
/// Upstream proxy, defaults to no proxy.
194278
publicvarproxy:Proxy?
195279

196280
publicinit(tlsConfiguration:TLSConfiguration?=nil, followRedirects:Bool=false, timeout:Timeout=Timeout(), proxy:Proxy?=nil){
@@ -208,15 +292,26 @@ public class HTTPClient{
208292
}
209293
}
210294

295+
/// Specifies how `EventLoopGroup` will be created and establishes lifecycle ownership.
211296
publicenumEventLoopGroupProvider{
297+
/// `EventLoopGroup` will be provided by the user. Owner of this group is responsible for its lifecycle.
212298
case shared(EventLoopGroup)
299+
/// `EventLoopGroup` will be created by the client. When `syncShutdown` is called, created `EventLoopGroup` will be shut down as well.
213300
case createNew
214301
}
215302

303+
/// Timeout configuration
216304
publicstructTimeout{
305+
/// Specifies connect timeout.
217306
publicvarconnect:TimeAmount?
307+
/// Specifies read timeout.
218308
publicvarread:TimeAmount?
219309

310+
/// Create timeout.
311+
///
312+
/// - parameters:
313+
/// - connect: `connect` timeout.
314+
/// - read: `read` timeout.
220315
publicinit(connect:TimeAmount?=nil, read:TimeAmount?=nil){
221316
self.connect = connect
222317
self.read = read
@@ -255,6 +350,7 @@ private extension ChannelPipeline{
255350
}
256351
}
257352

353+
/// Possible client errors.
258354
publicstructHTTPClientError:Error,Equatable,CustomStringConvertible{
259355
privateenumCode:Equatable{
260356
case invalidURL
@@ -281,16 +377,28 @@ public struct HTTPClientError: Error, Equatable, CustomStringConvertible{
281377
return"HTTPClientError.\(String(describing:self.code))"
282378
}
283379

380+
/// URL provided is invalid.
284381
publicstaticletinvalidURL=HTTPClientError(code:.invalidURL)
382+
/// URL does not contain host.
285383
publicstaticletemptyHost=HTTPClientError(code:.emptyHost)
384+
/// Client is shutdown and cannot be used for new requests.
286385
publicstaticletalreadyShutdown=HTTPClientError(code:.alreadyShutdown)
386+
/// URL does not contain scheme.
287387
publicstaticletemptyScheme=HTTPClientError(code:.emptyScheme)
388+
/// Provided URL scheme is not supported, supported schemes are: `http` and `https`
288389
publicstaticfunc unsupportedScheme(_ scheme:String)->HTTPClientError{returnHTTPClientError(code:.unsupportedScheme(scheme))}
390+
/// Request timed out.
289391
publicstaticletreadTimeout=HTTPClientError(code:.readTimeout)
392+
/// Remote connection was closed unexpectedly.
290393
publicstaticletremoteConnectionClosed=HTTPClientError(code:.remoteConnectionClosed)
394+
/// Request was cancelled.
291395
publicstaticletcancelled=HTTPClientError(code:.cancelled)
396+
/// Request contains invalid identity encoding.
292397
publicstaticletidentityCodingIncorrectlyPresent=HTTPClientError(code:.identityCodingIncorrectlyPresent)
398+
/// Request contains multiple chunks definitions.
293399
publicstaticletchunkedSpecifiedMultipleTimes=HTTPClientError(code:.chunkedSpecifiedMultipleTimes)
400+
/// Proxy response was invalid.
294401
publicstaticletinvalidProxyResponse=HTTPClientError(code:.invalidProxyResponse)
402+
/// Request does not contain `Content-Length` header.
295403
publicstaticletcontentLengthMissing=HTTPClientError(code:.contentLengthMissing)
296404
}

0 commit comments

Comments
(0)