Issue with downloading PDF from S3 on Chrome - google-chrome

I'm facing an issue on downloading PDF files from Amazon S3 using Chrome.
When I click a link, my controller redirect the request to the file's URL on S3.
It works perfectly with Firefox, but nothing happens with Chrome.
Yet, if I perform a right click -> Save location as will download the file ...
And even a copy-paste of the S3 URL into Chrome will lead to a blank screen ...
Here is some information returned by curl:
Date: Wed, 01 Feb 2012 15:34:09 GMT
Last-Modified: Wed, 01 Feb 2012 04:45:24 GMT
Accept-Ranges: bytes
Content-Type: application/x-pdf
Content-Length: 50024
Server: AmazonS3
My guesses are related to an issue with the content type ... but all I tried didn't work.

The canonical Internet media type for a PDF document is actually application/pdf as defined in The application/pdf Media Type (RFC 3778) - please note that application/x-pdf, while commonly encountered and listed as a media type in Portable Document Format as well, is notably absent from the official Application Media Types listed by the Internet Assigned Numbers Authority (IANA).
I'm not aware of why and when application/x-pdf came to life, but apparently the Chrome PDF Plugin does not open application/x-pdf documents as of today.
Consequently you should be able to trigger a different behavior in Chrome by changing the media type of the stored objects accordingly.
Alternative (for authenticated requests)
Another approach would be to Force a PDF to download instead of letting Chrome attempt to open it, which can be done by means of triggering the Content-Diposition: attachment header with your GET request - please see the S3 documentation for GET Object on how to achieve this via the response-content-disposition request parameter, specifically response-content-disposition=attachment as demonstrated there in section Sample Request with Parameters Altering Response Header Values.
This is only available for authenticated requests though, see section Request Parameters:
Note
You must sign the request, either using an Authorization header
or a Pre-signed URL, when using these parameters. They can not be used
with an unsigned (anonymous) request.

There is an html based solution to this. Since chrome is up to date with HTML5, we can use the shiny new download attribute!
Broken
Works

Related

Why is my request for an ASP resource not routed as expected by Azure API Management?

