jeygeethan / activestorage-backblaze

Looking for co-committers. Pls reach out. Activestorage (rails 6) gem for using backblaze b2 as the storage (just like aws s3 etc)
26 stars 10 forks source link

Backblaze setup example to direct upload (CORS) #4

Open antoniosmgatto opened 3 years ago

antoniosmgatto commented 3 years ago

Hi There !!!

First of all, Thanks for this integration !

I'm facing some CORS trouble with B2 and I appreciate any help.

I can't setup my bucket to upload files from my frontend (React-app). I am using this gem with Active Storage to generate the direct upload url.

This is the command I use to setup the CORS rules:

b2 update-bucket --corsRules '[
    {
        "corsRuleName": "downloadFromAnyOriginWithUpload",
        "allowedOrigins": [
            "*"
        ],
        "allowedHeaders": [
            "*"
        ],
        "allowedOperations": [
            "b2_download_file_by_id",
            "b2_download_file_by_name",
            "b2_upload_file",
            "b2_upload_part"
        ],
        "exposeHeaders": [
            "authorization",
            "x-bz-file-name",
            "x-bz-part-number",
            "x-bz-content-sha1"
        ],
        "maxAgeSeconds": 3600
    }
]' my-bucket allPublic

Any idea?

Thanks

jeygeethan commented 3 years ago

Hey Can you let me know what is the error that you are getting on the frontend react app? Are you getting the upload url in the first place?

antoniosmgatto commented 3 years ago

Yes, I get the url from my backend.

console tab output

image

upload request

image

pre-flight request

image image

Any idea?

jeygeethan commented 3 years ago

Hi,

from the first screenshot, it looks like CORs is not enabled. I usually set the cors for the bucket in the UI.

Can you try to do that?

jeygeethan commented 3 years ago

Try this out - https://www.backblaze.com/blog/enable-cors-for-cross-origin-resource-sharing/#:~:text=Backblaze%20supports%20the%20standard%20CORS,of%20assets%20to%20other%20origins.

antoniosmgatto commented 3 years ago

Hi there !!

The cors is enabled. Here my settings:

[
  {
    "corsRuleName": "downloadFromAnyOriginWithUpload",
    "allowedOrigins": [
      "*"
    ],
    "allowedHeaders": [
      "*"
    ],
    "allowedOperations": [
      "b2_download_file_by_id",
      "b2_download_file_by_name",
      "b2_upload_file",
      "b2_upload_part"
    ],
    "exposeHeaders": [
      "authorization",
      "content-type",
      "content-length",
      "x-bz-file-name",
      "x-bz-part-number",
      "x-bz-content-sha1"
    ],
    "maxAgeSeconds": 3600
  }
]

I tried to upload a file with ruby and it worked. Have you ever used direct upload?.

EmCousin commented 3 years ago

Hi there,

I have been encountering the exact same issue, and after digging for a while I managed to perform a direct upload to B2 successfully, but via a POST HTTP request. Performing a PUT request, as ActiveStorage does by default however still fails with the same CORS method not allowed error message.

It appears BackBlaze does not enable PUT methods when using their B2 API. I have reached customer support and am waiting for them to answer.

EmCousin commented 3 years ago

Here is the answer from Backblaze Support:

After further observation, it looks like you're using the B2 API for PUT actions rather than the S3 API. Essentially, the B2 API accepts POST calls but not PUT calls while the S3 API accepts PUT calls but not POST calls. So in this case, the CORS rule wouldn't be the cause here.From here, please try using the S3 API to conduct the PUT call instead. Please let me know if you have any further questions or concerns.

If this gem is going to be an ActiveStorage adapter for Backblaze, it could try to use the S3 API instead

jeygeethan commented 3 years ago

HI @EmCousin, This gem was created before b2 had the s3 apis. There was no other gem to have it integrated with the activestorage.

Considering that they have the s3 apis, i am guessing you can use the aws-sdk gem itself and just changing the s3 endpoint to b2. I haven't done this, but just guessing. If you can help with the results it would be great.

EmCousin commented 3 years ago

Hey @jeygeethan, I actually did that yesterday and indeed using the aws-sdk gem works just fine. With Rails and Active Storage, the following configuration suffices:

backblaze:
  service: S3
  access_key_id: <KEY_ID>
  secret_access_key: <KEY_TOKEN>
  region: <REGION> # example: us-east-001
  bucket: <BUCKET_NAME>
  endpoint: https://s3.<REGION>.backblazeb2.com

Providing the endpoint is necessary as it otherwise defaults to AWS'

Still, good job on making a gem to wire BackBlaze with ActiveStorage using the B2 API. If only we could configure Active Storage direct upload requests' verb to be POST by default, direct upload would work like a charm.

jeygeethan commented 3 years ago

@EmCousin I will try my best to see if I can patch the direct uploads verb to POST. But I am curious, will you be using the b2 apis instead of the s3?

EmCousin commented 3 years ago

I will try my best to see if I can patch the direct uploads verb to POST

@jeygeethan Unfortunately you can't. The direct upload request's verb is hardcoded in Active Storage's JS module

The S3-compatible API suits my needs, but using the B2 APi would be much better to enjoy the full set of features Backblaze provides. But that is out of the scope of this issue

jeygeethan commented 3 years ago

@EmCousin I forgot to add more one thing in the readme.

I had actually extracted the activestorage-backblaze and actiontext-backblaze npm packages separately but forgot to put them on github. Here they are:

https://github.com/jeygeethan/actiontext-backblaze https://github.com/jeygeethan/activestorage-backblaze-javascript

If you see, it has been updated to POST at https://github.com/jeygeethan/activestorage-backblaze-javascript/blob/master/src/blob_upload.js#L9

Add this to your package.json

"@jeygeethan/actiontext-backblaze": "^6.1.3-alpha"

tbhockey commented 2 years ago

Hey @jeygeethan, I actually did that yesterday and indeed using the aws-sdk gem works just fine. With Rails and Active Storage, the following configuration suffices:

backblaze:
  service: S3
  access_key_id: <KEY_ID>
  secret_access_key: <KEY_TOKEN>
  region: <REGION> # example: us-east-001
  bucket: <BUCKET_NAME>
  endpoint: https://s3.<REGION>.backblazeb2.com

Providing the endpoint is necessary as it otherwise defaults to AWS'

Still, good job on making a gem to wire BackBlaze with ActiveStorage using the B2 API. If only we could configure Active Storage direct upload requests' verb to be POST by default, direct upload would work like a charm.

Broooo thank you so so much. Not sure why this reply doesn't have more love, but it deserves an award. This had been giving our whole team headaches for days.

jeygeethan commented 2 years ago

@tbhockey True, since this was created before backblaze support S3 apis, this gem was relevant back then. But now you can directly use the S3 endpoints and skip this gem. I should probably add this in the readme!

tbhockey commented 2 years ago

@jeygeethan that would probably be very helpful for others. tbh this gem was perfectly fine for us, it was just until trying to use this DirectUpload feature of Rails that we ran into this issue as the regular BB endpoints don't support it. But thankfully their S3 apis do and this works beautifully.

adenta commented 1 year ago

Dang, I'm using the @jeygeethan/activestorage-backblaze npm package, and backblaze is configured for Share everything in this bucket with every origin, and I still can't get CORS requests to pass. Do I need to RTFM or are there any other tricks I can try?