home-assistant / core

:house_with_garden: Open source home automation that puts local control and privacy first.
https://www.home-assistant.io
Apache License 2.0
73.58k stars 30.75k forks source link

no mjpeg stream through apache2 proxy using ssl #13995

Closed vquie closed 5 years ago

vquie commented 6 years ago

Home Assistant release with the issue: 0.67.1

Last working Home Assistant release (if known): Tried with 0.66 before, same issue

Operating environment (Hass.io/Docker/Windows/etc.): Raspbian 9.1 - virtualenv

Component/platform: https://www.home-assistant.io/components/camera.mjpeg/ https://www.home-assistant.io/docs/ecosystem/apache/

Description of problem: When serving through apache2 proxy with ssl enabled vhost, there is no camera stream available.

Problem-relevant configuration.yaml entries and (fill out even if it seems unimportant):

camera:
  - platform: mjpeg
    name: 'camera_id'
    still_image_url: http://192.168.0.2/image/jpeg.cgi
    mjpeg_url: http://192.168.0.2/video/mjpg.cgi
    username: !secret mjpeg_user
    password: !secret mjpeg_password

Traceback (if applicable): hass log:

Apr 19 10:33:44 myhass hass[17214]: 2018-04-19 10:33:44 INFO (MainThread) [homeassistant.components.http.view] Serving /api/camera_proxy/camera.camera_id to 127.0.0.1 (auth: False)
Apr 19 10:33:45 myhass hass[17214]: 2018-04-19 10:33:45 INFO (MainThread) [homeassistant.components.http.view] Serving /api/camera_proxy_stream/camera.camera_id to 127.0.0.1 (auth: False)
Apr 19 10:33:47 myhass hass[17214]: 2018-04-19 10:33:47 INFO (MainThread) [homeassistant.components.http.view] Serving /states to 127.0.0.1 (auth: False)
Apr 19 10:33:47 myhass hass[17214]: 2018-04-19 10:33:47 INFO (MainThread) [homeassistant.components.http.view] Serving /api/themes to 127.0.0.1 (auth: True)
Apr 19 10:33:47 myhass hass[17214]: 2018-04-19 10:33:47 INFO (MainThread) [homeassistant.components.http.view] Serving /api/translations/en to 127.0.0.1 (auth: True)
Apr 19 10:33:47 myhass hass[17214]: 2018-04-19 10:33:47 INFO (MainThread) [homeassistant.components.http.view] Serving /api/websocket to 127.0.0.1 (auth: False)
Apr 19 10:33:48 myhass hass[17214]: 2018-04-19 10:33:48 INFO (MainThread) [homeassistant.components.http.view] Serving /api/camera_proxy/camera.camera_id to 127.0.0.1 (auth: False)

apache2 log:

192.168.0.1 - - [19/Apr/2018:10:26:29 +0200] "GET /api/websocket?latest HTTP/1.1" 200 104595 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/11.1 Safari/605.1.15"
192.168.0.1 - - [19/Apr/2018:10:33:23 +0200] "GET /states HTTP/1.1" 200 1786 "https://myurl/service_worker.js" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/11.1 Safari/605.1.15"
192.168.0.1 - - [19/Apr/2018:10:33:23 +0200] "GET /service_worker.js HTTP/1.1" 304 322 "https://myurl/service_worker.js" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/11.1 Safari/605.1.15"
192.168.0.1 - - [19/Apr/2018:10:33:23 +0200] "GET /service_worker.js HTTP/1.1" 304 322 "https://myurl/service_worker.js" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/11.1 Safari/605.1.15"
192.168.0.1 - - [19/Apr/2018:10:33:24 +0200] "GET /api/themes HTTP/1.1" 200 286 "https://myurl/states" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/11.1 Safari/605.1.15"
192.168.0.1 - - [19/Apr/2018:10:33:24 +0200] "GET /api/translations/en HTTP/1.1" 200 786 "https://myurl/states" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/11.1 Safari/605.1.15"
192.168.0.1 - - [19/Apr/2018:10:33:24 +0200] "GET /api/camera_proxy/camera.camera_id?token=c58164a69089deaa6703779cd1bebc8585ce027cced95718ead1a57e6b9d7461&time=1524126804471 HTTP/1.1" 200 23771 "https://myurl/states" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/11.1 Safari/605.1.15"
192.168.0.1 - - [19/Apr/2018:10:33:26 +0200] "GET /api/config/entity_registry/camera.camera_id HTTP/1.1" 404 292 "https://myurl/states" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/11.1 Safari/605.1.15"
192.168.0.1 - - [19/Apr/2018:10:33:26 +0200] "GET /api/camera_proxy_stream/camera.camera_id?token=c58164a69089deaa6703779cd1bebc8585ce027cced95718ead1a57e6b9d7461 HTTP/1.1" 200 24353 "https://myurl/states" "Mozilla/5

