0

I am dealing with a weird Error, that is reproducible only in production over a https connection. Firstly I am trying to download a *.cvs file, my backingbean code looks as follows:

    ExternalContext externalContext = facesContext.getExternalContext();
    try (OutputStream outputStream = externalContext.getResponseOutputStream()) {
        String exportFileName = exportHandler.getExportFileName();
        String contentType = externalContext.getMimeType(exportFileName);

        externalContext.responseReset();
        externalContext.setResponseCharacterEncoding(CHARSET);
        externalContext.setResponseContentType(contentType);
        externalContext.setResponseHeader("Content-disposition", "attachment; filename=\"" + exportFileName + "\"");

        int length = exportHandler.writeCsvTo(outputStream); // with a BufferedWriter the lines are written and the bytes are summed up.

        externalContext.setResponseContentLength(length);
        outputStream.flush();
    }

    facesContext.responseComplete();

Everything works fine over an http connection, or on localhost (even https on localhost works), but in production over an https connection, different web browsers give different Error messages. Chrome gives the following message: "The webpage at ... might be temporarily down or it may have moved permanently to a new web address. ERR_HTTP2_PROTOCOL_ERROR" Under Firefox starts to load and then nothing happens as it takes forever. Under IE: "The connection to the website was reset. Error Code: INET_E_DOWNLOAD_FAILURE"

My take would be that, it has to do with the response content length, as I am not sure I still need it after writing the Outputstream. The response header looks like this:

  • Connection: keep-alive
  • Content-disposition: attachment; filename="test.csv"
  • Content-Type: text/csv; charset=ISO-8859-15
  • Date: Mon, 04 May 2020 10:16:41 GMT
  • Transfer-Encoding: chunked

Not sure why ends up my response with a chunked transfer-encoding, as far as I know, that can happen only when content length is not set. Does any body have any idea, do i miss some header constraints in my response, like setting cache-control?

Kukeltje
  • 12,223
  • 4
  • 24
  • 47
att1la
  • 23
  • 4
  • You suspect the content-length, but I'm also suspecting http2 and not JSF directly. Tried downloading from a servlet? And the content-length is according to the headers not set – Kukeltje May 04 '20 at 11:49
  • No, I haven't...only through JSF. I find it also a bit odd, that the length is not set accordingly, even though the locally downloaded file has the same size in bytes, as the length variable. – att1la May 04 '20 at 12:27

1 Answers1

0

The difference might actually be between HTTP1.1 and 2.0 and not directly https and http. This might be occuring because https allows upgrading the protocol to 2.0 during the handshake, while in basic http no such negotiation takes place.

With that in mind, the header parsing implementations in the browser might be different. If I had to guess, this is about the content-disposition filename.

In HTTP2, most browsers will fail to parse the content-disposition filename if it contains non US-ASCII characters. HTTP1.1 implementations are more lenient with that.

You can still have utf-8 filenames with content-disposition filename* attribute.

Currently the most supported Content-Disposition format is:

attachment; filename="<us-ascii filename>"; filename*=utf-8''<url-encoded-utf-8-filename>

ie.

attachment; filename="EURO rates"; filename*=utf-8''%e2%82%ac%20rates