SwiftyRequest
SwiftyRequest
is an HTTP client built for Swift.
The latest release of SwiftyRequest is built upon the Swift-NIO based async-http-client
.
Contents
Features
- Several response methods (e.g. Data, Object, Array, String, etc.) to eliminate boilerplate code in your application.
- Direct retrieval of
Codable
types.
- JSON encoding and decoding.
- Integration with the CircuitBreaker library.
- Authentication tokens.
- Client Certificate support (2-way SSL).
- Multipart form data.
Swift version
The latest version of SwiftyRequest requires Swift 5 or later.
Swift 4 support is available in the 2.x release of SwiftyRequest.
Installation
To leverage the SwiftyRequest
package in your Swift application, you should specify a dependency for it in your Package.swift
file:
Add dependencies
Add SwiftyRequest
to the dependencies within your application’s Package.swift
file. Substitute "x.x.x"
with the latest SwiftyRequest
release.
.package(url: "https://github.com/Kitura/SwiftyRequest.git", from: "x.x.x")
Add SwiftyRequest
to your target’s dependencies:
.target(name: "example", dependencies: ["SwiftyRequest"]),
Usage
Make Requests
To make outbound HTTP calls using SwiftyRequest
, create a RestRequest
instance. The method
parameter is optional (it defaults to .get
), the url
parameter is required.
Example usage of RestRequest
:
import SwiftyRequest
let request = RestRequest(method: .get, url: "http://myApiCall/hello")
request.credentials = .basicAuthentication(username: "John", password: "12345")
You can customize the following parameters in the HTTP request:
headerParameters
: The HTTP header fields which form the header section of the request message.
credentials
: The HTTP authentication credentials for the request.
acceptType
: The HTTP Accept
header, defaults to application/json
.
messageBody
: The HTTP message body of the request.
productInfo
: The HTTP User-Agent
header.
circuitParameters
: A CircuitParameters
object which includes a reference to a fallback function that will be invoked when the circuit is failing fast (see CircuitBreaker Integration).
contentType
: The HTTP Content-Type header
, defaults to application/json
.
method
: The HTTP method specified in the request, defaults to .GET
.
queryItems
: Any query parameters to be appended to the URL.
Invoke Response
The result
object we get back is of type Result<RestResponse<String>, Error>
so we can perform a switch to determine if the network call was successful:
request.responseString { result in
switch result {
case .success(let response):
print("Success")
case .failure(let error):
print("Failure")
}
}
Invoke Response with Template Parameters
URLs can be templated with the {keyName}
syntax, allowing a single RestRequest
instance to be reused with different parameters.
In this example, we invoke a response method with two template parameters to be used to replace the {state}
and {city}
values in the URL:
let request = RestRequest(url: "http://api.weather.com/api/123456/conditions/q/{state}/{city}.json")
request.responseData(templateParams: ["state": "TX", "city": "Austin"]) { result in
// Handle response
}
Invoke Response with Query Parameters
In this example, we invoke a response method with a query parameter to be appended onto the url
behind the scenes so that the RestRequest
gets executed with the following url: http://api.weather.com/api/123456/conditions/q/CA/San_Francisco.json?hour=9
. Any query items already specified in the request URL will be replaced:
let request = RestRequest(url: "http://api.weather.com/api/123456/conditions/q/CA/San_Francisco.json")
request.responseData(queryItems: [URLQueryItem(name: "hour", value: "9")]) { result in
// Handle response
}
CircuitBreaker Integration
SwiftyRequest
has built-in functionality for leveraging the CircuitBreaker library to increase your application’s stability. To make use of this functionality, assign a CircuitParameters
object to the circuitParameters
property. This object will include a reference to a fallback function that will be invoked when the circuit is failing fast.
Fallback
Here is an example of a fallback closure:
let breakerFallback = { (error: BreakerError, msg: String) in
print("Fallback closure invoked... circuit must be open.")
}
CircuitParameters
We initialize the CircuitParameters
object and create a RestRequest
instance. The only required value you need to set for CircuitParameters
is the fallback
(everything else has default values).
let circuitParameters = CircuitParameters(timeout: 2000,
maxFailures: 2,
fallback: breakerFallback)
let request = RestRequest(method: .GET, url: "http://myApiCall/hello")
request.circuitParameters = circuitParameters
At this point, you can use any of the response methods mentioned in the section below.
Response Methods
RestRequest
provides a number of response
functions that call back with a Result
containing either a response or an error.
To invoke the request and receive a response, you can use the response
function. The completion handler will be called back with a result of type Result<HTTPClient.Response, Error>
.
RestRequest provides additional convenience methods you can use based on the type of the response body you expect:
responseData
requires that the response contains a body, and calls back with a Result<RestResponse<Data>, Error>
.
responseObject<T: Decodable>
decodes the response body to the specified type, and calls back with a Result<RestResponse<T>, Error>
.
responseString
decodes the response body to a String, and calls back with a Result<RestResponse<String>, Error>
.
responseDictionary
decodes the response body as JSON, and calls back with a Result<RestResponse<[String: Any]>, Error>
.
responseArray
decodes the response body as a a JSON array, and calls back with a Result<RestResponse<[Any]>, Error>
.
responseVoid
does not expect a response body, and calls back with a Result<HTTPClient.Response, Error>
.
Example of handling a response
let request = RestRequest(method: .get, url: "http://localhost:8080/users/{userid}")
request.responseObject(templateParams: ["userid": "1"]) { (result: Result<RestResponse<User>, RestError>) in
switch result {
case .success(let response):
let user = response.body
print("Successfully retrieved user \(user.name)")
case .failure(let error):
if let response = error.response {
print("Request failed with status: \(response.status)")
}
if let responseData = error.responseData {
// Handle error response body
}
}
}
Migration from v2 to v3
There are a number of changes to the API in SwiftyRequest v3 compared to the v2 release:
- The
RestRequest
initializer parameter containsSelfSignedCert
has been renamed insecure
to better reflect its purpose (turning off SSL certificate verification). The old name has been deprecated and may be removed in a future release.
- The
completionHandler
callback of responseData
(et al) has changed from (RestResponse<Data>) -> Void
to (Result<RestResponse<Data>, RestError>) -> Void
.
- The
JSONDecodable
and JSONEncodable
types have been removed in favour of using Codable
directly. The responseObject
function allows you to receive a Codable object in a response.
- Convenience functions for handling raw JSON have been added.
responseDictionary
and responseArray
alow retrieval of JSON as [String: Any]
and [Any]
respectively, and sending of raw JSON can be performed by setting the request.messageBodyDictionary
or request.messageBodyArray
properties.
- the
RestError
type is now returned explicitly in the .failure
case. If the error pertains to a response with a non-success status code, you can access the response with error.response
. If the response also contained body data, it can be retrieved via error.responseData
.
Client Certificate support (2-way SSL)
Specify a ClientCertificate
when creating a RestRequest
to enable a client certificate to be presented upon a secure request (2-way SSL).
The certificate may be provided in PEM format - either from a file, a string or Data, and an optional passphrase. The PEM data should contain the certificate and its corresponding private key. If the private key is encrypted, the corresponding passphrase should be specified when constructing the ClientCertificate.
If you need to handle certificates in other formats, you may create a ClientCertificate directly from a NIOSSLCertificate
and NIOSSLPrivateKey
. For more information on these types, see the documentation for the async-http-client
project.
API documentation
For more information visit our API reference.
We love to talk server-side Swift, and Kitura. Join our Slack to meet the team!
License
This library is licensed under Apache 2.0. Full license text is available in LICENSE.
SwiftyRequest
SwiftyRequest
is an HTTP client built for Swift.The latest release of SwiftyRequest is built upon the Swift-NIO based
async-http-client
.Contents
Features
Codable
types.Swift version
The latest version of SwiftyRequest requires Swift 5 or later.
Swift 4 support is available in the 2.x release of SwiftyRequest.
Installation
To leverage the
SwiftyRequest
package in your Swift application, you should specify a dependency for it in yourPackage.swift
file:Add dependencies
Add
SwiftyRequest
to the dependencies within your application’sPackage.swift
file. Substitute"x.x.x"
with the latestSwiftyRequest
release.Add
SwiftyRequest
to your target’s dependencies:Usage
Make Requests
To make outbound HTTP calls using
SwiftyRequest
, create aRestRequest
instance. Themethod
parameter is optional (it defaults to.get
), theurl
parameter is required.Example usage of
RestRequest
:You can customize the following parameters in the HTTP request:
headerParameters
: The HTTP header fields which form the header section of the request message.credentials
: The HTTP authentication credentials for the request.acceptType
: The HTTPAccept
header, defaults toapplication/json
.messageBody
: The HTTP message body of the request.productInfo
: The HTTPUser-Agent
header.circuitParameters
: ACircuitParameters
object which includes a reference to a fallback function that will be invoked when the circuit is failing fast (see CircuitBreaker Integration).contentType
: The HTTPContent-Type header
, defaults toapplication/json
.method
: The HTTP method specified in the request, defaults to.GET
.queryItems
: Any query parameters to be appended to the URL.Invoke Response
The
result
object we get back is of typeResult<RestResponse<String>, Error>
so we can perform a switch to determine if the network call was successful:Invoke Response with Template Parameters
URLs can be templated with the
{keyName}
syntax, allowing a singleRestRequest
instance to be reused with different parameters.In this example, we invoke a response method with two template parameters to be used to replace the
{state}
and{city}
values in the URL:Invoke Response with Query Parameters
In this example, we invoke a response method with a query parameter to be appended onto the
url
behind the scenes so that theRestRequest
gets executed with the following url:http://api.weather.com/api/123456/conditions/q/CA/San_Francisco.json?hour=9
. Any query items already specified in the request URL will be replaced:CircuitBreaker Integration
SwiftyRequest
has built-in functionality for leveraging the CircuitBreaker library to increase your application’s stability. To make use of this functionality, assign aCircuitParameters
object to thecircuitParameters
property. This object will include a reference to a fallback function that will be invoked when the circuit is failing fast.Fallback
Here is an example of a fallback closure:
CircuitParameters
We initialize the
CircuitParameters
object and create aRestRequest
instance. The only required value you need to set forCircuitParameters
is thefallback
(everything else has default values).At this point, you can use any of the response methods mentioned in the section below.
Response Methods
RestRequest
provides a number ofresponse
functions that call back with aResult
containing either a response or an error.To invoke the request and receive a response, you can use the
response
function. The completion handler will be called back with a result of typeResult<HTTPClient.Response, Error>
.RestRequest provides additional convenience methods you can use based on the type of the response body you expect:
responseData
requires that the response contains a body, and calls back with aResult<RestResponse<Data>, Error>
.responseObject<T: Decodable>
decodes the response body to the specified type, and calls back with aResult<RestResponse<T>, Error>
.responseString
decodes the response body to a String, and calls back with aResult<RestResponse<String>, Error>
.responseDictionary
decodes the response body as JSON, and calls back with aResult<RestResponse<[String: Any]>, Error>
.responseArray
decodes the response body as a a JSON array, and calls back with aResult<RestResponse<[Any]>, Error>
.responseVoid
does not expect a response body, and calls back with aResult<HTTPClient.Response, Error>
.Example of handling a response
Migration from v2 to v3
There are a number of changes to the API in SwiftyRequest v3 compared to the v2 release:
RestRequest
initializer parametercontainsSelfSignedCert
has been renamedinsecure
to better reflect its purpose (turning off SSL certificate verification). The old name has been deprecated and may be removed in a future release.completionHandler
callback ofresponseData
(et al) has changed from(RestResponse<Data>) -> Void
to(Result<RestResponse<Data>, RestError>) -> Void
.JSONDecodable
andJSONEncodable
types have been removed in favour of usingCodable
directly. TheresponseObject
function allows you to receive a Codable object in a response.responseDictionary
andresponseArray
alow retrieval of JSON as[String: Any]
and[Any]
respectively, and sending of raw JSON can be performed by setting therequest.messageBodyDictionary
orrequest.messageBodyArray
properties.RestError
type is now returned explicitly in the.failure
case. If the error pertains to a response with a non-success status code, you can access the response witherror.response
. If the response also contained body data, it can be retrieved viaerror.responseData
.Client Certificate support (2-way SSL)
Specify a
ClientCertificate
when creating aRestRequest
to enable a client certificate to be presented upon a secure request (2-way SSL).The certificate may be provided in PEM format - either from a file, a string or Data, and an optional passphrase. The PEM data should contain the certificate and its corresponding private key. If the private key is encrypted, the corresponding passphrase should be specified when constructing the ClientCertificate.
If you need to handle certificates in other formats, you may create a ClientCertificate directly from a
NIOSSLCertificate
andNIOSSLPrivateKey
. For more information on these types, see the documentation for theasync-http-client
project.API documentation
For more information visit our API reference.
Community
We love to talk server-side Swift, and Kitura. Join our Slack to meet the team!
License
This library is licensed under Apache 2.0. Full license text is available in LICENSE.