arantes555 / electron-fetch Goto Github PK
View Code? Open in Web Editor NEWA light-weight module that brings window.fetch to the background process of Electron
License: Other
A light-weight module that brings window.fetch to the background process of Electron
License: Other
Hi,
I cannot access properties inside the body value.
I used the get method like this:
export const getInstrument = async () => {
const url = baseUrl + "/Instruments";
const res = await fetch(url, {
method: "GET",
headers: { "Content-Type": "application/json" }
});
return await res;
};
I get the following response when checking the debug console
If use res.json() i get the following error
Uncaught (in promise) SyntaxError: Unexpected token o in JSON at position 1
at Object.parse (<anonymous>)
Some sites, for example, Armenia's government site, have invalid header values. The example site sends a X-Frame-Options
header set to “DENY�
, which, obviously, contains invalid characters.
The function checkInvalidHeaderChar
will throw an error if a header value contains an invalid character. When throwing in promises, the error is usually caught. But this code
const fetch = require('electron-fetch')
(async() => {
try {
await fetch('https://gov.am/en/');
} catch (e) {
console.log(`caught: ${e}`)
}
})
will throw an error, even though there is a catch
block.
This is caused by headers.append()
, which does the check (L189), located inside the callback of req.on('response')
(L147).
When something throws inside a callback inside a Promise, there is no way to catch the error. What I'm saying is:
function promiseThrowAfter1s() {
return new Promise(() => {
setTimeout(() => {
throw new Error("gotcha");
}, 1000)
})
};
promiseThrowAfter1s().catch(() => {
// never gets executed
})
A simple solution to that would be to wrap the on('response')
listener with a try-catch block, and reject the promise when caught.
Another suggestion
Maybe provide an option like sanitizeHeaders: boolean
so that the user can ignore invalid headers, because invalid headers don't create any unexpected errors in electron imo.
C:\Electron\Fetch_Data\node_modules\electron-fetch\lib\index.js:1279 Uncaught TypeError: Cannot read property 'isReady' of undefined
at Object. (C:\Electron\Fetch_Data\node_modules\electron-fetch\lib\index.js:1279)
at Object. (C:\Electron\Fetch_Data\node_modules\electron-fetch\lib\index.js:1499)
at Module._compile (internal/modules/cjs/loader.js:968)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:986)
at Module.load (internal/modules/cjs/loader.js:816)
at Module._load (internal/modules/cjs/loader.js:728)
at Module._load (electron/js2c/asar.js:717)
at Function.Module._load (electron/js2c/asar.js:717)
at Module.require (internal/modules/cjs/loader.js:853)
at require (internal/modules/cjs/helpers.js:74)
this is the error i am getting because i am calling "const fetch=require('electron-fetch').default"
in the renderer. please help me i have tried many solutions but nothing is working.
and i have tried calling the native fetch() without "require" then it is working only for GET method and in other it is giving 403 error.
While reading curl manual I came up with these sentences
curl will attempt to re-use connections for multiple file transfers, so that getting many files from the same server will not do multiple connects / handshakes. This improves speed. Of course this is only done on files specified on a single command line and cannot be used between separate curl invokes.
Wondered could this be done with electron fetch or any other fetch libraries somehow ?
Thanks
subj
The error below was thrown when building with esbuild on non-electron env
> node_modules/electron-fetch/lib/index.js:1291:21: error: Could not resolve "electro
n" (mark it as external to exclude it from the bundle, or surround it with try/catch t
o handle the failure at run-time)
1291 │ electron = require('electron');
╵ ~~~~~~~~~~
&&
> console.log(process.versions.electron)
undefined
undefined
I wonder if you could wrap it in a try...catch.
In the options section the agent
option is described like this:
agent: null, // (/!\ only works when useElectronNet is false) Node HTTP Agent.,
If we know upfront that this option is not supported with useElectronNet
enabled maybe there should be a check for that?
Like this the user gets direct feedback when using the wrong option combination and would avoid problems when e.g. switching from node-fetch
to electron-fetch
in which case it's easy to miss that information and the agent option is just silently ignored.
What do you think?
I can not send cookies via { session: session.fromPartition('myPartition') }
option, and it seems to be an issue of electron net
module? electron/electron#8891 (comment)
I wonder is there a good way to send cookies (from session) currently?
Default behavior is setting useElectronNet to true as mentioned in documentation,
but in my app I cannot read the header information content-type
.
My app downloads hundreds of files in chunks for example in 20 item groups then the next 20 one and so on, so I create a job stack and process them in a loop with awaiting,
when I set useElectronNet I can read the content-type so I am confused a little bit, am I doing sth wrong or is there an implementation problem with electron's net module ?
the below code might help with the issue;
const processItem = async (item, outputPath) => {
const [ itemUrl, newName, subFolderName ] = item;
const url = new URL(itemUrl);
const itemName = newName ? `${newName}${path.extname(url.pathname)}` : path.basename(url.pathname);
const response = await fetch(itemUrl, {useElectronNet: false});
if (response.ok) {
if (subFolderName) {
await mkdir(`${outputPath}/${subFolderName}`, { recursive: true }, () => {});
}
const contentType = response.headers.get('content-type');
const extension = mime.extension(contentType);
console.log('extension', extension);
const dest = createWriteStream(path.join(outputPath, subFolderName ? subFolderName : '', itemName));
await streamPipeline(response.body, dest);
} else {
throw {
status: response.status,
statusText: response.statusText,
itemInfo: url.href
}
}
};
any idea what I am missing or using electron's net is problematic in my apps electron version ?
Environment information;
electron": "^12.0.0",
"electron-builder": "^22.10.5",
node: v14.15.1,
npm: 6.14.8
When I'm making a request with "Authorization" header Basic auth-scheme and provide a wrong username or password in it I'm getting an error from req.on('login')
event handler "login event received from ${authInfo.host} but no credentials provided".
I'm not using a proxy and would like to receive the error response from the server instead.
In req.on('login')
callback first parameter authInfo
has isProxy
flag that is false in my case.
I suppose that flag should be used in the callback to prevent current behavior?
authInfo: {
host: 'localhost',
isProxy: false,
port: 7990,
realm: 'Atlassian Bitbucket',
scheme: 'basic'
}
Version 1.7.4
Line 22 in ee14e5a
require("electron")
then calling isReady
does not work in a render thread. I tried to fix this by changing it to require("electron").remote
but then it errors out when a request finishes.
add remote support for renderer user?
Uncaught TypeError: Cannot read property 'isReady' of undefined
this is how I fix it
// ./lib/index.js
// line 1225
let electron;
// istanbul ignore else
if (process.versions['electron']) {
electron = require('electron').remote; // this case we should use electron.remote
}
const isReady = !electron || electron.app.isReady() ? Promise.resolve() : new Promise(function (resolve$$1) {
return electron.app.once('ready', resolve$$1);
});
I don't know anything about writing config for modules, so I can't contribute any code, sorry.
The namespace fetch is exported instead of the function fetch
Undici now has a spec compliant fetch implementation: https://www.npmjs.com/package/undici
However, currently it would be a breaking change as undici, unlike node-fetch, returns web streams instead of node streams.
In v1.1.0
the exports of index.js look like:
exports = fetch;
exports.Headers = Headers;
exports.Request = Request;
exports.Response = Response;
exports.FetchError = FetchError;
In v1.2.x
however it was changed to:
exports.default = fetch;
exports.Headers = Headers;
exports.Request = Request;
exports.Response = Response;
exports.FetchError = FetchError;
which is incompatible with the current typings. Was this intended?
Hi is possible to do that?
We can enable request instead of useElectronNet
Then we can do something like:
var Client = require('node-rest-client').Client;
var client = new Client();
var args = {
headers: { "Content-Type": "application/json", 'Authorization': '' },
data:{},
rejectUnauthorized: false
};
Thanks!
Hello,
When using the library with the useElectronNet=true
option, any request working with Electron 6.x is now throwing an error with electron 7.x, here it is :
FetchError: request to https://xxx/graphql failed, reason: net::ERR_INVALID_ARGUMENT
at ClientRequest.<anonymous> (/home/vincent/lls/lls-desktop/node_modules/electron-fetch/lib/index.js:1415:13)
at ClientRequest.emit (events.js:203:13)
at URLRequest../lib/browser/api/net.js.URLRequest._emitRequestEvent (electron/js2c/browser_init.js:2284:24)
Any hint on this?
Thanks,
Vincent
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.
Based on the logic in fetch-error the type
is system
, the code
member is no longer a number
but a string
In v1.7.0, you've introduced the signal
parameter as part of the RequestInit
interface. This property is marked as required in the index.d.ts
declaration file:
v1.6.0...v1.7.0
Please make it optional.
The type defintions for fetch
do not currently allow passing a Request
object to the fetch
method.
declare function fetch (
url: string,
options?: RequestInit
): Promise<Response>
should instead be
declare function fetch (
url: RequestInfo,
options?: RequestInit
): Promise<Response>
I've been working on a service that has recently had to be changed from HTTP to HTTPS. It needs to be set to read a client certificate from my local machine. Is there currently any way to pass along certificates in the options? I see that there is an example here that kind of asks what I want, but it currently has no answers.
See this issue.
The gist of it is that if you're overriding the Origin
header like this:
app.on('ready', () => {
session.defaultSession.webRequest.onBeforeSendHeaders(
(details: any, callback: any) => {
details.requestHeaders.Origin = 'www.some-random-origin.com';
callback({ cancel: false, requestHeaders: details.requestHeaders });
}
);
});
Calling [email protected]/3
with Electron v2 cases a crash:
const response = await fetch(url, { method: 'POST', body });
I have tried your library from a very basic test with Fiddle, and a backend that runs an HTTP API over named pipes on Windows (golang); So far, I have only been able to use got
to work: crc-org/crc#2618 but would prefer to use the Fetch API. What might I be missing?
Hi,
First of all, thank you for giving this wonderful module for us. the issue i am facing is i dont want electron fetch to redirect the requests. for an example, if i request http://google.com, it should return 307 internal redirect response but actually its returning 200 response. Please check my below code.
const { app, net, BrowserWindow } = require("electron");
const url = require("url");
const path = require("path");
const fetch = require("electron-fetch").default;
app.whenReady().then(() => {
let window = new BrowserWindow({
width: 1024,
height: 768,
webPreferences: { nodeIntegration: true, webviewTag: true },
resizable: false,
show: false,
});
let session = window.webContents.session;
session.clearCache();
session.clearAuthCache();
// session.webRequest.onBeforeRequest((details, callback) => {
// callback({ cancel: true })
// })
var body = {
method : "GET",
redirect : "manual",
useSessionCookies: true
}
const request = fetch("http://www.google.com/", body)
.then(async function (response) {
// var text = await response.text();
console.log(response.status);
})
.catch(function (err) {
console.log("error --", err);
});
});
Could you pls help me ?
Test with https://icanhazip.com/
which throws TypeError: 🦆 is not a legal HTTP header value
given it contains a header x-duck: 🦆
Version: 1.4.0
Hi @arantes555! Thanks for electron-fetch
.
In #1, I see how the options.user
and .password
can be supplied ahead of time. I'd like to discuss a more robust approach!
In my app, I'm currently handling the app.on('login')
event. I prompt the user with a "enter your creds" prompt, and supply the creds to the event's callback. This works great for all network activity on renderer threads.
It surprisingly does not work from the main threads (with electron-fetch
), because the electron.net
requests fire their own login
events, and aren't tied to the app 'login'
event. There's currently no way for me to handle the request's login
event, because electron-fetch
is handling it internally.
I'd love to discuss how this could be handled better!
I see the repository don't support abort signal which node-fetch
repository had supported. Can have this plan?
Is there a way to get the default request headers that are set before it is sent?
const res = await fetch(url, opts);
// something like
const requestHeaders = res.request.headers;
My team is piloting switching to this library over electron net lib and I wanted to compare our request headers with this library's request headers. Thanks.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.