2

I have simple golang/gin-gonic REST Service that serves an excel report upon request to /api/billing. When the requester sets the accept header to application/vnd.openxmlformats-officedocument.spreadsheetml.sheet then an Excel file is served otherwise json. This code works fine in Chrome and IE but not with Firefox and I have no idea why.

In the FF debugger I see that the actual content is transmitted to the browser but FF does not offer the user the download dialog. So for the user it looks like as nothing is happening if he clicks on the link.

I checked already that the popups aren't blocked by FF also I disabled the other security features https://support.mozilla.org/1/firefox/62.0.2/Darwin/de/phishing-malware just in case. I also reinstalled plain FF without any extensions and any changes. The same happens on FF on windows.

r.GET("/api/billing", func(c *gin.Context) {
        if c.GetHeader("Accept") == "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" {
            b := api.GetBillingReportExcel()
            extraHeaders := map[string]string{
                "Content-Disposition": "attachment;filename='BillingReport.xlsx'",
                "Content-Transfer-Encoding": "binary",
                "Content-Description": "Excel Billing Report",
            }
            c.DataFromReader(200, int64(b.Len()),"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",&b,extraHeaders)
        }else {
            billingTenants, _ := cache.Get(c.Request.RequestURI)
            c.JSON(200, GetBillingData())
        }
})

Here are the request headers they are the same for FF & Chrome

HTTP Request:

    Host: localhost:8081
    User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:61.0) Gecko/20100101 Firefox/61.0
    Accept: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
    Accept-Language: de,en-US;q=0.7,en;q=0.3
    Accept-Encoding: gzip, deflate
    Referer: http://localhost:8081/
    Connection: keep-alive

Response

    HTTP/1.1 200 OK
    X-Powered-By: Express
    content-description: Excel Billing Report
    content-disposition: attachment; filename='BillingReport.xlsx'
    content-length: 11397
    content-transfer-encoding: binary
    content-type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
    date: Tue, 25 Sep 2018 12:17:41 GMT
Vad1mo
  • 5,156
  • 6
  • 36
  • 65

2 Answers2

2

You might need to use double-quotes (") for the Content Disposition filename instead of single quotes ('):

extraHeaders := map[string]string{
  "Content-Disposition": `attachment; filename="BillingReport.xlsx"`,
  // Note the double quotes -------------------^------------------^

See RFC 2616 Section 19.5.1 "Content-Disposition":

The Content-Disposition response-header field has been proposed as a means for the origin server to suggest a default filename if the user requests that the content is saved to a file...

    content-disposition = "Content-Disposition" ":"
                          disposition-type *( ";" disposition-parm )
    ...
    filename-parm = "filename" "=" quoted-string

And Section 2.2 "Basic Rules":

A string of text is parsed as a single word if it is quoted using double-quote marks.

  quoted-string  = ( <"> *(qdtext | quoted-pair ) <"> )

RFC 6266 defines additional rules but the simple quoting above is easiest.

Community
  • 1
  • 1
maerics
  • 151,642
  • 46
  • 269
  • 291
0

I tried to fix the issue for a couple of days. However I found the culprit where I didn't expect it. It finally was the behavior of the frontend application as I had the impression it was just a link that gets called and I was wrong.

However I wanted to point out that I could successfully verify that the browser doesn't care if the Content-Disposition has a ', " or no quoting at all.

Also the gin/golang above is working as it should.

thx everyone for helping me out.

Vad1mo
  • 5,156
  • 6
  • 36
  • 65