soto-project / soto

Swift SDK for AWS that works on Linux, macOS and iOS
https://soto.codes
Apache License 2.0
868 stars 81 forks source link

[7.x.x] watchOS : POSIXErrorCode(rawValue: 50): Network is down #690

Closed RichardFevrier closed 9 months ago

RichardFevrier commented 10 months ago

Getting POSIXErrorCode(rawValue: 50): Network is down when trying to put an object to a bucket.

Steps to reproduce the behavior:

import SotoS3

let service = "s3"
let region: Region = .euwest3
let bucket = "XXXXXXXXXXXXX"
let filename = "file.txt"
let bodyData = "hello world"

let client = AWSClient(
                credentialProvider: .static(accessKeyId: "XXXXXXXX", secretAccessKey: "XXXXXXX"),
                httpClientProvider: .createNew
            )

defer {
    do {
        try client.syncShutdown()
    } catch {
        print(error)
    }
}

let s3 = S3(client: client, region: region)

let putObjectRequest = S3.PutObjectRequest(
    body: .init(string: bodyData),
    bucket: bucket,
    key: filename
)

do {
    let _ = try await s3.putObject(putObjectRequest)
} catch {
    print(error)
}

Expected behavior No error 😅

Alternative solution Fortunately you provide a way to handle the situation 🤩

delete:

let putObjectRequest...

replace:

let _ = try await s3.putObject(putObjectRequest)

with:

let url = try await s3.signURL(
    url: URL(string: "https://\(service).\(region.rawValue).amazonaws.com/\(bucket)/\(filename)")!,
    httpMethod: .PUT,
    expires: .minutes(60)
)

let request = NSMutableURLRequest(url: url)
request.addValue("Accept", forHTTPHeaderField: "application/json")
request.httpMethod = "PUT"
request.httpBody = bodyData.data(using: String.Encoding.utf8)
let task = URLSession.shared.dataTask(with: request as URLRequest) { _,_,_ in }
task.resume()

Setup

adam-fowler commented 10 months ago

Low level networking is not available on watchOS, so any SwiftNIO based networking will not work. I believe the URLSession.shared.dataTask should work though. You should verify this on an actual watch as the emulator can give different results. See https://github.com/apple/swift-nio/issues/2255#issuecomment-1248224069

I would have to implement a URLSession based HTTP client for Soto for it to work for you. It has been asked for before.

RichardFevrier commented 10 months ago

Watch my Alternative solution part, I talked about URLSession.shared.dataTask. Everything was tested on real device. 🙂