Additional information: Browser reports:

Failed to load resource: the server responded with a status of 404 (Not Found)
https://myurl/api/config/entity_registry/camera.camera_id
vquie commented 6 years ago

Tried it with different browsers. Does NOT work on:

Does work on:

jamieshaw commented 6 years ago

I'm seeing this issue as well, it appears to be a caching issue with Apple-based browsers, including the SafariControllerView.

I'm finding that if I reload the page with an empty cache (Shift-Click the reload icon in macOS Safari), or force quit iOS Safari or the Home Assistant app, the camera stream will load. Then refreshing the page without emptying the cache causes the issue to resurface.

To add specifics; I'm serving HA behind a reverse-proxied instance of macOS Server's apache2 server with SSL.

vquie commented 6 years ago

@jamieshaw Thank you very much. Looks like it is working in the iOS app as well. Don't know how I tested it that it did not work.

jamieshaw commented 6 years ago

Not sure if it's worth keeping this issue open as it may be an issue with how Home Assistant is rendered in Safari; and not necessarily a greater bug in Apple's browsers.

Until further investigation to rule out a bug in Safari's behaviour, I'd recommend leaving open.

johnclawson commented 6 years ago

I've got the same problem with HA 0.68.1 running behind an nginx proxy. No mjpeg stream to Safari on iOS or MacOS.

carlostico commented 6 years ago

Same problem here works with Chrome and Firefox not Safari ..

moralmunky commented 6 years ago

MacOS Home Assistant 0.69.1 Apache Reverse Proxy (homebrew) One FFMPEG camera playing an MP4 file One FFMPED camera playing an RSTP camera stream 4 Static image JPG cameras Chrome, Firefox, Safari, iOS app

Noticed the behavior after upgrading from .67 to .69.1. I'm seeing 200 success messages when starting the stream in the server logs and no errors in homeassistant.components.http.view or haffmpeg.core debug logs. The video stream is alive and will display through homekit. It displays a broken image icon, no errors in the web console other than the 4040 about the entity registry which another bug report says is normal.

Video Thumbnails: Display in all browsers MP4 Stream: Displays only in Chrome RTSP Stream: Doesn't display in any browser Static JPG: Display full-size window in chrome and Firefox

christ commented 6 years ago

Found two possible causes. Depending on the type of camera, you might be hitting the max allowed connections. The Foscams I have are limited to 4 streams. Which brings me to the semi-workaround, I've disabled KeepAlive on my httpd proxy. The call api/camera_proxy_stream/camera.whatever sends a KeepAlive in the header, if you hit HA directly, the python webserver doesn't respond with KeepAlive while Apache httpd does. There are still times when the image doesn't load (still limited to 4 streams), but it's far less frequent.

vquie commented 6 years ago

Just upgraded to home-assistant 0.73. The stream ist working now through safari. Can anyone else confirm?

flounderscore commented 6 years ago

I have a similar problem with uvc (UniFi Camera NVR) and haproxy (SSL). The live stream shows just fine when I directly to home-assistant's local IP and port 8123, but not when going through haproxy.