For my use case, I would like to use Azure APIM as a proxy.
(Edit: I'm using the "Consumption" tier, and the answer given here works with the standard tiers. I will update this if I find a solution with MS support for the Consumption tier.)
So that a
GET https://my-awesome-api.azure-api.net/default.css
fetches and returns what sits there:
GET https://my-backend.my-domain.com/default.css
It works fine, except for ASP files. If my resource is /default.asp, I get a 404 generated directly by the APIM (not my backend, which is not called at all). The problem is reproduced at every level (I can get /foo/default.css, but 404 on /foo/default.asp).
I've not been able to find in the documentation anything related to special handling of ASP files by default (or any other for that matter). The fact that other types of resources work fine is even more puzzling.
GET /default.css -> works
GET /default.asp -> gets the Azure 404
GET /i-dont-exist.css -> gets the backend 404
GET /i-dont-exist.asp -> gets Azure 404
Azure's 404:
HTTP/1.1 404 Not Found
content-length: 103
content-type: text/html
date: Fri, 05 Apr 2019 15:35:34 GMT
vary: Origin
x-powered-by: ASP.NET
The resource you are looking for has been removed, had its name changed, or is temporarily unavailable.
Most likely your API is misconfigured. Seems you want to pass through all traffic, so you need to create API with Web service URL set to "https://my-backend.my-domain.com" and Path suffix to "/".
Underneath it create an operation for each HTTP method you want to proxy with URL template set to /*.

Cannot play wav file on safari

I'm trying to play a wav file on safari. Pretty much the same question as this: playing a WAV file on iOS Safari
But the accepted answers aren't working. I'm using a rails server with apache and phusion passenger. The audio file plays fine on chrome but not on any safari (desktop, mobile, and through uiwebview).
I'm sending the file in rails with
send_file filename, :type => "audio/x-wav", :disposition => "inline"
From the other stack overflow q&a, I tried adding Content-Range and Content-Length headers to the response
size = File.size(filename)
response.header["Content-Range"] = "bytes 0-#{size-1}/#{size}"
response.header["Content-Length"] = "#{size}"
The error i'm receiving is pretty nondescript "Failed to load resource: Plug-in handled load"
Here are the headers of the response
x-runtime 0.589797
Date Wed, 17 Aug 2016 16:38:49 GMT
X-Content-Type-Options nosniff
Server Apache/2.2.15 (CentOS)
X-Powered-By Phusion Passenger 5.0.7
Status 200 OK
Content-Type audio/x-wav
content-range bytes 0-3243/3244
Cache-Control private
Content-Transfer-Encoding binary
Content-Disposition inline; filename="eng-182-msg0026.wav"
Connection close
Content-Length 3244
X-XSS-Protection 1; mode=block
x-runtime 0.589797
When requesting a direct link to a media file this would work. But I was requesting this through a controller. Safari was making multiple http requests each for a certain range. The server was responding with the entire file every time which is why it fails.
The annoying thing is that the Safari web inspector decides not to show the "Range" header in the network request. It'll show other http headers but not the most important one in this case...
Anyways, short answer, respond back with the the correct byte range that each request wants.
I had the same problem, playing audio files on the Safari didn't work, but on the Chrome and every other browser everything worked as expected.
Set proper Content-Range in response header solve my problem. I used forked gem send_file_with_range, which contain fix for the Rails 5.1.
I recommend this gem because code in this gem is pretty simple and short, and this solution seems like the simplest and quickest.
Note: this solution is specific for the Ruby on Rails developers, but general solution is to set proper Content-Range in the response header, for every request.
I hope that this will be helpful for somebody.

Why do Firefox and Chrome react differently to these HTTP headers?

I'm not sure if my question is based on a lack of understanding - or on Google Chrome working incorrect.
My server sends the following HTTP headers (see yourself):
Etag:"1031384541"
Expires:Mon, 03 Nov 2014 00:01:46 GMT
On a reload Firefox will NOT ask the server but deliver a "200 OK" status code (that's how it should be).
But Google Chrome insists on asking the server and then delivers a "304".
Is there anything I did wrong? What should I change?
Btw.: Interestingly enough these are the default headers sent by GoGrid CDN - which I assume should be correct. But I'm also using the same approach on my own machine (see yourself).

"Protected" error when using "new_copy_url"

I have developed a Box App using "Web App Integrations", the options to manage the file from Box web using right click on it.
It is a popup integration that gets the file modify it and save it again.
Some time ago we detected it was broken but have not had time to check it until now and the problem lays in our last request to box when we want to save the modified file.
In our callback we are requesting #overwrite_url# and #new_copy_url# and we post to that urls with the modified files to "save as" or "save" based on user selection.
The new documentation does not describe this 2 parameters but the app management allows them to be requested so I assume that they are not deprecated, other than that I have not been able to see a difference in the documentation related to this issue.
The request we are using is:
POST /api/1.0/new_copy/dmq5esykpq30sp2kepy3b1d7mvese5ap/9721827325?new_file_name=Koala.proton.jpg HTTP/1.1
Accept: application/json
Content-Type: multipart/form-data;boundary=2iqAzMZWpgN473oDBmRGnysbfTtsD2
Cache-Control: no-cache
Pragma: no-cache
User-Agent: Java/1.7.0_45
Host: upload.box.com
Connection: keep-alive
Content-Length: 17831
--2iqAzMZWpgN473oDBmRGnysbfTtsD2
Content-Disposition: form-data; name="file"; filename="empty.dat"
Content-Type: application/octet-stream
Content-Length: 17627
And the only response I get is a 200 response with the body "restricted" without further information.
I suspect this has something to do with the deprecation of APIv1 but the integrations does not use the api and I did ask a couple of times to box support mail if the deprecation was going to have some effect to integrations and the responses were always negative.
There are definitely changes required in order to update your integration to continue to work. Yes, V1 APIs have been deprecated, and so your old integration has stopped working.
New documentation is here . Subtle difference is that you get way more power now for these web-app integrations. Tokens don't expire after 24 hours, but follow Box's same OAuth2 rules. Scope of your token will be for the file or folder that your web-app-integration is invoked on.
Fundamentally, first step after you get the inbound request on your server is to trade in the auth_code for an Auth-Token via the OAuth2 endpoints.
See the section on auth_code. Then you will have an Auth-token that will let you call regular V2 APIs. To do a copy you would then :
POST https://api.box.com/2.0/files/{id}/copy (with the Bearer-token header)
See https://developers.box.com/docs/#files-copy-a-file for the documentation on how to do a copy operation. Nice thing is you can also do any number of other API calls with that token... as long as they are within scope of that file.

iframe not working for some sites

I tried to access some sites using iframe. Seems it works for some sites but not for others. Any ideas about this? How to fix it? The src link in the iframe is valid, I can access it directly. It just didn't show up in the iframe.
Is this related to X-Frame-Options? How to go around it?
Thanks a lot.
========
Here is the html codes:
<html>
<head>
<title>IFrame Test</title>
</head>
<body>
<iframe src="http://s.click.taobao.com/t?e=zGU34CA7K%2BPkqB07S4%2FK0CITy7klxn%2F7bvn0ay1PXvKwtZSEswjTW0qipvZgGECAqg4jFMvRrmqEsewCV2vrDIKlj1m7fQBXl8oXaLeyNdntQSWHx%2F4LzcWUbay3v1DbpVnqVPkubyxNIXPljUBoBNuLFC0ZLm4SV46zTasP3e6uSYcfiqrWYSyZV%2B7G&spm=2014.21191910.1.0" width="100%" height="600" >
</iframe>
</body>
</html>
Is this related to X-Frame-Options?
Yes, well kinda. It's difficult, possibly impossible, to determine what technique was adopted on the server side to prevent contents from being loaded in frames of different domains, but the X-Frame-Options:SAMEORIGIN wasn't used. This are response headers returned, when attempting to load the web page in question in an iframe:
HTTP/1.1 302 Moved Temporarily
Server: Tengine
Date: Sun, 27 Jan 2013 06:24:22 GMT
Content-Type: text/html
Transfer-Encoding: chunked
Connection: close
Location: [too long, irrelevant, removed ;)]
Expires: Sun, 27 Jan 2013 06:24:22 GMT
Cache-Control: max-age=0
As you can see, the server responds with HTTP status code 302 (moved temporarily), which is often used on web servers instead of forbidden in a bid to prevent any additional such requests overloading the web server (or to distinguish individual denied requests one from another in log files). However, there isn't any X-Frame-Options:SAMEORIGIN header. Such header might or might not be respected by various browsers anyway.
How to go around it?
Not doing some illegal and nasty work on the web server involved, or knowing what conditions need to be satisfied for web server to grant access to the requested location, that's impossible to say. You could ask the admin of the web server kindly to make an exception to this rule for your domain, though. Just a thought...
EDIT: Upon further investigation, the URL you provided actually redirects to
http://item.taobao.com/item.htm?id=13188785766&ali_trackid=2:mm_32761976_0_0:1359267664_4k8_1456591680&spm=2014.21191910.1.0
meaning there are some server-side rewrite rules involved. That doesn't help you much with your URL, but you could use the one it translates to, if all you wanted is to present the target page to the end user. Problem is, you lose any session data and/or tracking cookies that you might have wanted to force on the unsuspecting user and collect spoils of some referral scheme. I'm not implying that's what you wanted to do, but if you did, putting in the iframe source a translated URL wouldn't work. ;)