arantes555 / electron-fetch

A light-weight module that brings window.fetch to the background process of Electron
Other
133 stars 21 forks source link

`blob.type` is empty for certain image urls #40

Closed searene closed 3 years ago

searene commented 3 years ago

I use electron-fetch to get some image's blob types, as follows:

const blobType = (await (await fetch(url)).blob()).type

It works well in most case, however, blobType is empty when url is the following one:

https://thumbor.forbes.com/thumbor/651x436/https://blogs-images.forbes.com/davidbressan/files/2017/07/TORGERSON_2010_Arizona_Meteor_Crater.jpg?width=960

blob itself is not empty, here is blob object I got while debugging

Blob {
  [Symbol(closed)]: false,
  [Symbol(type)]: '',
  [Symbol(buffer)]: <Buffer ff d8 ff e0 00 10 4a 46 49 46 00 01 01 00 00 01 00 01 00 00 ff db 00 43 00 08 06 06 07 06 05 08 07 07 07 09 09 08 0a 0c 14 0d 0c 0b 0b 0c 19 12 13 0f ... 46592 more bytes>
}

So why is blob type empty? I'm using electron-fetch 1.7.4.

arantes555 commented 3 years ago

I am sorry but I cannot reproduce your error. When I try getting the blob type of the link you gave, I get image/jpeg.

> fetch = require('electron-fetch').default
[Function: fetch] { isRedirect: [Function (anonymous)] }
> getBlobType = async (url) => (await (await fetch(url)).blob()).type 
[AsyncFunction: getBlobType]
> getBlobType("https://thumbor.forbes.com/thumbor/651x436/https://blogs-images.forbes.com/davidbressan/files/2017/07/TORGERSON_2010_Arizona_Meteor_Crater.jpg?width=960").then(console.log)
Promise { <pending> }
> image/jpeg

> getBlobType("https://thumbor.forbes.com/thumbor/651x436/https://blogs-images.forbes.com/davidbressan/files/2017/07/TORGERSON_2010_Arizona_Meteor_Crater.jpg?width=960").then(console.log)
Promise { <pending> }
> image/jpeg
arantes555 commented 3 years ago

The blob type comes directly from the content-type header : https://github.com/arantes555/electron-fetch/blob/master/src/body.js#L66 . Maybe somehow the server does not respond with the header in question when you send the request?

searene commented 3 years ago

The blob type comes directly from the content-type header : https://github.com/arantes555/electron-fetch/blob/master/src/body.js#L66 . Maybe somehow the server does not respond with the header in question when you send the request?

Thanks for the quick reply and the hint. I started Wireshark to capture HTTP packets and checked if Content-Type was in it. The result was:

  1. The first time I requested, the correct blob type was returned. The corresponding HTTP response code was 200, the response also had image/jpeg as its Content-Type, everything was perfect.
  2. The second time I requested, I got an empty blob type. The corresponding HTTP response code was 304 Not Modified, the response didn't have a Content-Type HTTP header(according to this StackOverflow answer, this was the correct behavior).
  3. After that, no matter how many times I tried, the blob type continued to be empty, the HTTP response was also the same: 304 Not Modified with no Content-Type HTTP header, unless I used the following code to clear Electron's cache:
    
    const win = BrowserWindow.getAllWindows()[0];
    const ses = win.webContents.session;

ses.clearCache(() => { alert("Cache cleared!"); });



I'm not sure whether it should be resolved by `electron-fetch`.

Another interesting fact worth noticing is that: when I use [node-fetch](https://github.com/node-fetch/node-fetch) to get the image's blob type, it's always the correct one: `image/jpeg`. The corresponding response is always 200. Maybe `electron-fetch` and `node-fetch` use different cache mechanisms?
searene commented 3 years ago

This is the corresponding HTTP request and response(304 Not Modified) I captured.

GET http://thumbor.forbes.com/thumbor/651x436/https://blogs-images.forbes.com/davidbressan/files/2017/07/TORGERSON_2010_Arizona_Meteor_Crater.jpg?width=960 HTTP/1.1
Host: thumbor.forbes.com
Proxy-Connection: keep-alive
accept: */*
user-agent: electron-fetch/1.0 electron (+https://github.com/arantes555/electron-fetch)
accept-encoding: gzip,deflate
connection: close
Accept-Language: en-US
If-None-Match: "dEVNir27sbw2Nf3gqwJJDu1CkOf4i4gph2z1W/ymXHo"

HTTP/1.1 304 Not Modified
Age: 546878
Connection: keep-alive
Date: Wed, 06 Oct 2021 15:55:26 GMT
Etag: "dEVNir27sbw2Nf3gqwJJDu1CkOf4i4gph2z1W/ymXHo"
Keep-Alive: timeout=4
Proxy-Connection: keep-alive
Via: 1.1 varnish
X-Cache: HIT
X-Cache-Hits: 1
X-Served-By: cache-qpg1252-QPG
X-Timer: S1633535726.317260,VS0,VE1
arantes555 commented 3 years ago

Another interesting fact worth noticing is that: when I use node-fetch to get the image's blob type, it's always the correct one: image/jpeg. The corresponding response is always 200. Maybe electron-fetch and node-fetch use different cache mechanisms?

Yes, node-fetch does not use any cache AFAIK, and electron-fetch uses the net networking stack from electron, which mandatorily uses the native Chromium caching.

As for this precise problem, it may be a Chromium or electron bug. Which electron version are you using ?

EDIT: a bit more detail : what happens with caching is that, even if the actual response is a 304, the net stack "magically" converts it back to a fake 200 before exposing it to the user, so electron-fetch cannot even know if it's a 200 or 304. But it should set it back with all the stuff from the original 200 that got cached, even the type, which seems to be missing here in the re-created 200.

searene commented 3 years ago

As for this precise problem, it may be a Chromium or electron bug. Which electron version are you using ?

I started this experiment using a brand new project, which meant I was using the latest version of electron, which is 15.1.1

I've attached the minimal project that I used to test this issue. You can check if you can reproduce the issue from it. Just run npm install then npm start, the blob will be printed in the console.

electron-test.zip

arantes555 commented 3 years ago

Sorry for the delayed response : it's actually a known electron bug, see https://github.com/electron/electron/issues/27895 . Nothing I can do until it's fixed on Electron's side, sorry. I'm closing this issue.