Sunday, October 19, 2014

Downloading Resources from Cross-Origin Requests

If you decide to have a separate web- and backend- tier, cross-origin HTTP requests cause no end of difficulties in a variety of unlikely ways. I've written before about using CORS headers to mitigate some of them but here's yet another. It surfaces whenever you try to use the download attribute in an anchor tag but where the URI resource lives on the backend and not the web server. For example, I host tunes on my server and I want users to be able to download the tune scores which are in pdf format:
    
  download pdf
The intention is that when the user selects the link, the browser will know that the resource is intended to be downloaded and will use the download attribute value as the file name. This indeed happens when the resource is hosted locally, but it no longer does so in the most recent versions of Chrome when it's hosted remotely. It seems as if the Chrome developers have now implemented a rather awkward algorithm in the html5 spec designed to mitigate possible security dangers in downloading files from untrusted sites. This is ostensibly because a hostile server could try to inveigle a user into unwittingly downloading private information (thinking it came from the hostile server itself) which could then perhaps be re-uploaded to that server. The solution is to use the Content-Disposition HTTP header when serving up the resource to suggest a file name. For example:
    
  Content-Disposition: attachment; filename=mytune.pdf
Conforming browsers should then use this name when they interpret the download attribute in the anchor tag.