Skip to content

Update readme with simple tutorial #2

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Apr 10, 2019
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 120 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,122 @@
# swift-nio-http-client
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SwiftNIOHTTPClient

This package provides simple HTTP Client library built on top of SwiftNIO.

Swift HTTP Client library built on top of SwiftNIO
## Getting Started

Add the following entry in your <code>Package.swift</code> to start using <code>HTTPClient</code>:

### Swift 5

```swift
dependencies: [
.package(url: "https://github.com/swift-server/swift-nio-http-client.git", from: "1.0.0")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

did we tag yet? if not, maybe be more explicit about that, see swift-log and swift-metrics READMEs

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

replaced with .branch("master")

]
```

## Status

This library provides the following:
1. Async single request methods
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"single request methods" is a bit unclear, rephrase?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed, do you thinks its better now?

2. Simple follow-redirect support (cookie headers are dropped)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

support

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed, thanks

3. Body download streaming
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Streaming body download

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed, thanks

4. TLS support
5. Cookie parsing (but not storage)

## How to use
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Usage guide

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed


### Request-Response API
The code snippet below illustrates how to make a simple GET request to a remote server:

```import HTTPClient
Copy link
Contributor

@tomerd tomerd Apr 9, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"```swift"

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed here and in all other blocks


let httpClient = HTTPClient(eventLoopGroupProvider: .createNew)
let response = try httpClient.get(url: "https://swift.org").wait()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

personally i dont love guiding users to use wait, and where we do we should make a note that this is not the proper way to do things

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good point! re-wrote example


if response.status == .ok {
// handle the response
}

// close the client
try? httpClient.syncShutdown()
```

It is important to close client instance after use to cleanly shutdown underlying NIO ```EventLoopGroup```. Alternatively, you can provide shared ```EventLoopGroup```:
```
let httpClient = HTTPClient(eventLoopGroupProvider: .shared(userProvidedGroup))
```
In this case shutdown of the client is not neccecary.

Library provides methods for most HTTP-methods. In case you need to have more control over the method, or you want to add headers or body, use ```HTTPRequest``` struct:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Library provides methods for most HTTP-methods -> Most common HTTP methods are supported out of the box

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done, thanks!

```import HTTPClient

let httpClient = HTTPClient(eventLoopGroupProvider: .createNew)
defer {
try? httpClient.syncShutdown()
}

var request = try HTTPRequest(url: "https://swift.org", method: .POST)
request.headers.add(name: "User-Agent", value: "Swift HTTPClient")
request.body = .string("some-body")

let response = try httpClient.execute(request: request).wait()

if response.status == .ok {
// handle the response
}
```

### Redirect following
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redirects

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

To enable follow-redirects behaviour, enable in using client configuration:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Enable follow-redirects behavior using the client configuration:

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

```
let httpClient = HTTPClient(eventLoopGroupProvider: .createNew,
configuration: HTTPClientConfiguration(followRedirects: true))
```

### Timeouts
Timeouts (connect and read) can be set in the client configuration:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Timeouts (connect and read) can also be set using the client configuration:

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

```
let httpClient = HTTPClient(eventLoopGroupProvider: .createNew,
configuration: HTTPClientConfiguration(timeout: Timeout(connectTimeout: .seconds(1),
readTimeout: .seconds(1))))
```
or on per-request basis:
```
let response = try httpClient.execute(request: request, timeout: Timeout(connectTimeout: .seconds(1), readTimeout: .seconds(1))).wait()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

format to be more readable

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

re-formatted, is it better now?

```

### Streaming
In case greater control over body processing is needed or you want to process HTTP Reponse body in a streaming manner, following delegate protocol could be used (example shows how to count bytes in response body without copiying it to the memory):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When dealing with larger amount of data, it's critical to steam the response body instead of aggregating it-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:

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed, thanks

```
class CountingDelegate: HTTPResponseDelegate {
typealias Response = Int

var count = 0

func didTransmitRequestBody() {
// this is executed when request is sent, called once
}

func didReceiveHead(_ head: HTTPResponseHead) {
// this is executed when we receive HTTP Reponse head part of the request (it contains response code and headers), called once
}

func didReceivePart(_ buffer: ByteBuffer) {
// this is executed when we receive parts of the response body, could be called zero or more times
count += buffer.readableBytes
}

func didFinishRequest() throws -> Int {
// 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
return count
}

func didReceiveError(_ error: Error) {
// this is called when we receive any network-related error, called once
}
}

let request = try HTTPRequest(url: "https://swift.org")
let delegate = CountingDelegate()

let count = try httpClient.execute(request: request, delegate: delegate).wait()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

drop wait

```