Mobile Safari on iOS 5.1 Unexpectedly Making Cross Origin Resource Sharing Requests

I was astonished when I finally understood a problem my web application was experiencing recently: After viewing a PDF file from Mobile Safari on the iPad, the browser treated all future Ajax requests in that browser tab as Cross Origin Resource Sharing requests and subsequently sent the HTTP ‘OPTIONS’ verb, rather than the ‘GET’ verb I expected. That caused a lot of my functionality to break. It’s been quite a while since I’ve experienced a bug in my application this esoteric.

If you’ve seen this behavior in your application, you should be able to fix it by using “Content-Disposition: inline” and not “Content-Disposition: attachment”. For the long version, keep reading.

The Symptoms

The symptoms were thus:

  1. Click link to view PDF.
  2. See PDF in Mobile Safari.
  3. Use the back button to return to the site.
  4. Poof! The site is now seriously broken.

It took me quite some time to narrow this down, doing everything from logging debug messages to reading the HTTP conversation in Wireshark, but I finally noticed the connection to the PDF viewer and from that point there weren’t many possibilities left.

I was originally serving up the file with this line in my Rails controller: send_data :filename => "foo.pdf", :type => "application/pdf", :status => 200. This seemed to work fine on most platforms, including all desktop browsers and Mobile Safari on iOS 5.0. However, after viewing the PDF in Mobile Safari on iOS 5.1 all hell broke loose and my application’s Ajax calls stopped working.

The Fix

Changing the send_data call to look like send_data :filename => "foo.pdf", :type => "application/pdf", :disposition => "inline", :status => 200 turned out to be all I needed to fix the problem.

If you’ve been having strange issues with unexpected cross origin resource sharing requests from the iPad, try checking your Content-Disposition headers. The specific solution will depend on your web application platform, but taking a look at your headers may resolve the issue.