Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Asset url encoding issues: spaces and accents #5593

Open
stuartcusackie opened this issue Mar 22, 2022 · 11 comments
Open

Asset url encoding issues: spaces and accents #5593

stuartcusackie opened this issue Mar 22, 2022 · 11 comments
Labels

Comments

@stuartcusackie
Copy link

stuartcusackie commented Mar 22, 2022

Bug description

I think there is a problem with the Statamic\Support\Str::isUrl() helper, more details below.

I was using a piece of code to generate glide images in a blade component, which I used for complex responsive images. This code was taken directly from the old blade directives package:

/**
   * Return glide data for an image at path.
   * Modified from Edalzell\Blade\Directives\Glide
   * 
   * @param $field mixed
   * @param $params array
   * @return object
   */
    protected function generateGlideImage(string $path, array $params = []) {

        $data = (new \Statamic\Tags\Glide)
            ->setParser(\Statamic\Facades\Antlers::parser())
            ->setContext([])
            ->setParameters($params)
            ->generate($path);

        return (object)$data[0];

    }

This piece of code no longer works in Statamic 3.3 and I am getting this error: "Call to a member function disk() on null"

I think I have found the problem in statamic\cms\src\Tags\Glide.php:

/**
   * Generate the image.
   *
   * @param  mixed  $item
   * @return string
   */
    private function generateImage($item)
    {
        $item = $this->normalizeItem($item);
        $params = $this->getGlideParams($item);

        if (is_string($item) && Str::isUrl($item)) {
            return Str::startsWith($item, ['http://', 'https://'])
                ? $this->getGenerator()->generateByUrl($item, $params)
                : $this->getGenerator()->generateByPath($item, $params);
        }

        return $this->getGenerator()->generateByAsset(Asset::find($item), $params);
    }

The Str::isUrl() helper is failing for my digital ocean asset container urls. Example:
https://ams3.digitaloceanspaces.com/mywebsite/images/subfolder/Image X - Whatever_17.jpg

When this check fails the Glide class then tries to generateByAsset(), which then throws the disk() on null error.
I have tried manually calling Statamic\Support\Str::isUrl() on the url above and it does in fact return false - this should not happen right?

If I remove the isUrl check from Glide.php then everything works fine.

How to reproduce

Try to generate glide images using urls through a class or function.

Or simply call \Statamic\Support\Str::isUrl('https://ams3.digitaloceanspaces.com/mywebsite/images/subfolder/Image X - Whatever_17.jpg')

The above will return false when it should return true.

Logs

No response

Versions

Statamic 3.3.2 Pro
Laravel 9.5.1
PHP 8.0.10
statamic/seo-pro 3.1.0

Installation

Existing Laravel app

Antlers Parser

No response

Additional details

No response

@jasonvarga
Copy link
Member

It's the spaces in the ImageX - Whatever_17.jpg part of the URL that's causing a problem.

https://ams3.digitaloceanspaces.com/mywebsite/images/subfolder/ImageX - Whatever_17.jpg does indeed come back as not a URL.

But if you get rid of the spaces https://ams3.digitaloceanspaces.com/mywebsite/images/subfolder/ImageX%20-%20Whatever_17.jpg it is considered a URL.

How are you getting the URL?

@stuartcusackie
Copy link
Author

stuartcusackie commented Mar 22, 2022

These spaces have been added to filenames by the client. The statamic asset url is returning this value ($asset_field->url).

Of course I cannot stop my clients from adding spaces to filenames. Either the helper function, or the statamic asset object handled the spaces correctly in v3.2 because this problem has only presented in 3.3.

@jasonvarga
Copy link
Member

Nah it should handle it automatically. I just wanted to confirm how you're getting the URL so we can address the right spot.

@jasonvarga
Copy link
Member

In the meantime you could do $url = str_replace(' ', '%20', $url);

@stuartcusackie
Copy link
Author

Cheers. Thought I was going crazy for there for a minute. I'll do a str_replace for now.

@jasonvarga jasonvarga changed the title Glide generate logic problem on 3.3 Spaces in asset urls should be encoded Mar 22, 2022
@stuartcusackie
Copy link
Author

stuartcusackie commented Mar 22, 2022

It seems it's not just spaces that are a problem. The accent in the filename below causes the same error.

https://ams3.digitaloceanspaces.com/myspace/images/myfolder/Dún%20Laoghaire_18%202.jpg

@stuartcusackie stuartcusackie changed the title Spaces in asset urls should be encoded Spaces in asset urls should be encoded, and other glide issues. Mar 30, 2022
@stuartcusackie stuartcusackie changed the title Spaces in asset urls should be encoded, and other glide issues. Asset url encoding issues: glide generation and caching Mar 30, 2022
@stuartcusackie stuartcusackie changed the title Asset url encoding issues: glide generation and caching Asset url encoding issues: spaces and accents Apr 11, 2022
@jasonvarga
Copy link
Member

If you open that image through the DO Spaces UI... what does the URL look like? What does it do with the ú?

@stuartcusackie
Copy link
Author

stuartcusackie commented Apr 11, 2022

@edalzell
Copy link
Contributor

I ended up making a custom modifier to fix this:

public function index($value, $params, $context)
    {
        $details = parse_url($value);

        return URL::assemble(
            'https://',
            $details['host'],
            implode('/', array_map('rawurlencode', explode('/', Arr::get($details, 'path'))))
        );
    }

@stuartcusackie
Copy link
Author

@edalzell That works for me alright. No more issues with spaces or accents.

Can we get this added to the 3.3 core?

@jasonvarga
Copy link
Member

I don't want to add the modifier to the core, I'd rather just have it output the correct URL to begin with.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants