HTTP Client
Introduction
Alchemy provides a lightweight, async
enabled, wrapper around the official Swift on the Server async-http-client
. You get a high performance, easy to use interface that makes it easy for your app to communicate with other web applications.
Making Requests
Out of the box, a default client is registered to your application’s service container and comes with a request builder, conveniently accessible through the Http
alias. You may use the get
, post
, put
, patch
, delete
, etc functions to make requests.
Each request returns a Client.Response
object that contains a variety of methods to help handle the response.
Like Request
, Client.Response
also conforms to ContentInspector
so you can use subscripts and dynamic typing to access various fields the response.
Request Content
The reqest builder conforms to RequestBuilder
and contains many methods for constructing requests. If you want to include some JSON content on your requests, you should use the .withJSON()
function which takes a dictionary.
You may also pass an Encodable
type, optionally speciying the JSONEncoder
with which to encode.
Queries
If you’d like to specify a url query on the request, you may specify it directly in the url or use either withQuery()
(for a single key / value pair) or withQueries()
(for multiple query items).
Making Form URL Encoded Requests
The .withForm()
method lets you send data using the application/x-www-form-urlencoded
content type. Like withJSON()
, it takes either a dictionary or an Encodable
type and an optional URLEncodedFormEncoder
.
Sending a Raw Request Body
Of course, you have full customization over the content of your request. If you’d prefer to send a raw request body, you can use the .withBody()
to send either Foundation.Data
or a swift-nio ByteBuffer
.
Multipart Requests
If you need to make a multipart/form-data
request, you’ll use the attach()
method. This takes a name, an attachment contents, and an optional filename.
You can also attach a streamed File
or multiple File
resources directly.
Headers
A header may be added to a request using the withHeader()
method. Multiple headers may be added using withHeaders()
.
Authentication
You may specify basic authentication credentials using withBasicAuth()
.
Bearer Token
If you’d like to quickly add a bearer token to the request, you may use the withToken()
method.
Timeout
You may specify a timeout for your request using withTimeout()
, after which your request will be terminated and an error will be thrown.
Response Streaming
By default, any Client.Response
will have it’s body accumulated into a single ByteBuffer
before returning, so that you don’t need to worry about streamed responses. If you would like to explicitly allow a streamed response, you may do so with the withStream()
function.
Custom Configurations
Under the hood, all you requests are made by the official Swift Server async-http-client
library. If you’d like finer grain customization over the internal client configuration, you may specify one using withClientConfig()
.
Testing
To help you write isolated, expressive tests, the Client
interface includes a stub()
method allowing you to respond to requests with mock responses.
Stubbing Responses
To return a 200
for all outgoing requests on a client, you may use the stub()
function.
Stubbing Specific URLs
If you’d like to provide custom stubbed responses for specific URLs, you may pass a dictionary of url patterns & responses to the stub()
method. If a request doesn’t match any of the provided patterns, it will result in a 200
response. *
is treated as a wildcard. The static stub()
function on Client.Response
lets you quickly create stubbed responses.
Stubbing With A Handler
If you’d prefer fine grain control over stubbing each request’s response, you may pass a closure to the stub function. With it, you can perform whatever logic you need to mock the given request. It take a single Client.Request
parameter and must return a Client.Response
.
Validating Requests
If you’d like to validate the requests your app is making during testing, you may use the assertSent()
function in the AlchemyTest
library. It takes an optional count of expected requests, as well as an optional closure for verifying the request contents. When verifying the request, you may use the RequestInspector
interface as well as the hasPath()
, hasHeader()
, hasPath()
, and hasMethod()
sugar functions.
If you’d like to assert that nothing was sent, use the assertNothingSent()
function.