1

I'm fetching static assets (images, pdfs, etc) from AWS S3 and displaying their download progresses to the client using the service worker api. To do this, I'm reading the "content-length" header in the response. In Chrome Canary (77.0.3821.0) this works fine, but in Firefox (version 67.0) and Chrome (version 75.0.3770.80) there is no "content-length" header in the response.

This answer on SO was helpful in setting the request.mode to "cors" which provided me with some initial success, but so far this only seems to work in Chrome Canary.

function respondWithProgressMonitor(clientId, response) {
  for (const key of response.headers.keys()) {
    console.log(key); // returns only "content-type" and "last-modified" on chrome and firefox, but in Chrome Canary includes "content-length"
  }

  const contentLength = response.headers.get('content-length');

  // ...
}
function fetchWithProgressMonitor(event) {
  const request = new Request(event.request.clone(), {
    mode: 'cors',
    credentials: 'omit',
  });
  return fetch(request).then(response => respondWithProgressMonitor(event.clientId, response));
}

My S3 bucket CORS configuration rules should be exposing the header unless I'm doing something wrong.

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
  <CORSRule>

    <AllowedOrigin>*</AllowedOrigin>
    <AllowedMethod>HEAD</AllowedMethod>
    <AllowedHeader>*</AllowedHeader>
    <ExposeHeader>Content-Length</ExposeHeader>
  </CORSRule>
</CORSConfiguration>

I'm not sure why the content-length header is exposed in the Canary response but not in the current Chrome release or Firefox. Are there some other options I need to include in my request to get back a "content-length" header in the response? Any insights or threads to follow are much appreciated.

JT Houk
  • 171
  • 2
  • 16
  • 1
    I think this is due to the fact that until a year ago, the CORS requirements in the Fetch spec didn’t define Content-Length as a “CORS-safelisted response-header name” https://fetch.spec.whatwg.org/#cors-safelisted-response-header-name. So because it’s also defined as a “forbidden header name” https://fetch.spec.whatwg.org/#forbidden-header-name, browsers were required to never expose it to frontend JavaScript code. That changed with https://github.com/whatwg/fetch/commit/3a896ef. See also https://github.com/whatwg/fetch/issues/622. But I guess browsers didn’t implement that change til now. – sideshowbarker Jun 12 '19 at 05:11
  • These are some really great resources, does this apply only to `no-cors` request modes, or should adding a `cors` mode to the request allow me to access forbidden domains? – JT Houk Jun 12 '19 at 07:58
  • It applies to 'cors' mode. Setting the mode to 'no-cors' will ensure that your code can’t access *any* response headers at all — not just forbidden headers. And 'no-cors' mode ensures your code can’t access the response body at all either. So everything in my previous comment refers to 'cors' mode, the normal mode for cross-origin requests. (You basically never want to use 'no-cors' mode; that mode exists almost solely just for the case of caching resources with service workers.) – sideshowbarker Jun 12 '19 at 10:52

1 Answers1

0

Not an answer but rather a workaround... Put the content size in another header. Create something like 'x-content-length-visible' for the header name, which probably won't be a name guarded from the serviceworker.

Eduardo Poço
  • 2,819
  • 1
  • 19
  • 27