Edit: Sorry, forgot to mention: works with chrome, doesn't work with safari. Edit2: Shift-Click reload temporarily fixes the issue on Safari.

nicx commented 6 years ago

I am affected too when using Safari with HA 0.79.3, with Chrome it works fine. When using Safari directly (http://192.168.0.10:8123) without proxy it works even with Safari.

christ commented 6 years ago

Found something on https://www.home-assistant.io/docs/ecosystem/apache/ that seems to have helped out a bit. Specifically disablereuse=on being set for the proxy. I just enabled that and so far it's been way more reliable loading the stream. I'm still limited by my cameras ability to only have 4 streams at once, but this is far better than before.

nicx commented 5 years ago

any news to this? who could help us? whats needed to help us?

balloobbot commented 5 years ago

There hasn't been any activity on this issue recently. Due to the high number of incoming GitHub notifications, we have to clean some of the old issues, as many of them have already been resolved with the latest updates.

Please make sure to update to the latest Home Assistant version and check if that solves the issue. Let us know if that works for you by adding a comment :+1:

nicx commented 5 years ago

nope still the same problem with latest release :(

tkislan commented 5 years ago

I have the same issue. Fails in Safari, but works in Chrome. There is an error in the console, but no stacktrace nor reference to anything actually.

[Error] The operation couldn’t be completed. ( error 0.)
[Error] Cannot load .
shmuelzon commented 5 years ago

For what it's worth, here's what I found so far: Just as @tkislan, I saw the same errors in safari. Using Wireshark, I can see that Safari closes the connection with a TLS/SSL alert "Level: Warning, Description: Close Notify". The HTTP request is pretty much the same between an SSL connection (proxied by nginx) and a direct HTTP request to HA:

GET /api/camera_proxy_stream/camera.generic_camera?token=<token> HTTP/1.1
Host: raspberrypi.local:8123
Connection: keep-alive
Accept: image/png,image/svg+xml,image/*;q=0.8,video/*;q=0.8,*/*;q=0.5
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0.3 Safari/605.1.15
Accept-Language: en-us
Referer: http://raspberrypi.local:8123/lovelace/default_view
Accept-Encoding: gzip, deflate

The server response is a bit different as the server name is different and some cache-control headers are included. HTTP:

HTTP/1.1 200 OK
Content-Type: multipart/x-mixed-replace; boundary=--frameboundary
Transfer-Encoding: chunked
Date: Tue, 09 Apr 2019 14:31:19 GMT
Server: Python/3.5 aiohttp/3.5.4

HTTPS:

HTTP/1.1 200 OK
Server: nginx/1.10.3
Date: Tue, 09 Apr 2019 14:59:54 GMT
Content-Type: multipart/x-mixed-replace; boundary=--frameboundary
Transfer-Encoding: chunked
Connection: keep-alive
Strict-Transport-Security: max-age=31536000; includeSubdomains
Cache-Control: private
Cache-Control: no-cache
Cache-Control: no-store

Another thing that might be worth mentioning is that the initial chunk when using SSL is smaller and does not include the entire MJPEG frame:

ffa
--frameboundary
Content-Type: image/jpeg
Content-Length: 14893

As opposed to the HTTP variant:

48c6
--frameboundary
Content-Type: image/jpeg
Content-Length: 18560

The latter include the entire frame boundary and the frame itself (as expected). Maybe Safari can't handle the MJPEG frame being split to multiple HTTP chunks?

Anyways, the requests and responses are the same for both Safari and Chrome so it's "just" a matter of Safari not handling it correctly.

Edit: I also compared the network dump on the proxy server and can confirm nginx is manipulating the HTTP chunks and seems to be limiting them to 0x1000 (4096) bytes.

Edit 2: it seems the MJPEG streams don’t really need to be chunk-encoded. I’ll try to see if I can remove that and if it makes any difference.

shmuelzon commented 5 years ago

After trying out a few things, I don't think it's directly related to the chunked encoding. Using mjpg-streamer as the server with the same nginx proxy works as expected. I did notice that HA sends the boundary incorrectly in the header:

Content-Type: multipart/x-mixed-replace; boundary=--frameboundary

When it should be without the two dashes, i.e.:

Content-Type: multipart/x-mixed-replace; boundary=frameboundary

Fixing this does cause Safari to accept the first JPEG frame, but when the second one starts it resets the connection again. Not sure yet if it's something to do with HTTP chunks or the second multipart, but it's a start...

nicx commented 5 years ago

this is really annoying, still having that issue :(

shmuelzon commented 5 years ago

Sadly, I was never able to get to the root cause of the issue. It’s not directly related to SSL nor chunked encoding as I have another working example. I tried producing the same responses from mjpg-streamer in HA (same headers, same chunk sizes, etc.) but that didn’t work. The only difference remaining was the JPEG frame itself. I was able to reach the point that Safari read the first complete frame but then it rejected it for some reason. Webkit’s code is quite complex and I couldn’t fine the actual location where the decision that the HTTP content isn’t an image was made, only caught it somewhere down the line...

jamieshaw commented 5 years ago

So I've just had another look into this, as it's one of the bugs still in my config.

I'm wondering if it's just Safari's poor service worker support in version 12? The latest technology preview doesn't appear to have an issue…

nicx commented 5 years ago

Hi @jamieshaw, I just tested it with the latest Tech Preview too... but I have exact the same issue. It is still only working with Chrome or Firefox, not with Safari. :(

shmuelzon commented 5 years ago

It’s been a while but, IIRC, after fixing the HTTP boundary, Webkit didn’t recognize the first frame as an image and closed the connection. The only lead I have right now is the fact that the working example is an EXIF image while the non-working one is a JFIF. I don’t know if it’s related but I wanted to try and re-encode the frame in HA to see if that makes any difference but I never got around to trying. @jamieshaw, @nicx, could you please check the JPEG format of your cameras and tell me which JPEG type it is? Looking at the first few bytes of the image should be enough. Maybe that could tell us if it’s related or not...

nicx commented 5 years ago

@shmuelzon am using Hikvision cams, they are using JFIF type.

stale[bot] commented 5 years ago

There hasn't been any activity on this issue recently. Due to the high number of incoming GitHub notifications, we have to clean some of the old issues, as many of them have already been resolved with the latest updates. Please make sure to update to the latest Home Assistant version and check if that solves the issue. Let us know if that works for you by adding a comment 👍 This issue now has been marked as stale and will be closed if no further activity occurs. Thank you for your contributions.

vandalon commented 4 years ago

I'm seeing this exact same issue with home assistant 0.104 and https enabled. Only in safari, chrome, firefox Fully, IOS app and Kiosk browser working fine.

mkarnebeek commented 3 years ago

Anybody managed to get this solved, or having further hits/pointers on where to look? Even going through Nabu Casa remote access, this fails in safari. (we might raise it there, for them to try an figure this out, and then see what solution they come up with :) )

I've been digging through disabling buffers, keep-alive, etc in nginx, but no avail just yet.

Ofcourse it works when accessing HA directly, without going through nginx.

shmuelzon commented 3 years ago

Last time I investigated this there were two issues. The first was the HA didn't correctly create the multipart HTTP content as described here. After fixing that I tried to debug Safari/WebKit and it seemed that the combination of chunked encoding (which the NGINX proxy adds) and the JFIF format caused WebKit to fail detecting the chunk as an image and then it closes the connection. As a workaround, it may be possible, in HA, to remux the JPEG frame and convert it from the JFIF format to the EXIF format. I think the only difference is the header of the file and the image itself is the same. I may be enough to just pass the image through the PIL library but I never got around to try this.

mkarnebeek commented 3 years ago

Tnx for the quick response!

I managed to get some progress in macOS safari: I created another nginx server definition without ssl on the same domain and a different port, and that just worked.

Even weirder, it also caused the ssl site definition to work, but it's a bit erratic. When copying the url of the stream (.../api/camera_proxy_stream/...) into an incognito window, it would break, but later work. It now even keeps working if I remove website data for that domain, restart the browser and try the url again.

The behaviour on mobile (safari, chrome, firefox) is a bit different: It works for http, but consistently doesn't work for https nginx server definition

shmuelzon commented 3 years ago

Yes, that's what I saw as well. My guess is that with the SSL encapsulation WebKit get's a smaller buffer from the mjpeg frame and just fails parsing it. I never was able to find the root cause of it thought. I tried posting on the WebKit mailing list but no one responded. As I don't think it will be fixed there anytime soon and, even if it will, it would take a while until it makes its way to the next stable version, we might need our own workaround here. I have a different device that publishes an mjpeg video also behind an NGINX proxy that works just fine with Safari. The only difference I could find was the jpeg format I mentioned before. That's why I suggest trying to convert each frame in HA when streaming to see if it makes a difference.

mkarnebeek commented 3 years ago

I've worked around it by switching from PWA to the IOS companion app, there it does work. I did have to sacrifice my client-certificates authentication for something else through, as that's not supported in the ios app. Anyhow, I've worked around it sadly instead of solving it.

Thanks for all the pointers! I've got a fairly well working situation now.

mbaran5 commented 3 years ago

@mkarnebeek

I created another nginx server definition without ssl on the same domain and a different port, and that just worked.

Can you elaborate on that a little bit? I'd love to try this fix out.

mkarnebeek commented 3 years ago

I currently have something along the lines of:

server {
  listen 12345 ssl;
  server_name my.domain.name;

  ssl_certificate /etc/nginx/extra/my.domain.name/crt;
  ssl_certificate_key /etc/nginx/extra/my.domain/name/key;

  include /etc/nginx/extra/options-ssl-nginx.conf;
  ssl_dhparam /etc/nginx/extra/ssl-dhparams.pem;

  location / {
    proxy_pass "http://homeassistant.local:8123";
    proxy_set_header Host $host:$server_port;

    proxy_http_version 1.1;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto "https";
    proxy_set_header X-Forwarded-Host $host;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $http_connection;
    proxy_set_header Sec-WebSocket-Protocol $http_sec_websocket_protocol;
    proxy_set_header Sec-WebSocket-Key $http_sec_websocket_key;
    proxy_set_header Sec-WebSocket-Extensions $http_sec_websocket_extensions;
    proxy_set_header Sec-WebSocket-Version $http_sec_websocket_version;
  }
}

Where options-ssl-nginx.conf contains:

# https://raw.githubusercontent.com/certbot/certbot/master/certbot-nginx/certbot_nginx/options-ssl-nginx.conf

ssl_session_cache shared:le_nginx_SSL:1m;
ssl_session_timeout 1440m;

ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;

ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384;

I added another definition without all of the ssl stuff, on a different port number:

server {
  listen 12346;
  server_name my.domain.name;

  location / {
    proxy_pass "http://homeassistant.local:8123";
    proxy_set_header Host $host:$server_port;

    proxy_http_version 1.1;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto "http";
    proxy_set_header X-Forwarded-Host $host;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $http_connection;
    proxy_set_header Sec-WebSocket-Protocol $http_sec_websocket_protocol;
    proxy_set_header Sec-WebSocket-Key $http_sec_websocket_key;
    proxy_set_header Sec-WebSocket-Extensions $http_sec_websocket_extensions;
    proxy_set_header Sec-WebSocket-Version $http_sec_websocket_version;
  }
}

And pointed macOS Safari to http://my.domain.name:12346, logged into HA, and my videostream appeared. After pointing Safari again at https://my.domain.name:12345, the stream magically also appeared, where it previously didn't. Trying it again this morning, it didn't work on https anymore. The behaviour on https seems erratic, on http is seems stable enough for general use, but it wouldn't surprise me that a different bitrate/resolution/whatever would cause it to break again.

For some reason the iOS companion app doesn't suffer from this, where all other browsers on iOS (chrome, firefox tested) do suffer from it.

mkarnebeek commented 3 years ago

Also: the stream is only broken when passing through a proxy (Nabu Casa included). When accessing it directly using homeassistant.local for example, it always works.

I think @shmuelzon is on the correct path: Trying a different JPEG format sent by HA would change things, or ofcourse, solving it in WebKit.

mbaran5 commented 3 years ago

Ah, ok. I wonder why this issue doesn't seem to get any traction from the HA team to help review. It's a very old issue at this point.

shmuelzon commented 3 years ago

Well, first of all, this issue is closed. Second, I guess the people using an SSL proxy in front of HA are a minority. Add to this the fact that the problem isn't in HA to begin with. I guess it's just not interesting enough...

mbaran5 commented 3 years ago

True, but it does affect Nabu Casa as well, which is a paid service.

shmuelzon commented 3 years ago

That's a good point. Personal SSL proxies are out of scope for HA but Nabu Casa is a different story. I don't personally use it but perhaps it would be best to open a new issue stating the problem while using Nabu Casa and referring to this ticket for technical details.

radiocolin commented 2 years ago

I see the same issue in Safari over https via Cloudflare Tunnel. Safari local and via Tunnel over HTTP work fine.

saschaludwig commented 1 year ago

Any news on this? I still have no Videos in Safari and I do not use any proxies, but have the SSL directly in the HassOS VM.

dumpfheimer commented 1 year ago

Was someone able to fix this?

shmuelzon commented 1 year ago

Hey, I think that, as this is technically a bug in WebKit's implementation, Home-Assistant isn't inclined to handle it but, as @mbaran5 mentioned, it also doesn't work through the paid Nabu Casa service so perhaps someone using that service can open a bug for that platform and reference here for technical details.

From what I have so far, there several issues here:

  1. Home Assistant doesn't send a correct HTTP header when it generates the MJPEG stream itself. See here where --frameboundary should be frameboundary. Fixing this only caused the first frame to work on Safari but the following ones did not
  2. Safari seems to work fine with SSL-Proxied EXIF-based MJPEG images (as is generated by, for example, mjpeg-streamer with an RPi camera). If an MJPEG frame is created with the JFIF header, Safari fails to parse it (through SSL proxy only). If HA could convert the formats before sending a frame, that could also help
  3. When HA proxies an MJPEG stream, i.e., it doesn't create the stream itself from still JPEG images, it creates a chunk-encoded HTTP stream which, again, Safari doesn't seem to like. Generally speaking, Safari works better if it gets the entire frame together and not separated to chunks (which SSL proxies usually do)

As an example, if I try to access the mjpeg-streamer directly, not via HA, behind the SSL proxy, Safari can display the stream just fine, when it's proxied via HA, it doesn't work. The below screenshot has the stream as provided directly by mjpeg-streamer on the left and the HA-proxied version on the right. The left one is works with an SSL proxy but the right one does not: image

mploetner commented 11 months ago

Any news on this? I wonder why this is broken so long while it also affects the paid subscription service. Even if it's a WebKit problem there seems to be a possible solution pointed out.

I would not care when the App would allow easier switch between multiple homes but like that it's a p.i.t.a.

hiatsu0 commented 7 months ago

Been having this issue as well. Initially thought it was just some weird error in my configuration/cameras but then happened to access HA with a non-safari browser and to my surprise the Glance-cards worked just fine.

Really weird that an issue affecting the whole Apple ecosystem, the official iOS/iPadOS app and even paid subscription is not being taken care of after all these years.

shmuelzon commented 7 months ago

@hiatsu0 It's a bug in WebKit (the web browser engine) Apple use so it affects all of their devices. The bug relates somehow to parsing a specific type of JPEG type, JFIF vs EXIF, when it comes in chunks (which is, usually, what happens when using a proxy. It would be ideal to fix it in WebKit (and wait for it to arrive in the relevant Apple OS versions). Alternatively, a work-around might be for HA to transcode the JPEG images from one format to another.