0

Don't know where to begin debugging this.

I have a local Apache server running a PHP backend that spits out a list of links from an API to the front.

...
<li>
<a href="http://example.com/image1.jpg" target="_blank">Image</a>
</li>
<li>
<a href="https://example.com/image2.jpg" target="_blank">Image</a>
</li>
...

Links are mixed both HTTP and HTTPS. I'm having a problem with Safari in particular. It appears to download the linked HTTPS image (HTTP opens fine in new tab) instead of viewing them in a new tab.

Expected behaviour: all links that have target="_blank" attribute should open the image in a new tab in all browsers.

Actual behaviour: all links open image in new tab in all browsers except for Safari (downloads jpg file instead)

cURL on HTTP links shows a 301 redirect (works fine in all browsers)

> GET /path/to/image1.jpg HTTP/1.1
> Host: hostpath
> User-Agent: curl/7.64.1
> Accept: */*
>
< HTTP/1.1 301 Moved Permanently
< Date: Mon, 20 Feb 2023 07:10:41 GMT
< Content-Type: text/html
< Content-Length: 178
< Connection: keep-alive
< Server: nginx
< Location: https://newpath.com/overHTTPS/image1.jpg
< Strict-Transport-Security: max-age=31536000; includeSubDomains; preload;

cURL on HTTPS links (these open in new tab fine in all browsers EXCEPT for Safari)

> GET /path/to/image2.jpg HTTP/2
> Host: hostpath
> User-Agent: curl/7.64.1
> Accept: */*

< HTTP/2 200
< content-type: image/jpg
< content-length: 150672
< last-modified: Thu, 24 Jun 2021 10:45:06 GMT
< x-amz-version-id: null
< accept-ranges: bytes
< server: AmazonS3
< strict-transport-security: max-age=31536000; includeSubdomains; preload
< date: Mon, 20 Feb 2023 07:16:15 GMT
< etag: "62a2466dbe39f0cd92908fa096ba9011"
< x-cache: RefreshHit from cloudfront
< via: 1.1 uid.cloudfront.net (CloudFront)
< x-amz-cf-pop: -cf-pop
< x-amz-cf-id: amz-cf-id==

cURL from totally different HTTPS as an experiment. (works! Safari opens this jpg to view in new tab just fine)

> GET /path/to/differentHTTPS/image2.jpg HTTP/2
> Host: m.media-amazon.com
> User-Agent: curl/7.64.1
> Accept: */*
>

< HTTP/2 200
< content-type: image/jpeg
< content-length: 13470
< server: Server
< date: Mon, 20 Feb 2023 07:29:44 GMT
< x-amz-ir-id: 6e4a2087-7e28-47ca-bef1-f332c0575d92
< expires: Sun, 15 Feb 2043 04:07:45 GMT
< cache-control: max-age=630720000,public
< surrogate-key: x-cache-214 /images/I/51U-ZNaX5sL
< timing-allow-origin: https://www.amazon.in, https://www.amazon.com
< edge-cache-tag: x-cache-214,/images/I/51U-ZNaX5sL
< access-control-allow-origin: *
< last-modified: Sat, 24 Jul 2021 09:53:23 GMT
< x-nginx-cache-status: HIT
< accept-ranges: bytes
< via: 1.1 uid.cloudfront.net (CloudFront)
< server-timing: provider;desc="cf"
< x-cache: Miss from cloudfront
< x-amz-cf-pop: -cf-pop
< x-amz-cf-id: cf-id==
<

For the most part, my original HTTPS origin and the test HTTPS origin have near identical response headers.

Might be how Safari treats requests to HTTPS resources from insecure HTTP origins (security?). So I deployed to my server which hosts everything over HTTPS; still exact same problem. Safari just will not open a .jpg from this external HTTPS origin in a new tab, it always downloads it.

I swapped in a totally different HTTPS link to an image, and it WORKS. Opens the image to view in a new tab, DOESN'T DOWNLOAD. Just not from the other HTTPS source.

Requests headers from all browsers and accepting image/*.

Any ideas on how I can dig through this? Not sure what else I can try!

Corey
  • 1
  • 2
  • 1
    Different content-type in these two resources: image/jpg vs image/jpeg Maybe this will help: https://stackoverflow.com/questions/33692835/is-the-mime-type-image-jpg-the-same-as-image-jpeg – Robert Feb 20 '23 at 07:53
  • "cURL `from totally different HTTPS`" - suggests that the setup of original HTTPS endpoint is not right and as @Robert links to perhaps the mime-type of `image/jpg` is being set incorrectly in Apache – Professor Abronsius Feb 20 '23 at 07:55
  • 1
    Does this answer your question? [How to force a file to download in PHP](https://stackoverflow.com/questions/3476362/how-to-force-a-file-to-download-in-php) – Ken Lee Feb 20 '23 at 07:57
  • @ProfessorAbronsius This endpoint works fine in other browsers though, which is the confusing part. Wouldn't this indicate Safari weirdness? – Corey Feb 20 '23 at 07:59
  • 1
    If that mime-type of `image/jpg` is served by a n incorrectly configured Apache server perhaps other browsers are more relaxed than Safari ( notably a PITA ) and in this instance Safari is honouring the fact that this is not correct. Have you confirmed config is correct in apache? – Professor Abronsius Feb 20 '23 at 08:08
  • @ProfessorAbronsius I'm confused at how my local Apache config would influence Safari browser behaviour. Links from API (and resulting image links) are not owned by me. Can you clarify what you mean by an incorrectly set mime-type in my own Apache conf? – Corey Feb 20 '23 at 08:16
  • You can, and I'm not saying that you have, configure Apace mime-types in different ways. For instance you might have set a rule in http.conf like this `AddType image/jpg .jpg .jpeg .pjpeg` which would set that header when trying to serve jpeg images... It is merely a line of enquiry. – Professor Abronsius Feb 20 '23 at 08:26
  • I just read your comment fully - so these links are not controlled by you but as your curl trace shows that header is `content-type: image/jpg` rather than `content-type: image/jpeg` as would be more accurate – Professor Abronsius Feb 20 '23 at 08:28
  • Would you have an idea, top of your head, how I could tell Safari to interpret the mime as image/jpeg instead of image/jpg, similar to other browsers? Thanks for these responses by the way – Corey Feb 20 '23 at 09:50

1 Answers1

0

Here are the things that can trigger web browsers to download something:

  1. A download=filename.jpg attribute on the clicked <a> tag.
  2. A Content-Disposition: attachment header sent with the document.
  3. An unknown Content-Type: header sent with the document.

In your case, you are not using the standard mime type for JPEG images in the Content-Type: header. It should be image/jpeg NOT image/jpg. Browsers will freak out and not know how to display the image that e is missing. See Common MIME types - HTTP | MDN for a list of mime types that most browsers understand. Make sure you are using types from that list.

Stephen Ostermiller
  • 23,933
  • 14
  • 88
  • 109