[GH-ISSUE #761] Image attachments from url won't get rendered in web ui #548

Closed
opened 2026-05-07 00:25:20 +02:00 by BreizhHardware · 4 comments

Originally created by @codebude on GitHub (Jun 1, 2023).
Original GitHub issue: https://github.com/binwiederhier/ntfy/issues/761

🐞 Describe the bug
Image/photo attachments from url are not loaded/previewed in web ui.

💻 Components impacted
web app

🔮 Additional context
Attachments, when send via the X-Attach header (=url) are not preview in the web ui. Same notification previews image on Android app. In Webbapp, just a file icon is shown.
In opposite, when the same file is send as local attachment, the image is shown in web ui (and in Android app).

Is this a bug or a feature?

Originally created by @codebude on GitHub (Jun 1, 2023). Original GitHub issue: https://github.com/binwiederhier/ntfy/issues/761 :lady_beetle: **Describe the bug** Image/photo attachments from url are not loaded/previewed in web ui. :computer: **Components impacted** web app :crystal_ball: **Additional context** Attachments, when send via the X-Attach header (=url) are not preview in the web ui. Same notification previews image on Android app. In Webbapp, just a file icon is shown. In opposite, when the same file is send as local attachment, the image is shown in web ui (and in Android app). Is this a bug or a feature?
BreizhHardware 2026-05-07 00:25:20 +02:00
  • closed this issue
  • added the
    🪲 bug
    label
Author
Owner

@binwiederhier commented on GitHub (Jun 1, 2023):

This is a browser restriction. 99% of hosts won't allow rendering a URL from a different host due to CORS restrictions, so we don't even attempt it.

So it is not a feature or a bug. Ha.

<!-- gh-comment-id:1572840622 --> @binwiederhier commented on GitHub (Jun 1, 2023): This is a browser restriction. 99% of hosts won't allow rendering a URL from a different host due to CORS restrictions, so we don't even attempt it. So it is not a feature or a bug. Ha.
Author
Owner

@codebude commented on GitHub (Jun 1, 2023):

But doesn't CORS mainly relate to AJAX requests? If you load the preview via AJAX I understand the problem, but images doesn't have to be loaded via AJAX.
For example, something as follow should work (and bypass any CORS problems):

  • Check content type of attachment
  • If content type != image type then render download link as is
  • Else (content type = image type) then add img-tag to DOM via JS and write image url to SRC Tag.

This should work, because the img-Tag doesn't care for CORS (at least that's my understanding/experience).

<!-- gh-comment-id:1572850936 --> @codebude commented on GitHub (Jun 1, 2023): But doesn't CORS mainly relate to AJAX requests? If you load the preview via AJAX I understand the problem, but images doesn't have to be loaded via AJAX. For example, something as follow should work (and bypass any CORS problems): - Check content type of attachment - If content type != image type then render download link as is - Else (content type = image type) then add img-tag to DOM via JS and write image url to SRC Tag. This should work, because the img-Tag doesn't care for CORS (at least that's my understanding/experience).
Author
Owner

@binwiederhier commented on GitHub (Jun 2, 2023):

@codebude I would have bet good money on the fact that what you are saying is incorrect. But it seems to be true. This just blew my mind. 🤯 🤯 🤯

For example, something as follow should work (and bypass any CORS problems)

As for your suggestion. This will likely not work like this because for attachments that are not uploaded to the ntfy server, I do not have the content type.

External attachments look like this:

  "attachment": {
    "name": "0fe05365-9e73-4d4d-a259-bb919e903502_w948_r1.778_fpx62.47_fpy50.webp",
    "url": "https://cdn.prod.www.spiegel.de/images/0fe05365-9e73-4d4d-a259-bb919e903502_w948_r1.778_fpx62.47_fpy50.webp"
  }

While uploaded ones look like this:

  "attachment": {
    "name": "attachment.png",
    "type": "image/png",
    "size": 82776,
    "expires": 1685680731,
    "url": "http://localhost:2586/file/h9t9UMB3SL4N.png"
  }

I don't want to have the server probe the URL, because there's a whole lot of security issues that come with that, so I'll have to figure something out in the browser. Let me see what I can do.

<!-- gh-comment-id:1573009058 --> @binwiederhier commented on GitHub (Jun 2, 2023): @codebude I would have bet good money on the fact that what you are saying is incorrect. But it seems to be true. This just blew my mind. :exploding_head: :exploding_head: :exploding_head: > For example, something as follow should work (and bypass any CORS problems) As for your suggestion. This will likely not work like this because for attachments that are not uploaded to the ntfy server, I do not have the content type. External attachments look like this: ```json "attachment": { "name": "0fe05365-9e73-4d4d-a259-bb919e903502_w948_r1.778_fpx62.47_fpy50.webp", "url": "https://cdn.prod.www.spiegel.de/images/0fe05365-9e73-4d4d-a259-bb919e903502_w948_r1.778_fpx62.47_fpy50.webp" } ``` While uploaded ones look like this: ```json "attachment": { "name": "attachment.png", "type": "image/png", "size": 82776, "expires": 1685680731, "url": "http://localhost:2586/file/h9t9UMB3SL4N.png" } ``` I don't want to have the server probe the URL, because there's a whole lot of security issues that come with that, so I'll have to figure something out in the browser. Let me see what I can do.
Author
Owner

@binwiederhier commented on GitHub (Jun 2, 2023):

This is a PoC that works, but it flickers awkwardly. It assumes everything is an image and tries to load it as an <img> tag, and then switches to the attachment box if it errors.

I assume this can be "fixed" by storing the "is this an image" property locally in the indexedDB.

https://github.com/binwiederhier/ntfy/pull/763

<!-- gh-comment-id:1573039663 --> @binwiederhier commented on GitHub (Jun 2, 2023): This is a PoC that works, but it flickers awkwardly. It assumes everything is an image and tries to load it as an `<img>` tag, and then switches to the attachment box if it errors. I assume this can be "fixed" by storing the "is this an image" property locally in the indexedDB. https://github.com/binwiederhier/ntfy/pull/763
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/ntfy#548
No description provided.