Soto icon

Soto

AWS Service Objects

In Soto each AWS Service has a service object. This object brings together an AWSClient and a service configuration, AWSServiceConfig, and provides methods for accessing all the operations available from that service.

The init for each service is as follows. Again details about each parameter are available below.

public init(
    client: AWSClient,
    region: SotoCore.Region? = nil,
    partition: AWSPartition = .aws,
    endpoint: String? = nil,
    timeout: TimeAmount? = nil,
    byteBufferAllocator: ByteBufferAllocator = ByteBufferAllocator(),
    options: AWSServiceConfig.Options = []
)

Client

The client is the AWSClient this service object will use when communicating with AWS.

Region and Partition

The region defines which AWS region you want to use for that service. The partition defines which set of AWS server regions you want to work with. Partitions include the standard .aws, US government .awsusgov and China .awscn. If you provide a region, the partition parameter is ignored. If you don't supply a region then the region will be set as the default region for the specified partition, if that is not defined it will check the AWS_DEFAULT_REGION environment variable or default to us-east-1.

Some services do not have a region parameter in their initializer, such as IAM. These services require you to communicate with one global region which is defined by the service. You can still control which partition you connect to though.

Endpoint

If you want to communicate with non-AWS servers you can provide an endpoint which replaces the amazonaws.com web address. You may want to do this if you are using a AWS mocking service for debugging purposes for example, or you are communicating with a non-AWS service that replicates AWS functionality.

Time out

Time out defines how long the HTTP client will wait until it cancels a request. This value defaults to 20 seconds. If you are planning on downloading/uploading large objects you should probably increase this value. AsyncHTTPClient allows you to set an additional connection timeout value. If you are extending your general timeout, use an HTTPClient configured with a shorter connection timeout to avoid waiting for long periods when a connection fails.

ByteBufferAllocator

During request processing the AWSClient will most likely be required to allocate space for ByteBuffers. You can define how these are allocated with the byteBufferAllocator parameter.

Options

A series of flags, that can affect how requests are constructed. The only option available at the moment is s3ForceVirtualHost. S3 uses virtual host addressing by default except if you use a custom endpoint. s3ForceVirtualHost will force virtual host addressing even when you specify a custom endpoint.

AWSService

All service objects conform to the AWSService protocol. This protocol brings along a couple of extra bits of functionality

Presigned URLs

When a request is made to AWS it has to be signed. This uses your AWS credentials and the contents of the request to create a signature. When the request is sent to the AWS server, the server also creates a version of this signature. If these two signatures match then AWS knows who is making the request and that it can be trusted. If you want to allow your clients to access AWS resources, creating a presigned request to send to your client is a common way to do this. Alternatively you would have to send AWS credentials to the client and these could be abused.

One of the most common operations where this is used is for uploading an object to S3. Below creates a presigned URL which someone could use to upload a file to S3.

let signedURL = try await s3.signURL(
    url: URL(string: "https://<bucketname>.s3.us-east-1.amazonaws.com/<key>")!,
    httpMethod: .PUT,
    expires: .minutes(60)
)

The function signURL is async as it is dependent on a credential provider that may not have been resolved yet.

Creating new service objects from existing

It is possible to create a new version of a service object from an already existing one with additional AWSServiceMiddleware, an edited timeOut, byteBufferAllocator or options using the AWSService.with(middlewares:timeout:byteBufferAllocator:options) function.

If you are loading a much larger object then usual into S3 and want to extend the timeout value for this one operation you can do it as follows.

try await s3.with(timeout: .minutes(10)).putObject(request)