How to set public read using go-cloud s3blob?

Viewed 304
3 Answers

It looks like the library expects anything inconsistent between providers to be provided as BeforeWrite callbacks:

opts := &blob.WriterOptions{}
opts.BeforeWrite(func(i interface{}) bool {
    p, ok := i.(*s3manager.UploadInput)
    if !ok {
        return false
    }
    p.ACL = aws.String("public-read")
    return true
})

w, err := b.NewWriter(ctx, "feeds/index.html", opts)

Warning: I totally didn't test this code, but it fmt'd, so it should work?

I will warn you, it seems this library is in alpha, for these types of reasons. Relying on this kind of work around is going to cause you issues trying to reuse it for all cloud providers. Ultimately, I suggest just implementing the functionality you'd like using the provided SDKs, and leveraging the Factory/Adapter pattern to retrieve the right adapter for a given call.

Setting the ACL at the bucket/container level is probably the right thing to do. Setting per-blob ACLs may be difficult to manage effectively. It is possible on some blob storage providers (AWS S3, GCS) but not others (Azure), so Go Cloud hasn't added support for it. Additionally, all 3 providers (and Go Cloud) support "signed URL" functionality, where you as an owner of the resource can create a URL that provides public read access to it for a limited period of time.

anything inconsistent between providers to be provided as BeforeWrite as @syntaqx said.

b, err := s3blob.OpenBucket(ctx, bucket, s, nil)
    if err != nil {
        return
    }
    before := func(asFunc func(interface{}) bool) error {
        req := &s3manager.UploadInput{}
        ok := asFunc(&req)
        if !ok {
            return errors.New("invalid s3 type")
        }
        req.ACL = aws.String(acl)
        return nil
    }
    w, err := b.NewWriter(ctx, appendTime(fileName), &blob.WriterOptions{
        ContentType: forceContentTypeByExtension(fileName),
        BeforeWrite: before,
    })
Related