Search code examples
macosamazon-s3soto

Can't get soto to talk to non-AWS service


I've successfully implemented an Amazon Web Service S3 storage app using the Swift soto package.

I create the S3 service object like this:

func s3Maker() -> S3
{
    return S3(client: client, region: Region(rawValue: awsConfiguration.region), endpoint: awsConfiguration.endpoint, timeout: commandTimeout)
}

When using AWS, the awsConfiguration.region is one of AWS's standard region names (in this case, "us-west-2") and .endpoint is nil (which tells soto use the standard "amazonaws.com" domain).

Everything works great.

I now want to reuse this code to communicate with non-AWS providers (starting with BackBlaze) that emulates the AWS S3 API. My understanding is that you simply change the endpoint and region during the service object creation.

I have a subclass of the awsConfiguration object that simply has different region ("us-west-000") and endpoint ("backblazeb2.com") property values, but it doesn't work.

When the code runs it fails get the list of objects in the bucket, returning the error: "unable to read bucket contents"

In an attempt to debug this, I ran Fiddler Everywhere to monitor the HTTP requests being sent from my machine. When I run the AWS version, I see two HTTPS requests: http://qr3dev1.s3.us-west-2.amazonaws.com:443 and https://qr3dev1.s3.us-west-2.amazonaws.com/?list-type=2, both of which are successful.

But when I change the region and endpoints to BackBlaze, the code does nothing. Soto never sends any HTTP requests. The code just returns the error.

Has anyone every run into this, know how to debug it, or know the secret of getting soto to talk to a non-AWS service?


Solution

  • It turns out the "problem" was simply an impedance mismatch between my brain, the soto documentation, and the code.

    Shout out to Adam Fowler (one of the soto authors) who graciously helped me out with some sample code illustrating the correct use of endpoint.

    The endpoint property must be an URL fragment, not just the domain name of the service (which was my assumption):

    func s3Maker() -> S3
    {
        return S3(client: client,
                  region: Region(rawValue: "us-region-1"),
                endpoint: "https://s3.us-region-1.non-aws-server.com") // <-- CORRECT
    //          endpoint: "non-aws-server.com" ) <--- wrong
    }