ElectronJS是一个开源框架,用于使用能够在 Windows、macOS 和 Linux 操作系统上运行的 HTML、CSS 和 JavaScript 等 Web 技术构建跨平台原生桌面应用程序。它将 Chromium 引擎和NodeJS 组合成一个单一的运行时。
我们已经知道HTTP REST API在任何系统中的重要性。它们在全球范围内随处使用,互联网上有专门的资源,其中详细介绍了有关 HTTP REST API、标准和协议的所有内容。这里和这里提到了一些比较著名的 HTTP REST 资源。 NodeJS为通过内置模块和外部包进行 HTTP REST API 调用提供了广泛的支持。 NodeJS 为我们提供了内置的HTTP和HTTPS模块, NodeJS 中使用的一些最著名的 npm 包是axios 、 request和node-fetch 。由于 Electron 本质上是一个 Node 应用程序,因此上述所有包都得到支持,也可以在 Electron 中使用。有关如何在 Electron 中使用axios包进行 REST API 调用的简短教程,请参阅文章: ElectronJS 中的地理信息。除此之外,Electron 还为此提供了一个内置的网络模块。 net模块用于使用 Chromium 的本机网络库发出 HTTP/HTTPS REST 请求。本教程将演示了如何使用网模块在电子HTTP REST API调用和优势,净模块的功能。
我们假设您熟悉上述链接中介绍的先决条件。为了让 Electron 正常工作,需要在系统中预装node和npm 。
net模块是 Electron 中用于发出HTTP/HTTPS请求的客户端 API。如上所述,它类似于 NodeJS 的HTTP和HTTPS模块,但它使用 Chromium 的本机网络库而不是 NodeJS 实现,因此为 Web 代理提供更好的支持。 net模块的其他一些优点是:
- 自动管理系统代理配置,支持WPAD( Web Proxy Auto-Discovery )协议和代理pac配置文件。
- HTTPS 请求的自动隧道。
- 支持使用基本、摘要、NTLM、Kerberos 或协商身份验证方案对代理进行身份验证。
- 支持流量监控代理:用于访问控制和监控的类似 Fiddler 的代理。
- 项目结构:
示例:按照ElectronJS中的动态样式中给出的步骤设置基本的 Electron 应用程序。复制文章中提供的main.js文件和index.html文件的样板代码。还要执行package.json文件中提到的必要更改以启动电子应用程序。我们将继续使用相同的代码库构建我们的应用程序。设置 Electron 应用程序所需的基本步骤保持不变。
包.json:
{
"name": "electron-net",
"version": "1.0.0",
"description": "Making HTTP REST API Calls - net Module in Electron ",
"main": "main.js",
"scripts": {
"start": "electron ."
},
"keywords": [
"electron"
],
"author": "Radhesh Khanna",
"license": "ISC",
"dependencies": {
"electron": "^8.3.0"
}
}
输出:
Electron 中的HTTP REST API 调用 Electron 中的net模块是Main Process 的一部分。为了在Renderer Process 中导入和使用net模块,我们将使用 Electron远程模块。在本教程中,我们使用了httpbin.org ,它是一个简单且免费的 3rd Party HTTP REST 请求和响应服务。它提供了公开可用且不需要任何身份验证和授权的示例 HTTP REST API。它还通过示例 REST API 提供许多其他功能,例如身份验证测试、重定向、cookie、动态和随机数据等。我们将使用net模块向此服务发出 HTTP GET和 HTTP POST请求以进行演示。 net Module 中使用的所有组件,包括实例方法、实例事件和实例属性等设计和实现,都类似于 NodeJS 实现。这个net模块只能在app模块的ready事件发出后才能使用。所有操作系统平台和环境都支持此模块。
- index.html :在该文件中添加以下代码段。
html
Making HTTP REST API Calls
using net Module in Electron
javascript
const electron = require('electron');
// Importing the net Module from electron remote
const net = electron.remote.net;
var get = document.getElementById('get');
get.addEventListener('click', () => {
const request = net.request({
method: 'GET',
protocol: 'http:',
hostname: 'httpbin.org',
path: '/get',
redirect: 'follow'
});
request.on('response', (response) => {
console.log(`STATUS: ${response.statusCode}`);
console.log(`HEADERS: ${JSON.stringify(response.headers)}`);
response.on('data', (chunk) => {
console.log(`BODY: ${chunk}`)
});
});
request.on('finish', () => {
console.log('Request is Finished')
});
request.on('abort', () => {
console.log('Request is Aborted')
});
request.on('error', (error) => {
console.log(`ERROR: ${JSON.stringify(error)}`)
});
request.on('close', (error) => {
console.log('Last Transaction has occured')
});
request.setHeader('Content-Type', 'application/json');
request.end();
});
var post = document.getElementById('post');
post.addEventListener('click', () => {
var body = JSON.stringify({ key: 1 });
const request = net.request({
method: 'POST',
protocol: 'http:',
hostname: 'httpbin.org',
path: '/post',
redirect: 'follow'
});
request.on('response', (response) => {
console.log(`STATUS: ${response.statusCode}`);
console.log(`HEADERS: ${JSON.stringify(response.headers)}`);
response.on('data', (chunk) => {
console.log(`BODY: ${chunk}`)
});
});
request.on('finish', () => {
console.log('Request is Finished')
});
request.on('abort', () => {
console.log('Request is Aborted')
});
request.on('error', (error) => {
console.log(`ERROR: ${JSON.stringify(error)}`)
});
request.on('close', (error) => {
console.log('Last Transaction has occured')
});
request.setHeader('Content-Type', 'application/json');
request.write(body, 'utf-8');
request.end();
});
- index.js : Make Sample GET Request和Make Sample POST Request按钮还没有任何相关的功能。
javascript
const electron = require('electron');
// Importing the net Module from electron remote
const net = electron.remote.net;
var get = document.getElementById('get');
get.addEventListener('click', () => {
const request = net.request({
method: 'GET',
protocol: 'http:',
hostname: 'httpbin.org',
path: '/get',
redirect: 'follow'
});
request.on('response', (response) => {
console.log(`STATUS: ${response.statusCode}`);
console.log(`HEADERS: ${JSON.stringify(response.headers)}`);
response.on('data', (chunk) => {
console.log(`BODY: ${chunk}`)
});
});
request.on('finish', () => {
console.log('Request is Finished')
});
request.on('abort', () => {
console.log('Request is Aborted')
});
request.on('error', (error) => {
console.log(`ERROR: ${JSON.stringify(error)}`)
});
request.on('close', (error) => {
console.log('Last Transaction has occured')
});
request.setHeader('Content-Type', 'application/json');
request.end();
});
var post = document.getElementById('post');
post.addEventListener('click', () => {
var body = JSON.stringify({ key: 1 });
const request = net.request({
method: 'POST',
protocol: 'http:',
hostname: 'httpbin.org',
path: '/post',
redirect: 'follow'
});
request.on('response', (response) => {
console.log(`STATUS: ${response.statusCode}`);
console.log(`HEADERS: ${JSON.stringify(response.headers)}`);
response.on('data', (chunk) => {
console.log(`BODY: ${chunk}`)
});
});
request.on('finish', () => {
console.log('Request is Finished')
});
request.on('abort', () => {
console.log('Request is Aborted')
});
request.on('error', (error) => {
console.log(`ERROR: ${JSON.stringify(error)}`)
});
request.on('close', (error) => {
console.log('Last Transaction has occured')
});
request.setHeader('Content-Type', 'application/json');
request.write(body, 'utf-8');
request.end();
});
说明: net模块仅支持一种 Instance 方法。这个net.request(options) Instance 方法使用ClientRequest Instance。每次调用此 Instance 方法都会创建并返回一个新的 ClientRequest实例。此实例方法用于根据选项对象中指定的协议方案发出安全和不安全的 HTTP 请求。有关net.request()方法的更多详细信息。它接受以下参数。
- 选项:对象/字符串此参数可以接收一个对象或一个简单的字符串值。这表示ClientRequest Constructor 选项并直接转发到ClientRequest实例。如果此参数是String ,则将其解释为请求URL 。如果它是一个object ,则期望完全指定ClientRequest构造函数支持的 HTTP 请求。
上面代码中进一步使用的所有实例方法、事件和属性都是ClientRequest实例的一部分。 ClientRequest实例发出实际的 HTTP/HTTPS 请求,它实现了Writable Stream接口,因此是一个EventEmitter 。下面给出了ClientRequest构造函数选项的详细说明。它支持以下参数:
- Method:该参数指定HTTP请求方法。它默认为 HTTP GET方法。
- URL:此参数指定 HTTP 请求 URL。此参数必须以绝对形式提供,协议指定为http:或https: 。如果未提供协议,则不会设置默认值,因此 HTTP 请求将失败。对于简单的 HTTP GET请求,指定方法和url参数就足以进行调用。 URL 参数也可以进一步分解为其他参数。
- Session:该参数指定与请求相关联的 Electron Session Instance。
- 分区:字符串(可选)此参数指定从与请求关联的会话实例派生的分区名称。默认值为空字符串。如果session参数和partition参数一起定义,则session参数优先。因此,如果明确指定并传递会话实例,则忽略分区参数。
- useSessionCookies:此参数指定是否使用源自会话实例的此请求发送cookie 。这将使网络模块请求的 cookie 行为与 NodeJS获取请求相匹配。默认值为false 。
- Protocol: String (可选)此参数指定HTTP 请求的协议方案。当前支持的值为http:或https: 。默认值为http: 。该参数严格遵循URL模块中描述的 NodeJS 模型。
- 主机:此参数指定服务器主机,即作为主机名参数和端口号参数的串联提供的基本 URL,格式为主机名:端口,如 URL 标准所遵循。该参数严格遵循URL模块中描述的 NodeJS 模型。
- 主机名:字符串(可选)此参数指定服务器主机名。它可以是DNS (域名服务)服务器名称或IP地址。该参数严格遵循URL模块中描述的 NodeJS 模型。
- 端口:整数(可选)此参数指定服务器的侦听端口号。该参数严格遵循URL模块中描述的 NodeJS 模型。
- Path: String (可选)此参数指定请求 URL 的路径部分,即基本 URL主机名/主机/端口参数之后的部分。此参数可以包含需要传递给 REST API 的查询字符串参数或路径参数。查询字符串参数在?在 URL 中使用键值对。该参数严格遵循URL模块中描述的 NodeJS 模型。
- redirect: String (可选)此参数定义 HTTP 请求的重定向模式。它可以包含以下任何值:
- follow遵循 HTTP 请求的默认行为。
- error中止 HTTP 请求中的任何或所有重定向。
- 手动取消重定向,除非在发出重定向实例事件时同步调用request.followRedirect()实例方法。
ClientRequest实例支持以下实例事件。
- response: Event处理 HTTP 请求并从 REST API 返回响应时会发出此 Instance 事件。此实例事件在网络模块对象(在本例中为请求对象)上发出。它返回单个响应:代表传入 HTTP 响应数据包的对象,其中包括 HTTP 状态、HTTP 标头、HTTP 正文等。
- 完成:事件此实例事件在收到 HTTP 请求数据的最后一个块并将其写入请求对象后立即发出。
- abort: Event当 HTTP请求中止时,会发出此 Instance 事件。如果请求已经关闭,即关闭实例事件已被触发,则不会发出此事件。
- error: Event当net模块无法发出 HTTP 网络请求时会发出此 Instance 事件,这可能由于各种原因(例如网关错误、无网络连接等)而发生。通常,当请求对象发出错误Instance 事件时,关闭实例事件也紧随其后发出,并且不会提供响应对象。此事件返回一个错误对象,其中包含有关 HTTP 请求失败的一些信息,例如 HTTP 状态代码等。
- close: Event此实例事件作为握手完成后 HTTP 请求-响应事务中的最后一个事件发出。此事件表示不会在请求或响应对象上发出进一步的事件,并将事务标记为完成。
此外, ClientRequest实例支持单个实例属性。
- request.chunkedEncoding这个实例属性接受一个布尔值。此属性指定 HTTP 请求是否将使用 HTTP 分块传输编码。此属性只能在第一次写入操作之前设置,即在request.write()实例方法之前设置,因为 HTTP 标头还没有放在线路上。在第一次写入后尝试设置chunkedEncoding属性将引发错误。默认值为假。如果您需要发送大型请求正文,强烈建议使用chunkedEncoding Instance 属性作为true ,因为数据将以小块流式传输,而不是在 Electron 进程内存中进行内部缓冲。
基于ClientRequest构造函数选项以及我们迄今为止所涵盖的 Instance 事件和属性,我们注意到缺少一些 HTTP 请求的关键参数,例如 HTTP POST 请求的标头和正文。这是因为这些参数已从 Electron 以前版本的构造函数选项对象中删除,并在较新版本中作为单独的 Instance 方法添加。 ClientRequest实例支持以下实例方法。
- request.setHeader(name, value)此实例方法用于添加额外的 HTTP 标头或覆盖除默认 HTTP 标头之外的现有标头。标题名称将按原样使用,而不用小写。它只能在第一次写入之前调用,即在调用request.write()实例方法之前。在第一次写入后调用此方法将引发错误。如果传入的值不是字符串,则在设置 HTTP 请求包中的 headers 之前,将调用其toString()方法获取最终值。
- request.getHeader(name)这个 Instance 方法用于返回name: String参数中传递的 header 的值。返回值是一个包含该值的字符串。
- request.removeHeader(name)这个 Instance 方法用于移除name: String参数中传递的标题。它只能在第一次写入之前调用,即在调用request.write()实例方法之前。在第一次写入后调用此方法将引发错误。此方法不返回任何值。
- request.write(chunk, encoding, callback)这个 Instance 方法向请求体添加了一个数据块。这种情况的方法是我们设定的HTTP POST请求的主体。第一个写操作可能会导致请求头被在线发送。第一次写操作后,不允许添加或删除自定义标头。它接受以下参数:
- 块:字符串/缓冲区请求正文数据的块。如果是String值,则使用encoding参数中指定的编码在内部将其转换为Buffer 。
- encoding: String (可选)上面提到的这个参数,用于将chunk参数String值转换成一个Buffer对象。用于编码的默认值是utf-8 ,这是通过网络传输 HTTP 请求时使用的默认编码。
- callback: 函数 (可选)这个回调函数本质上是一个虚拟函数,为了保持与 NodeJS API 的相似性而引入的。在块内容传送到 Chromium 网络层后异步调用它。
- request.abort()如果调用此实例方法,则会取消正在进行的 HTTP 事务。如果close Instance 事件已经发出,则此 Instance 方法将不起作用。否则会发出中止和关闭实例事件。此外,如果有一个正在进行的响应对象,它也会发出abort Instance 事件。
- request.followRedirect()此实例方法继续并强制通过 HTTP 请求的任何挂起重定向。此 Instance 方法只能在发出重定向Instance 事件时调用。
此时,在启动 Electron 应用程序时,我们应该能够对httpbin.org HTTP 服务、 GET和POST示例 API 进行成功的 HTTP REST API 调用,并检查我们从这些 API 获得的响应。
输出: