Skip to content

Commit 43d1b72

Browse files
authored
Merge pull request #2 from swift-server/updated-readme
Update readme with simple tutorial
2 parents da770ca + 9be0315 commit 43d1b72

File tree

1 file changed

+147
-2
lines changed

1 file changed

+147
-2
lines changed

Diff for: README.md

+147-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,148 @@
1-
# swift-nio-http-client
1+
# SwiftNIOHTTPClient
2+
This package provides simple HTTP Client library built on top of SwiftNIO.
23

3-
Swift HTTP Client library built on top of SwiftNIO
4+
This library provides the following:
5+
1. Asynchronous and non-blocking request methods
6+
2. Simple follow-redirects (cookie headers are dropped)
7+
3. Streaming body download
8+
4. TLS support
9+
5. Cookie parsing (but not storage)
10+
11+
---
12+
13+
**NOTE**: You will need [Xcode 10.2](https://itunes.apple.com/us/app/xcode/id497799835) or [Swift 5.0](https://swift.org/download/#swift-50) to try out `SwiftNIOHTTPClient`.
14+
15+
---
16+
17+
## Getting Started
18+
19+
#### Adding the dependency
20+
Add the following entry in your <code>Package.swift</code> to start using <code>HTTPClient</code>:
21+
22+
```swift
23+
// it's early days here so we haven't tagged a version yet, but will soon
24+
.package(url: "https://github.com/swift-server/swift-nio-http-client.git", .branch("master"))
25+
```
26+
and ```SwiftNIOHTTP``` dependency to your target:
27+
```swift
28+
.target(name: "MyApp", dependencies: ["NIOHTTPClient"]),
29+
```
30+
31+
#### Request-Response API
32+
The code snippet below illustrates how to make a simple GET request to a remote server:
33+
34+
```swift
35+
import HTTPClient
36+
37+
let httpClient = HTTPClient(eventLoopGroupProvider: .createNew)
38+
httpClient.get(url: "https://swift.org").whenComplete { result in
39+
switch result {
40+
case .failure(let error):
41+
// process error
42+
case .success(let response):
43+
if let response.status == .ok {
44+
// handle response
45+
} else {
46+
// handle remote error
47+
}
48+
}
49+
}
50+
```
51+
52+
It is important to close client instance after use to cleanly shutdown underlying NIO ```EventLoopGroup```:
53+
```
54+
try? httpClient.syncShutdown()
55+
```
56+
Alternatively, you can provide shared ```EventLoopGroup```:
57+
```swift
58+
let httpClient = HTTPClient(eventLoopGroupProvider: .shared(userProvidedGroup))
59+
```
60+
In this case shutdown of the client is not neccecary.
61+
62+
## Usage guide
63+
64+
Most common HTTP methods are supported out of the box. In case you need to have more control over the method, or you want to add headers or body, use ```HTTPRequest``` struct:
65+
```swift
66+
import HTTPClient
67+
68+
let httpClient = HTTPClient(eventLoopGroupProvider: .createNew)
69+
defer {
70+
try? httpClient.syncShutdown()
71+
}
72+
73+
var request = try HTTPRequest(url: "https://swift.org", method: .POST)
74+
request.headers.add(name: "User-Agent", value: "Swift HTTPClient")
75+
request.body = .string("some-body")
76+
77+
httpClient.execute(request: request).whenComplete { result in
78+
switch result {
79+
case .failure(let error):
80+
// process error
81+
case .success(let response):
82+
if let response.status == .ok {
83+
// handle response
84+
} else {
85+
// handle remote error
86+
}
87+
}
88+
}
89+
```
90+
91+
### Redirects following
92+
Enable follow-redirects behavior using the client configuration:
93+
```swift
94+
let httpClient = HTTPClient(eventLoopGroupProvider: .createNew,
95+
configuration: HTTPClientConfiguration(followRedirects: true))
96+
```
97+
98+
### Timeouts
99+
Timeouts (connect and read) can also be set using the client configuration:
100+
```swift
101+
let timeout = Timeout(connectTimeout: .seconds(1), readTimeout: .seconds(1))
102+
let httpClient = HTTPClient(eventLoopGroupProvider: .createNew,
103+
configuration: HTTPClientConfiguration(timeout: timeout))
104+
```
105+
or on per-request basis:
106+
```swift
107+
let timeout = Timeout(connectTimeout: .seconds(1), readTimeout: .seconds(1))
108+
httpClient.execute(request: request, timeout: timeout)
109+
```
110+
111+
### Streaming
112+
When dealing with larger amount of data, it's critical to stream the response body instead of aggregating in-memory. Handling a response stream is done using a delegate protocol. The following example demonstrates how to count the number of bytes in a streaming response body:
113+
```swift
114+
class CountingDelegate: HTTPResponseDelegate {
115+
typealias Response = Int
116+
117+
var count = 0
118+
119+
func didTransmitRequestBody() {
120+
// this is executed when request is sent, called once
121+
}
122+
123+
func didReceiveHead(_ head: HTTPResponseHead) {
124+
// this is executed when we receive HTTP Reponse head part of the request (it contains response code and headers), called once
125+
}
126+
127+
func didReceivePart(_ buffer: ByteBuffer) {
128+
// this is executed when we receive parts of the response body, could be called zero or more times
129+
count += buffer.readableBytes
130+
}
131+
132+
func didFinishRequest() throws -> Int {
133+
// this is called when request is fully read, called once, this is where you return a result or throw any errors you require to propagate to the client
134+
return count
135+
}
136+
137+
func didReceiveError(_ error: Error) {
138+
// this is called when we receive any network-related error, called once
139+
}
140+
}
141+
142+
let request = try HTTPRequest(url: "https://swift.org")
143+
let delegate = CountingDelegate()
144+
145+
try httpClient.execute(request: request, delegate: delegate).future.whenSuccess { count in
146+
print(count)
147+
}
148+
```

0 commit comments

Comments
 (0)