关于
@adobe/fetch 一般遵守 获取 API 规格,执行 API 的子集。 然而,有一些明显的偏差:
Response.body返回节点.js 可读流。 。 。 .Response.blob()未执行。 使用Response.buffer()换句话说.Response.formData()未执行.- 饼干不是默认保存的. 然而,饼干可以通过操纵请求和响应头来取出并传递.
- 以下数值
fetch()选项cache已支持:'default'和'no-store'。所有其他值目前都被忽略. - 以下内容:
fetch()由于Node.js的性质,自此,选项被忽略@adobe/fetch没有网页的概念:mode, (中文(简体) ),referrer, (中文(简体) ),referrerPolicy, (中文(简体) ),integrity财务报告和审定财务报表credentials。 。 。 . - 这个
fetch()选项keepalive不被支持。 但你可以使用这个h1.keepAlive显示的上下文选项 这里。 。 。 .
@adobe/fetch 还支持以下非光谱扩展:
Response.buffer()返回节点.jsBuffer。 。 。 .Response.url包含跟踪方向调整时的最后url.- 这个
body可以发送到Request也可以是一个Readable节点.js流, aBuffer、字符串或普通对象. - 没有禁用的标题.
- 这个
Response对象有额外的属性httpVersion这是其中之一'1.0', (中文(简体) ),'1.1'或者说'2.0',取决于与服务器谈判的内容. - 这个
Response对象有额外的属性fromCache它决定了是否从缓存中检索到答复. - 这个
Response对象有额外的属性decoded决定响应机构是否自动解码(参见获取选项)decode页:1. Response.headers.plain()返回信头为普通对象.Response.headers.raw()返回页眉的内部/生代表,例如:Set-Cokkie标题以字符串值表示.- 获取选项
follow允许限制要遵循的重定向次数( 默认 :20) (中文(简体) ). - 获取选项
compress允许透明 gzip/deflate/br 内容编码( 默认 ):true) (中文(简体) ). - 获取选项
decode允许透明 gzip/deflate/br 内容解码( 默认 ):true) (中文(简体) ).
注意非标准获取选项已与 节点比对 在适当情况下.
特征
- 支持标准的合理子集 获取规格
- HTTP/1(1)和HTTP/2连接的透明处理
- RFC 7234 (英语) 符合的缓存
- 支助
gzip/deflate/br内容编码 - HTTP/2 请求和响应多功能支持
- HTTP/2 服务器 Push 支持(透明缓存和明确的收听器支持)
- 压倒性用户代理
- 低等HTTP/1.* 代理/连接选项支持(例如:.
keepAlive, (中文(简体) ),rejectUnauthorized(中文(简体) )
无害环境管理/刑事司法支助
这个软件包是本地的 无害环境管理 并且不再提供普通JS出口. 使用 3.x 版本,如果您还需要使用此软件包.
安装
说明数字 :
截至v4节点版本需要QQ 14.16.
$ npm install @adobe/fetch
API 密码
除了标准获取 API
fetch()RequestResponseHeadersBody
@adobe/fetch 暴露以下非光谱扩展:
context()- 创建新定制的 API 上下文reset()- 重置当前 API 上下文,即关闭待决会话/ sockets,清除内部缓存等.onPush()- 注册 HTTP/2 服务器 Push 听器offPush()- 取消先前注册的听众的登记onPush()clearCache()- 清除 HTTP 缓存( 紧急回复)cacheStats()- 返回缓存统计noCache()- 创建适合残疾人缓存的API环境(便利(中文(简体) )h1()- 创建定制的带有HTTP/1.1协议的API上下文(便利(中文(简体) )keepAlive()- 创建一个定制的API上下文,执行HTTP/1.1协议和持续连接(便利(中文(简体) )h1NoCache()- 建立一个定制的API环境,其中包含残疾缓存和执行HTTP/1.1协议(便利(中文(简体) )keepAliveNoCache()- 创建一个定制的API环境,与残疾缓存相接,并强制执行HTTP/1.1协议,与持续连接(便利(中文(简体) )createUrl()- 创建含有查询参数的URL(便利(中文(简体) )timeoutSignal()- 发出超时信号(便利(中文(简体) )
A. 背景情况
API上下文允许自定义执行的某些方面,并按API上下文提供内部结构的隔离(会话缓存,HTTP缓存等).
支持以下选项:
interface ContextOptions {
/**
* Value of `user-agent` request header
* @default 'adobe-fetch/<version>'
*/
userAgent?: string;
/**
* The maximum total size of the cached entries (in bytes). 0 disables caching.
* @default 100 * 1024 * 1024
*/
maxCacheSize?: number;
/**
* The protocols to be negotiated, in order of preference
* @default [ALPN_HTTP2, ALPN_HTTP1_1, ALPN_HTTP1_0]
*/
alpnProtocols?: ReadonlyArray< ALPNProtocol >;
/**
* How long (in milliseconds) should ALPN information be cached for a given host?
* @default 60 * 60 * 1000
*/
alpnCacheTTL?: number;
/**
* (HTTPS only, applies to HTTP/1.x and HTTP/2)
* If not false, the server certificate is verified against the list of supplied CAs. An 'error' event is emitted if verification fails; err.code contains the OpenSSL error code.
* @default true
*/
rejectUnauthorized?: boolean;
/**
* Maximum number of ALPN cache entries
* @default 100
*/
alpnCacheSize?: number;
h1?: Http1Options;
h2?: Http2Options;
};
interface Http1Options {
/**
* Keep sockets around in a pool to be used by other requests in the future.
* @default false
*/
keepAlive?: boolean;
/**
* When using HTTP KeepAlive, how often to send TCP KeepAlive packets over sockets being kept alive.
* Only relevant if keepAlive is set to true.
* @default 1000
*/
keepAliveMsecs?: number;
/**
* (HTTPS only)
* If not false, the server certificate is verified against the list of supplied CAs. An 'error' event is emitted if verification fails; err.code contains the OpenSSL error code.
* @default true
*/
rejectUnauthorized?: boolean;
/**
* (HTTPS only)
* Maximum number of TLS cached sessions. Use 0 to disable TLS session caching.
* @default 100
*/
maxCachedSessions?: number;
}
interface Http2Options {
/**
* Max idle time in milliseconds after which a session will be automatically closed.
* @default 5 * 60 * 1000
*/
idleSessionTimeout?: number;
/**
* Enable HTTP/2 Server Push?
* @default true
*/
enablePush?: boolean;
/**
* Max idle time in milliseconds after which a pushed stream will be automatically closed.
* @default 5000
*/
pushedStreamIdleTimeout?: number;
/**
* (HTTPS only)
* If not false, the server certificate is verified against the list of supplied CAs. An 'error' event is emitted if verification fails; err.code contains the OpenSSL error code.
* @default true
*/
rejectUnauthorized?: boolean;
};
常用示例
访问响应信头和其他元数据
import { fetch } from '@adobe/fetch';
const resp = await fetch('https://httpbin.org/get');
console.log(resp.ok);
console.log(resp.status);
console.log(resp.statusText);
console.log(resp.httpVersion);
console.log(resp.headers.plain());
console.log(resp.headers.get('content-type'));
获取 JSON
import { fetch } from '@adobe/fetch';
const resp = await fetch('https://httpbin.org/json');
const jsonData = await resp.json();
获取文本数据
import { fetch } from '@adobe/fetch';
const resp = await fetch('https://httpbin.org/');
const textData = await resp.text();
获取二进制数据
import { fetch } from '@adobe/fetch';
const resp = await fetch('https://httpbin.org//stream-bytes/65535');
const imageData = await resp.buffer();
指定超时 fetch 操作
使用 timeoutSignal(ms) 非光谱扩展:
import { fetch, timeoutSignal, AbortError } from '@adobe/fetch';
const signal = timeoutSignal(1000);
try {
const resp = await fetch('https://httpbin.org/json', { signal });
const jsonData = await resp.json();
} catch (err) {
if (err instanceof AbortError) {
console.log('fetch timed out after 1s');
}
} finally {
// avoid pending timers which prevent node process from exiting
signal.clear();
}
使用 AbortController数字 :
import { fetch, AbortController, AbortError } from '@adobe/fetch';
const controller = new AbortController();
const timerId = setTimeout(() => controller.abort(), 1000);
const { signal } = controller;
try {
const resp = await fetch('https://httpbin.org/json', { signal });
const jsonData = await resp.json();
} catch (err) {
if (err instanceof AbortError) {
console.log('fetch timed out after 1s');
}
} finally {
// avoid pending timers which prevent node process from exiting
clearTimeout(timerId);
}
流出图像
import { createWriteStream } from 'fs';
import { fetch } from '@adobe/fetch';
const resp = await fetch('https://httpbin.org/image/jpeg');
resp.body.pipe(createWriteStream('saved-image.jpg'));
JSON 员额
import { fetch } from '@adobe/fetch';
const method = 'POST';
const body = { foo: 'bar' };
const resp = await fetch('https://httpbin.org/post', { method, body });
后 JPEG 图像
import { createReadStream } from 'fs';
import { fetch } from '@adobe/fetch';
const method = 'POST';
const body = createReadStream('some-image.jpg');
const headers = { 'content-type': 'image/jpeg' };
const resp = await fetch('https://httpbin.org/post', { method, body, headers });
表格数据
import { FormData, Blob, File } from 'formdata-node'; // spec-compliant implementations
import { fileFromPath } from 'formdata-node/file-from-path'; // helper for creating File instance from disk file
import { fetch } from '@adobe/fetch';
const method = 'POST';
const fd = new FormData();
fd.set('field1', 'foo');
fd.set('field2', 'bar');
fd.set('blob', new Blob([0x68, 0x65, 0x6c, 0x69, 0x78, 0x2d, 0x66, 0x65, 0x74, 0x63, 0x68]));
fd.set('file', new File(['File content goes here'], 'file.txt'));
fd.set('other_file', await fileFromPath('/foo/bar.jpg', 'bar.jpg', { type: 'image/jpeg' }));
const resp = await fetch('https://httpbin.org/post', { method, body: fd });
获取查询参数对象
import { createUrl, fetch } from '@adobe/fetch';
const qs = {
fake: 'dummy',
foo: 'bar',
rumple: "stiltskin",
};
const resp = await fetch(createUrl('https://httpbin.org/json', qs));
或使用 URLSearchParams数字 :
import { fetch } from '@adobe/fetch';
const body = new URLSearchParams({
fake: 'dummy',
foo: 'bar',
rumple: "stiltskin",
});
const resp = await fetch('https://httpbin.org/json', { body });
缓存
答复 GET 财务报告和审定财务报表 HEAD 根据以下规则,请求默认缓存 RFC 7234 (英语)数字 :
import { fetch } from '@adobe/fetch';
const url = 'https://httpbin.org/cache/60'; // -> max-age=60 (seconds)
// send initial request, priming cache
let resp = await fetch(url);
assert(resp.ok);
assert(!resp.fromCache);
// re-send request and verify it's served from cache
resp = await fetch(url);
assert(resp.ok);
assert(resp.fromCache);
您可以禁用每个请求的缓存 cache: 'no-store' 选项 :
import { fetch } from '@adobe/fetch';
const resp = await fetch('https://httbin.org/', { cache: 'no-store' });
assert(resp.ok);
assert(!resp.fromCache);
您可以完全禁用缓存 :
import { noCache } from '@adobe/fetch';
const { fetch } = noCache();
高级使用示例
HTTP/2 服务器推
注意被推动的资源将自动透明地添加到缓存中. 不过,您可以添加一个将在每个被驱动(和缓存)的资源上被通知的听众 .
import { fetch, onPush } from '@adobe/fetch';
onPush((url, response) => console.log(`received server push: ${url} status ${response.status}`));
const resp = await fetch('https://nghttp2.org');
console.log(`Http version: ${resp.httpVersion}`);
使用h2c(http2 cleartext w/prior-knowledge)协议
import { fetch } from '@adobe/fetch';
const resp = await fetch('http2://nghttp2.org');
console.log(`Http version: ${resp.httpVersion}`);
强制 HTTP/1(1) 协议
import { h1 } from '@adobe/fetch';
const { fetch } = h1();
const resp = await fetch('https://nghttp2.org');
console.log(`Http version: ${resp.httpVersion}`);
HTTP/1.1 保持寿命
import { keepAlive } from '@adobe/fetch';
const { fetch } = keepAlive();
const resp = await fetch('https://httpbin.org/status/200');
console.log(`Connection: ${resp.headers.get('connection')}`); // -> keep-alive
提取 Set- Cookie 页眉
与浏览器不同, 您可以访问原始 Set-Cookie 手动使用页眉 Headers.raw()。这是一个 @adobe/fetch 仅限API.
import { fetch } from '@adobe/fetch';
const resp = await fetch('https://httpbin.org/cookies/set?a=1&b=2');
// returns an array of values, instead of a string of comma-separated values
console.log(resp.headers.raw()['set-cookie']);
自签名证书
import { context } from '@adobe/fetch';
const { fetch } = context({ rejectUnauthorized: false });
const resp = await fetch('https://localhost:8443/'); // a server using a self-signed certificate
设定缓存大小限制
import { context } from '@adobe/fetch';
const { fetch } = context({
maxCacheSize: 100 * 1024, // 100kb (Default: 100mb)
});
let resp = await fetch('https://httpbin.org/bytes/60000'); // ~60kb response
resp = await fetch('https://httpbin.org/bytes/50000'); // ~50kb response
console.log(cacheStats());
禁用缓存
import { noCache } from '@adobe/fetch';
const { fetch } = noCache();
let resp = await fetch('https://httpbin.org/cache/60'); // -> max-age=60 (seconds)
// re-fetch
resp = await fetch('https://httpbin.org/cache/60');
assert(!resp.fromCache);
设置自定义用户代理
import { context } from '@adobe/fetch';
const { fetch } = context({
userAgent: 'custom-fetch'
});
const resp = await fetch('https://httpbin.org//user-agent');
const json = await resp.json();
console.log(json['user-agent']);
更多实例
可在 测试源文件。 。 。 .
发展
构建
$ npm install
测试
$ npm test
林特
$ npm run lint
解决问题
您可以启用 @adobe/fetch 设置低级调试控制台输出 DEBUG 环境变量改为 adobe/fetch*,例如:
$ DEBUG=adobe/fetch* node test.js
这将产生类似于下列控制台外出:
...
adobe/fetch:core established TLS connection: #48 (www.nghttp2.org) +2s
adobe/fetch:core www.nghttp2.org -> h2 +0ms
adobe/fetch:h2 reusing socket #48 (www.nghttp2.org) +2s
adobe/fetch:h2 GET www.nghttp2.org/httpbin/user-agent +0ms
adobe/fetch:h2 session https://www.nghttp2.org established +1ms
adobe/fetch:h2 caching session https://www.nghttp2.org +0ms
adobe/fetch:h2 session https://www.nghttp2.org remoteSettings: {"headerTableSize":8192,"enablePush":true,"initialWindowSize":1048576,"maxFrameSize":16384,"maxConcurrentStreams":100,"maxHeaderListSize":4294967295,"maxHeaderSize":4294967295,"enableConnectProtocol":true} +263ms
adobe/fetch:h2 session https://www.nghttp2.org localSettings: {"headerTableSize":4096,"enablePush":true,"initialWindowSize":65535,"maxFrameSize":16384,"maxConcurrentStreams":4294967295,"maxHeaderListSize":4294967295,"maxHeaderSize":4294967295,"enableConnectProtocol":false} +0ms
adobe/fetch:h2 session https://www.nghttp2.org closed +6ms
adobe/fetch:h2 discarding cached session https://www.nghttp2.org +0ms
...
此外,您可以通过设置节点.js低等调试控制台输出 NODE_DEBUG 环境可适当变,例如:.
$ export NODE_DEBUG=http*,stream*
$ export DEBUG=adobe/fetch*
$ node test.js
注意:这将用高活字调试输出来淹没控制台.
致谢
感谢 节点比对 财务报告和审定财务报表 gi/牵引 提供坚实的执行参考.