flysystem-aws-s3-v3 icon indicating copy to clipboard operation
flysystem-aws-s3-v3 copied to clipboard

Issues when specifying a 'root' path

Open bennettblack opened this issue 2 years ago • 13 comments

  • Laravel Version: 9.8
  • PHP Version: 8.1.3
  • flysystem-aws-s3-v3 Version: 3.0.13

Description:

I'm encountering this issue with Laravel, but their team directed me here. See Issue.

I'm using Digital Ocean Spaces to host website assets. If I specify a 'root' path in filesystems.php for any DO disk, I run into issues retrieving the files. If I remove the 'root' key and write the folder path manually, I don't have any issues. Specifically, it looks like the end path character "/" is being converted to "%5C". Note, I only encountered this issue after upgrading from L8 to L9.

Here's how I'm generating the URL in my Blade:

<img src="{{ Storage::disk('vendor-logos')->url($vendor->image) }}" alt="{{ $vendor->name }}">

Here's the HTML that produces: <img src="https://bwi.nyc3.digitaloceanspaces.com/vendor-logos%5Cb574d580c91d97b6b12155708ecc61a3c0779750" alt="BASF">

Note how the src path above is missing a / , right after the root location 'vendor-logos'. Any file I display like this gets prepended with a %5C. I could be going in the wrong direction, but a quick Google search shows that 5c is the hex ASCII representation of "backslash".

Disk:

'vendor-logos' => [
    'driver'        => 's3',
    'key'           => env('DIGITALOCEAN_SPACES_KEY'),
    'secret'        => env('DIGITALOCEAN_SPACES_SECRET'),
    'endpoint'      => 'https://nyc3.digitaloceanspaces.com',
    'region'        => 'nyc',
    'bucket'        => 'bwi',
    'root'          => 'vendor-logos',
    'visibility'    => 'public',
],

Here's a snippet of my vendor model's underlying table. The highlighted record is the one used in my example above. image

Steps To Reproduce:

  1. Setup a disk in L9 that uses digital ocean spaces.
  2. Define a 'root' key in the filesystem config for that disk
  3. Make sure the asset in your digital ocean space is in the folder that corresponds to the 'root' path you specified in filesystems.php
  4. Try to display the asset in a blade.

bennettblack avatar Apr 14 '22 13:04 bennettblack

@bennettblack Hi, I don't believe this is a Flysystem issue. Flysystem does not expose the paths apart from listings which do not display this described behaviour.

frankdejonge avatar Apr 14 '22 14:04 frankdejonge

@frankdejonge Thank you for looking into my inquiry. @driesvints is this ok to re-open?

bennettblack avatar Apr 14 '22 15:04 bennettblack

@bennettblack in the meanwhile, have you tried debugging the call? See where the encoding actually happens?

frankdejonge avatar Apr 14 '22 15:04 frankdejonge

@frankdejonge Well, now that I have, It appears that it's happening in aws\aws-sdk-php\src\functions.php @ serialize() which utilizes some GuzzleHttp methods. Unfortunately there are some things going on there that are above my understanding. Doesn't seem to be Laravel or Flysystem though - sorry for the trouble.

bennettblack avatar Apr 14 '22 16:04 bennettblack

Isn't the issue that you're trying to use the S3 driver with digitalocean? Don't you need a special digitalocean driver?

driesvints avatar Apr 14 '22 16:04 driesvints

I don't think this is a Laravel issue. All we do is pass the root to the S3Adapter from Flysystem as the prefix. It then gets handled by flysystem as the adapter root.

driesvints avatar Apr 14 '22 17:04 driesvints

@driesvints the docs say its compatible with the s3 filesystem

bennettblack avatar Apr 14 '22 18:04 bennettblack

Hi, I have the same problem with Wasabi S3.

the backslash appears converted.

If you put the URL parameter and with the full endpoint it will work (or maybe it ignores it and just uses it).

It seems that the problem is when automatically generating the url.

See my Issue at laravel repo: https://github.com/laravel/framework/issues/42136

Thank you

victorelec14 avatar Apr 26 '22 12:04 victorelec14

Hi, same here but the problem occurs only on Windows platform. Same project on Ubuntu works fine.

2acode avatar Jun 23 '22 12:06 2acode

Same problem here. RHEL8 and latest macos

If config has 'root' => '/' its eats first letter of path

more related to laravel here

andaril avatar Jul 02 '22 22:07 andaril

Adding in - I'm having same issue on Windows.

If I remove the root key then no issues. Otherwise the root gets a \ between root specified and file. That then gets encoded to %5C the HTML URL Encoding.

For what it's worth I traced it deeper.

Entry into the Flysystem package happens on the url method for me AwsS3V3Adapter.php class

The method checks if there is a url key in the config property, doesn't find it and then hits a getObjectUrl Method. In that there's a prefixpath method being called for the second parameter:

image

And that class(PathPrefixer.php) has a prefix private string that I think the file system over wrote to be '' on windows: image

And then with Xdebug I can show that the prefix rendered with the expectred / as a \ but suspect that's a windows file system thing image

JonathanAspeling avatar Aug 04 '22 18:08 JonathanAspeling

@frankdejonge I have another issue related to "Extra slash" when i'm trying to get list of files with prefix that is not ending with '/' but is part of files naming i got empty list of files because of prefixer adding slash at the end of prefix $feedList = $storage->listContents($this->feedLocation . $this->feedNamePrefix);

Why it is trying to trim and write back this slash at all ?! my path is looks like "media/group/fileprefix_" and for example it should return files like "media/group/fileprefix_20220618.csv" in native AWS SDK it work this way

image

leonidd-hyuna avatar Aug 22 '22 16:08 leonidd-hyuna

This happen on Windows system. Add the 'directory_separator' to your s3 block inside the filesystems config.

s3' => [
           'driver' => 's3',
           'key' => env('AWS_ACCESS_KEY_ID'),
           'secret' => env('AWS_SECRET_ACCESS_KEY'),
           'region' => env('AWS_DEFAULT_REGION'),
           'bucket' => env('AWS_BUCKET'),
           'url' => env('AWS_URL'),
           'endpoint' => env('AWS_ENDPOINT'),
           'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false),
           'throw' => false,
           'root' => "your_root_path"
           'directory_separator' => '/'
       ],

This solves the same problem on my side: PHP: 8.1.9 Laravel: 9.31.0 flysytem-aws-s3-v3: 3.5.0

laurentmeuwly avatar Sep 26 '22 14:09 laurentmeuwly

Got this issue as well, when setting a s3 disk with a root "/", I cannot get the content of a file.

The URL used by curl is then completely wrong:

image

image

image

When removing the root "/" it seems to work.

incoming-th avatar Nov 15 '22 17:11 incoming-th

This happen on Windows system. Add the 'directory_separator' to your s3 block inside the filesystems config.

s3' => [
           'driver' => 's3',
           'key' => env('AWS_ACCESS_KEY_ID'),
           'secret' => env('AWS_SECRET_ACCESS_KEY'),
           'region' => env('AWS_DEFAULT_REGION'),
           'bucket' => env('AWS_BUCKET'),
           'url' => env('AWS_URL'),
           'endpoint' => env('AWS_ENDPOINT'),
           'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false),
           'throw' => false,
           'root' => "your_root_path"
           'directory_separator' => '/'
       ],

This solves the same problem on my side: PHP: 8.1.9 Laravel: 9.31.0 flysytem-aws-s3-v3: 3.5.0

Likewise. I believe this is the solution.

bennettblack avatar Nov 29 '22 20:11 bennettblack