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

[Ghost Admin] Defining [cdnURL] triggers relative path construction for user-image.png specific to Ghost(Pro) that breaks on other hosting setups #21838

Closed
1 task done
alexgmathews opened this issue Dec 9, 2024 · 5 comments
Labels
needs:info [triage] Blocked on missing information

Comments

@alexgmathews
Copy link

alexgmathews commented Dec 9, 2024

Issue Summary

Ghost Admin does not render the correct URL for the user avatar when cdnURL is defined.

Steps to Reproduce

  1. Spin up a new stand-alone instance of Ghost

  2. Observe that without defining cdnURL, the user avatar HTML renders as:

    <div class="gh-user-avatar relative" style="background-image: url(/ghost/assets/img/user-image-639a88b784fb5f10964be8b975ca9fdf.png);">
    
  3. Modify the HTML-encoded EmberJS data inside <meta name="ghost-admin/config/environment"> so that "cdnUrl": "https://testdomain.com/ghost/", the same path that Ghost would serve admin assets from if the path were undefined. I do so by post-processing the HTML for /ghost/ using NGINX subs_filter. I see Ghost(Pro) uses the path https://assets.ghost.io/admin/1234/

  4. Observe that after defining cdnURL, the user avatar HTML renders as:

     <div class="gh-user-avatar relative" style="background-image: url(/img/user-image-639a88b784fb5f10964be8b975ca9fdf.png);">
    
  5. I think the user avatar HTML should render as... (This is the behavior of other dynamically-generated URLs in Ghost's admin):

     <div class="gh-user-avatar relative" style="background-image: url(https://testdomain.com/ghost/assets/img/user-image-639a88b784fb5f10964be8b975ca9fdf.png);">
    

Ghost Version

5.103.0

Node.js Version

18.20.5

How did you install Ghost?

Docker ghost:5-alpine

Database type

MySQL 8

Relevant log / error output

screenshot

Code of Conduct

  • I agree to be friendly and polite to people in this repository
@github-actions github-actions bot added the needs:triage [triage] this needs to be triaged by the Ghost team label Dec 9, 2024
@alexgmathews alexgmathews changed the title [Ghost Admin] User-Profile Avatar URL Renders Incorrectly When [cdnURL] Defined [Ghost Admin] User Avatar URL Renders Incorrectly When [cdnURL] Defined Dec 9, 2024
@ErisDS
Copy link
Member

ErisDS commented Dec 17, 2024

Hi @alexgmathews, can you explain what your use-case is for using cdnURL? Also how/where are you setting it?

This is a build time only variable used for loading the admin app from a different location to the main app. It's not documented anywhere that I know of and is working perfectly for its intended use.

I think it's more likely a case of mistaken identity, but if you can explain what you're using it for and how we can probably help.

@ErisDS ErisDS added the needs:info [triage] Blocked on missing information label Dec 17, 2024
@github-actions github-actions bot removed the needs:triage [triage] this needs to be triaged by the Ghost team label Dec 17, 2024
Copy link
Contributor

Note from our bot: The needs:info label has been added to this issue. Updating your original issue with more details is great, but won't notify us, so please make sure you leave a comment so that we can see when you've updated us.

@alexgmathews
Copy link
Author

alexgmathews commented Jan 9, 2025

Thank you, @ErisDS, for your clarifying questions.


First, here's the relevant source code:

When you compare the code for all three, here's the odd thing thing about user-image.png: Each uses cdnURL as a switch operator, but user-image.png doesn't include cdnURL in its URL construction.


I'm extending Ghost's intended functionality and serving static assets (both front-end and admin) from a cdn. subdomain. I'm not modifying Ghost core or themes to do so. Rather, I'm using an NGINX module to search and replace on Ghost's HTML/XML output. I figured out how to rewrite URLs for all static assets [*1] except user-image.png (IMAGE URL).

As you said, I'm not aware of IMAGE URL rendering incorrectly for its intended use cases. The issue I ran into (by hacking my way into it) is that when cdnURL is defined, IMAGE URL renders as a relative path. IMAGE URL's relative path works for Ghost(Pro), but since my hosting setup is different, the relative path breaks on me. (The relative path construction disregards the cdn. subdomain and omits /ghost/assets/.)


First, I found what strings to rewrite in the rendered HTML/XML to get Ghost's admin to load static assets over a cdn. subdomain.

This is as far as I could get on the admin dashboard before defining cdnURL. The four URLs I couldn't figure out how to rewrite were IMAGE URL, admin-x-settings.js and koenig-lexical.umd.js (OTHER URLS), and ghost-dark.css [*1].

c

Eventually I figured out that I couldn't rewrite these paths because they were being called from client-side javascript:

e

I looked through a Ghost(Pro) website and noticed cdnURL was defined inside the URL-encoded content of <meta name="ghost-admin/config/environment" content="...">. I found that if I defined cdnURL as cdn.domain.com, OTHER URLS would load directly from the cdn. subdomain. I also noticed that defining cdnURL changed the construction of IMAGE URL, even though to an invalid path.

Also how/where are you setting [cdnURL]?

Here's an abstract of the NGINX configuration I'm using to define cdnURL:

location = /ghost/ {
    subs_filter '%22cdnUrl%22%3A%22%22%2C' '%22cdnUrl%22%3A%22https%3A%2F%2F$map_ghost_cdn_domain%2Fghost%2F%22%2C' o;
    ...
}

subs_filter finds the URL-encoded string "cdnUrl":"", in the HTML output of /ghost/ and replaces it with the URL-encoded string "cdnUrl":"https://cdn.domain.com/ghost/",.

Here are how IMAGE URL, OTHER URLs, and ghost-dark.css [*1] load after defining cdnURL as cdn.domain.com:

f

Resulting generated HTML:

 <div class="gh-user-avatar relative" style="background-image: url(/img/user-image-639a88b784fb5f10964be8b975ca9fdf.png);">

The reason I think this is a bug matter of design inconsistency is because when cdnURL is defined, ghost.js constructs OTHER URLS using absolute paths. I assumed the same design intent would apply for user-image.png, though the relative class in the above HTML implies there's more going on with this particular URL than I understand.

[*1]: ghost-dark.css, which is also called by ghost.js, seems to ignore when cdnURL is defined and still loads from the base-domain path. I'm ignoring that in this issue report.


I created an isolated setup for this issue report with the below NGINX configuration. Instead of changing cdnURL to a cdn. subdomain, I set it to the same domain as the base URL. In theory, every asset would still have loaded at the same URL. As I showed, though, ghost.js constructed a relative path for user-image.png that 404-ed.

# Sample NGINX configuration for https://domain.com:
# requires the 3rd-party NGINX module https://github.com/yaoweibin/ngx_http_substitutions_filter_module

location / {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header Host $http_host;
    proxy_pass http://127.0.0.1:2368;
}

location = /ghost/ {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header Host $http_host;
    proxy_pass http://127.0.0.1:2368;
    subs_filter '%22cdnUrl%22%3A%22%22%2C' '%22cdnUrl%22%3A%22https%3A%2F%2Fdomain.com%2Fghost%2F%22%2C' o;
}

Copy link
Contributor

github-actions bot commented Jan 9, 2025

Hey @alexgmathews 👋

Our team needed some more info to get to the bottom of this, however we've not heard back from you. We're going to close this for now, but let us know if you manage to dig up some more info and we'll reopen.

@github-actions github-actions bot closed this as not planned Won't fix, can't repro, duplicate, stale Jan 9, 2025
@alexgmathews
Copy link
Author

@ErisDS - Apologies for my delayed response. It seems I was auto-bot-closed on for not having a timely response. Would you still consider?

@alexgmathews alexgmathews changed the title [Ghost Admin] User Avatar URL Renders Incorrectly When [cdnURL] Defined [Ghost Admin] UsWhen [cdnURL] Defined Jan 10, 2025
@alexgmathews alexgmathews changed the title [Ghost Admin] UsWhen [cdnURL] Defined [Ghost Admin] Defining [cdnURL] triggers relative path construction for user-image.png specific to Ghost(Pro) that breaks on other hosting setups Jan 10, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs:info [triage] Blocked on missing information
Projects
None yet
Development

No branches or pull requests

3 participants
@ErisDS @alexgmathews and others