Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

swift-server/async-http-client

 
 

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

This library provides the following:

  • Asynchronous and non-blocking request methods
  • Simple follow-redirects (cookie headers are dropped)
  • Streaming body download
  • TLS support
  • Automatic HTTP/2 over HTTPS (since version 1.7.0)
  • Cookie parsing (but not storage)

NOTE: You will needXcode 11.4 orSwift 5.2 to try outAsyncHTTPClient.


Getting Started

Adding the dependency

Add the following entry in yourPackage.swift to start usingHTTPClient:

.package(url:"https://github.com/swift-server/async-http-client.git", from:"1.0.0")

andAsyncHTTPClient dependency to your target:

.target(name:"MyApp", dependencies:[.product(name:"AsyncHTTPClient",package:"async-http-client")]),

Request-Response API

The code snippet below illustrates how to make a simple GET request to a remote server.

Please note that the example will spawn a newEventLoopGroup which willcreate fresh threads which is a very costly operation. In a real-world application that usesSwiftNIO for other parts of your application (for example a web server), please prefereventLoopGroupProvider: .shared(myExistingEventLoopGroup) to share theEventLoopGroup used by AsyncHTTPClient with other parts of your application.

If your application does not use SwiftNIO yet, it is acceptable to useeventLoopGroupProvider: .createNew but please make sure to share the returnedHTTPClient instance throughout your whole application. Do not create a large number ofHTTPClient instances witheventLoopGroupProvider: .createNew, this is very wasteful and might exhaust the resources of your program.

import AsyncHTTPClientlethttpClient=HTTPClient(eventLoopGroupProvider:.createNew)httpClient.get(url:"https://swift.org").whenComplete{ resultinswitch result{case.failure(let error):        // process error    case.success(let response):if response.status==.ok{            // handle response}else{            // handle remote error}}}

You should always shut downHTTPClient instances you created usingtry httpClient.syncShutdown(). Please note that you must not callhttpClient.syncShutdown before all requests of the HTTP client have finished, or else the in-flight requests will likely fail because their network connections are interrupted.

Usage guide

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 theHTTPRequest struct:

import AsyncHTTPClientlethttpClient=HTTPClient(eventLoopGroupProvider:.createNew)defer{try? httpClient.syncShutdown()}varrequest=tryHTTPClient.Request(url:"https://swift.org", method:.POST)request.headers.add(name:"User-Agent", value:"Swift HTTPClient")request.body=.string("some-body")httpClient.execute(request: request).whenComplete{ resultinswitch result{case.failure(let error):        // process error    case.success(let response):if response.status==.ok{            // handle response}else{            // handle remote error}}}

Redirects following

Enable follow-redirects behavior using the client configuration:

lethttpClient=HTTPClient(eventLoopGroupProvider:.createNew,                            configuration:HTTPClient.Configuration(followRedirects:true))

Timeouts

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

lettimeout=HTTPClient.Configuration.Timeout(connect:.seconds(1), read:.seconds(1))lethttpClient=HTTPClient(eventLoopGroupProvider:.createNew,                            configuration:HTTPClient.Configuration(timeout: timeout))

or on a per-request basis:

httpClient.execute(request: request, deadline:.now()+.milliseconds(1))

Streaming

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:

import NIOCoreimport NIOHTTP1classCountingDelegate:HTTPClientResponseDelegate{typealiasResponse=Intvarcount=0func didSendRequestHead(task:HTTPClient.Task<Response>, _ head:HTTPRequestHead){        // this is executed right after request head was sent, called once}func didSendRequestPart(task:HTTPClient.Task<Response>, _ part:IOData){        // this is executed when request body part is sent, could be called zero or more times}func didSendRequest(task:HTTPClient.Task<Response>){        // this is executed when request is fully sent, called once}func didReceiveHead(        task:HTTPClient.Task<Response>,         _ head:HTTPResponseHead)->EventLoopFuture<Void>{        // this is executed when we receive HTTP response head part of the request         // (it contains response code and headers), called once in case backpressure         // is needed, all reads will be paused until returned future is resolvedreturn task.eventLoop.makeSucceededFuture(())}func didReceiveBodyPart(        task:HTTPClient.Task<Response>,         _ buffer:ByteBuffer)->EventLoopFuture<Void>{        // this is executed when we receive parts of the response body, could be called zero or more times        count+= buffer.readableBytes        // in case backpressure is needed, all reads will be paused until returned future is resolvedreturn task.eventLoop.makeSucceededFuture(())}func didFinishRequest(task:HTTPClient.Task<Response>)throws->Int{        // this is called when the request is fully read, called once        // this is where you return a result or throw any errors you require to propagate to the clientreturn count}func didReceiveError(task:HTTPClient.Task<Response>, _ error:Error){        // this is called when we receive any network-related error, called once}}letrequest=tryHTTPClient.Request(url:"https://swift.org")letdelegate=CountingDelegate()httpClient.execute(request: request, delegate: delegate).futureResult.whenSuccess{ countinprint(count)}

File downloads

Based on theHTTPClientResponseDelegate example above you can build more complex delegates,the built-inFileDownloadDelegate is one of them. It allows streaming the downloaded dataasynchronously, while reporting the download progress at the same time, like in the followingexample:

letclient=HTTPClient(eventLoopGroupProvider:.createNew)letrequest=tryHTTPClient.Request(    url:"https://swift.org/builds/development/ubuntu1804/latest-build.yml")letdelegate=tryFileDownloadDelegate(path:"/tmp/latest-build.yml", reportProgress:{iflet totalBytes= $0.totalBytes{print("Total bytes count:\(totalBytes)")}print("Downloaded\($0.receivedBytes) bytes so far")})client.execute(request: request, delegate: delegate).futureResult.whenSuccess{ progressiniflet totalBytes= progress.totalBytes{print("Final total bytes count:\(totalBytes)")}print("Downloaded finished with\(progress.receivedBytes) bytes downloaded")}

Unix Domain Socket Paths

Connecting to servers bound to socket paths is easy:

lethttpClient=HTTPClient(eventLoopGroupProvider:.createNew)httpClient.execute(.GET,     socketPath:"/tmp/myServer.socket",     urlPath:"/path/to/resource").whenComplete(...)

Connecting over TLS to a unix domain socket path is possible as well:

lethttpClient=HTTPClient(eventLoopGroupProvider:.createNew)httpClient.execute(.POST,     secureSocketPath:"/tmp/myServer.socket",     urlPath:"/path/to/resource",     body:.string("hello")).whenComplete(...)

Direct URLs can easily be constructed to be executed in other scenarios:

letsocketPathBasedURL=URL(    httpURLWithSocketPath:"/tmp/myServer.socket",     uri:"/path/to/resource")letsecureSocketPathBasedURL=URL(    httpsURLWithSocketPath:"/tmp/myServer.socket",     uri:"/path/to/resource")

Disabling HTTP/2

The exclusive use of HTTP/1 is possible by settinghttpVersion to.http1Only onHTTPClient.Configuration:

varconfiguration=HTTPClient.Configuration()configuration.httpVersion=.http1Onlyletclient=HTTPClient(    eventLoopGroupProvider:.createNew,    configuration: configuration)

Security

Please have a look atSECURITY.md for AsyncHTTPClient's security process.


[8]ページ先頭

©2009-2025 Movatter.jp