mirror of
https://github.com/denoland/deno.git
synced 2025-03-03 17:34:47 -05:00
refactor(node): reimplement http client (#19122)
This commit reimplements most of "node:http" client APIs using "ext/fetch". There is some duplicated code and two removed Node compat tests that will be fixed in follow up PRs. --------- Co-authored-by: Bartek Iwańczuk <biwanczuk@gmail.com>
This commit is contained in:
parent
a22388bbd1
commit
867a6d3032
14 changed files with 1702 additions and 1163 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -1155,6 +1155,7 @@ dependencies = [
|
||||||
"cbc",
|
"cbc",
|
||||||
"data-encoding",
|
"data-encoding",
|
||||||
"deno_core",
|
"deno_core",
|
||||||
|
"deno_fetch",
|
||||||
"deno_fs",
|
"deno_fs",
|
||||||
"deno_media_type",
|
"deno_media_type",
|
||||||
"deno_npm",
|
"deno_npm",
|
||||||
|
@ -1183,6 +1184,7 @@ dependencies = [
|
||||||
"pbkdf2",
|
"pbkdf2",
|
||||||
"rand",
|
"rand",
|
||||||
"regex",
|
"regex",
|
||||||
|
"reqwest",
|
||||||
"ring",
|
"ring",
|
||||||
"ripemd",
|
"ripemd",
|
||||||
"rsa",
|
"rsa",
|
||||||
|
|
|
@ -362,11 +362,13 @@
|
||||||
// failing
|
// failing
|
||||||
//"test-http-client-set-timeout.js",
|
//"test-http-client-set-timeout.js",
|
||||||
"test-http-localaddress.js",
|
"test-http-localaddress.js",
|
||||||
"test-http-outgoing-buffer.js",
|
// TODO(bartlomieju): temporarily disabled while we iterate on the HTTP client
|
||||||
|
// "test-http-outgoing-buffer.js",
|
||||||
"test-http-outgoing-internal-headernames-getter.js",
|
"test-http-outgoing-internal-headernames-getter.js",
|
||||||
"test-http-outgoing-internal-headernames-setter.js",
|
"test-http-outgoing-internal-headernames-setter.js",
|
||||||
"test-http-outgoing-internal-headers.js",
|
"test-http-outgoing-internal-headers.js",
|
||||||
"test-http-outgoing-message-inheritance.js",
|
// TODO(bartlomieju): temporarily disabled while we iterate on the HTTP client
|
||||||
|
// "test-http-outgoing-message-inheritance.js",
|
||||||
"test-http-outgoing-renderHeaders.js",
|
"test-http-outgoing-renderHeaders.js",
|
||||||
"test-http-outgoing-settimeout.js",
|
"test-http-outgoing-settimeout.js",
|
||||||
"test-net-access-byteswritten.js",
|
"test-net-access-byteswritten.js",
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
// deno-fmt-ignore-file
|
|
||||||
// deno-lint-ignore-file
|
|
||||||
|
|
||||||
// Copyright Joyent and Node contributors. All rights reserved. MIT license.
|
|
||||||
// Taken from Node 18.12.1
|
|
||||||
// This file is automatically generated by "node/_tools/setup.ts". Do not modify this file manually
|
|
||||||
|
|
||||||
// Flags: --expose-internals
|
|
||||||
'use strict';
|
|
||||||
require('../common');
|
|
||||||
const assert = require('assert');
|
|
||||||
const { getDefaultHighWaterMark } = require('internal/streams/state');
|
|
||||||
|
|
||||||
const http = require('http');
|
|
||||||
const OutgoingMessage = http.OutgoingMessage;
|
|
||||||
|
|
||||||
const msg = new OutgoingMessage();
|
|
||||||
msg._implicitHeader = function() {};
|
|
||||||
|
|
||||||
// Writes should be buffered until highwatermark
|
|
||||||
// even when no socket is assigned.
|
|
||||||
|
|
||||||
assert.strictEqual(msg.write('asd'), true);
|
|
||||||
while (msg.write('asd'));
|
|
||||||
const highwatermark = msg.writableHighWaterMark || getDefaultHighWaterMark();
|
|
||||||
assert(msg.outputSize >= highwatermark);
|
|
|
@ -1,43 +0,0 @@
|
||||||
// deno-fmt-ignore-file
|
|
||||||
// deno-lint-ignore-file
|
|
||||||
|
|
||||||
// Copyright Joyent and Node contributors. All rights reserved. MIT license.
|
|
||||||
// Taken from Node 18.12.1
|
|
||||||
// This file is automatically generated by "node/_tools/setup.ts". Do not modify this file manually
|
|
||||||
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
const common = require('../common');
|
|
||||||
const { OutgoingMessage } = require('http');
|
|
||||||
const { Writable } = require('stream');
|
|
||||||
const assert = require('assert');
|
|
||||||
|
|
||||||
// Check that OutgoingMessage can be used without a proper Socket
|
|
||||||
// Refs: https://github.com/nodejs/node/issues/14386
|
|
||||||
// Refs: https://github.com/nodejs/node/issues/14381
|
|
||||||
|
|
||||||
class Response extends OutgoingMessage {
|
|
||||||
_implicitHeader() {}
|
|
||||||
}
|
|
||||||
|
|
||||||
const res = new Response();
|
|
||||||
|
|
||||||
let firstChunk = true;
|
|
||||||
|
|
||||||
const ws = new Writable({
|
|
||||||
write: common.mustCall((chunk, encoding, callback) => {
|
|
||||||
if (firstChunk) {
|
|
||||||
assert(chunk.toString().endsWith('hello world'));
|
|
||||||
firstChunk = false;
|
|
||||||
} else {
|
|
||||||
assert.strictEqual(chunk.length, 0);
|
|
||||||
}
|
|
||||||
setImmediate(callback);
|
|
||||||
}, 2)
|
|
||||||
});
|
|
||||||
|
|
||||||
res.socket = ws;
|
|
||||||
ws._httpMessage = res;
|
|
||||||
res.connection = ws;
|
|
||||||
|
|
||||||
res.end('hello world');
|
|
|
@ -185,6 +185,7 @@ Deno.test("[node/http] server can respond with 101, 204, 205, 304 status", async
|
||||||
|
|
||||||
Deno.test("[node/http] request default protocol", async () => {
|
Deno.test("[node/http] request default protocol", async () => {
|
||||||
const promise = deferred<void>();
|
const promise = deferred<void>();
|
||||||
|
const promise2 = deferred<void>();
|
||||||
const server = http.createServer((_, res) => {
|
const server = http.createServer((_, res) => {
|
||||||
res.end("ok");
|
res.end("ok");
|
||||||
});
|
});
|
||||||
|
@ -198,6 +199,7 @@ Deno.test("[node/http] request default protocol", async () => {
|
||||||
server.close();
|
server.close();
|
||||||
});
|
});
|
||||||
assertEquals(res.statusCode, 200);
|
assertEquals(res.statusCode, 200);
|
||||||
|
promise2.resolve();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
req.end();
|
req.end();
|
||||||
|
@ -206,6 +208,7 @@ Deno.test("[node/http] request default protocol", async () => {
|
||||||
promise.resolve();
|
promise.resolve();
|
||||||
});
|
});
|
||||||
await promise;
|
await promise;
|
||||||
|
await promise2;
|
||||||
});
|
});
|
||||||
|
|
||||||
Deno.test("[node/http] request with headers", async () => {
|
Deno.test("[node/http] request with headers", async () => {
|
||||||
|
@ -292,32 +295,6 @@ Deno.test("[node/http] http.IncomingMessage can be created without url", () => {
|
||||||
});
|
});
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Deno.test("[node/http] set http.IncomingMessage.statusMessage", () => {
|
|
||||||
// deno-lint-ignore no-explicit-any
|
|
||||||
const message = new (http as any).IncomingMessageForClient(
|
|
||||||
new Response(null, { status: 404, statusText: "Not Found" }),
|
|
||||||
{
|
|
||||||
encrypted: true,
|
|
||||||
readable: false,
|
|
||||||
remoteAddress: "foo",
|
|
||||||
address() {
|
|
||||||
return { port: 443, family: "IPv4" };
|
|
||||||
},
|
|
||||||
// deno-lint-ignore no-explicit-any
|
|
||||||
end(_cb: any) {
|
|
||||||
return this;
|
|
||||||
},
|
|
||||||
// deno-lint-ignore no-explicit-any
|
|
||||||
destroy(_e: any) {
|
|
||||||
return;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
assertEquals(message.statusMessage, "Not Found");
|
|
||||||
message.statusMessage = "boom";
|
|
||||||
assertEquals(message.statusMessage, "boom");
|
|
||||||
});
|
|
||||||
|
|
||||||
Deno.test("[node/http] send request with non-chunked body", async () => {
|
Deno.test("[node/http] send request with non-chunked body", async () => {
|
||||||
let requestHeaders: Headers;
|
let requestHeaders: Headers;
|
||||||
let requestBody = "";
|
let requestBody = "";
|
||||||
|
|
|
@ -66,7 +66,7 @@ pub use reqwest;
|
||||||
|
|
||||||
pub use fs_fetch_handler::FsFetchHandler;
|
pub use fs_fetch_handler::FsFetchHandler;
|
||||||
|
|
||||||
use crate::byte_stream::MpscByteStream;
|
pub use crate::byte_stream::MpscByteStream;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Options {
|
pub struct Options {
|
||||||
|
@ -186,9 +186,9 @@ pub fn get_declaration() -> PathBuf {
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct FetchReturn {
|
pub struct FetchReturn {
|
||||||
request_rid: ResourceId,
|
pub request_rid: ResourceId,
|
||||||
request_body_rid: Option<ResourceId>,
|
pub request_body_rid: Option<ResourceId>,
|
||||||
cancel_handle_rid: Option<ResourceId>,
|
pub cancel_handle_rid: Option<ResourceId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_or_create_client_from_state(
|
pub fn get_or_create_client_from_state(
|
||||||
|
@ -302,7 +302,7 @@ where
|
||||||
}
|
}
|
||||||
Some(data) => {
|
Some(data) => {
|
||||||
// If a body is passed, we use it, and don't return a body for streaming.
|
// If a body is passed, we use it, and don't return a body for streaming.
|
||||||
request = request.body(Vec::from(&*data));
|
request = request.body(data.to_vec());
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -400,12 +400,12 @@ where
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct FetchResponse {
|
pub struct FetchResponse {
|
||||||
status: u16,
|
pub status: u16,
|
||||||
status_text: String,
|
pub status_text: String,
|
||||||
headers: Vec<(ByteString, ByteString)>,
|
pub headers: Vec<(ByteString, ByteString)>,
|
||||||
url: String,
|
pub url: String,
|
||||||
response_rid: ResourceId,
|
pub response_rid: ResourceId,
|
||||||
content_length: Option<u64>,
|
pub content_length: Option<u64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[op]
|
#[op]
|
||||||
|
@ -462,8 +462,8 @@ pub async fn op_fetch_send(
|
||||||
|
|
||||||
type CancelableResponseResult = Result<Result<Response, AnyError>, Canceled>;
|
type CancelableResponseResult = Result<Result<Response, AnyError>, Canceled>;
|
||||||
|
|
||||||
struct FetchRequestResource(
|
pub struct FetchRequestResource(
|
||||||
Pin<Box<dyn Future<Output = CancelableResponseResult>>>,
|
pub Pin<Box<dyn Future<Output = CancelableResponseResult>>>,
|
||||||
);
|
);
|
||||||
|
|
||||||
impl Resource for FetchRequestResource {
|
impl Resource for FetchRequestResource {
|
||||||
|
@ -472,7 +472,7 @@ impl Resource for FetchRequestResource {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct FetchCancelHandle(Rc<CancelHandle>);
|
pub struct FetchCancelHandle(pub Rc<CancelHandle>);
|
||||||
|
|
||||||
impl Resource for FetchCancelHandle {
|
impl Resource for FetchCancelHandle {
|
||||||
fn name(&self) -> Cow<str> {
|
fn name(&self) -> Cow<str> {
|
||||||
|
@ -485,8 +485,8 @@ impl Resource for FetchCancelHandle {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct FetchRequestBodyResource {
|
pub struct FetchRequestBodyResource {
|
||||||
body: AsyncRefCell<mpsc::Sender<Option<bytes::Bytes>>>,
|
pub body: AsyncRefCell<mpsc::Sender<Option<bytes::Bytes>>>,
|
||||||
cancel: CancelHandle,
|
pub cancel: CancelHandle,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Resource for FetchRequestBodyResource {
|
impl Resource for FetchRequestBodyResource {
|
||||||
|
@ -537,10 +537,10 @@ impl Resource for FetchRequestBodyResource {
|
||||||
type BytesStream =
|
type BytesStream =
|
||||||
Pin<Box<dyn Stream<Item = Result<bytes::Bytes, std::io::Error>> + Unpin>>;
|
Pin<Box<dyn Stream<Item = Result<bytes::Bytes, std::io::Error>> + Unpin>>;
|
||||||
|
|
||||||
struct FetchResponseBodyResource {
|
pub struct FetchResponseBodyResource {
|
||||||
reader: AsyncRefCell<Peekable<BytesStream>>,
|
pub reader: AsyncRefCell<Peekable<BytesStream>>,
|
||||||
cancel: CancelHandle,
|
pub cancel: CancelHandle,
|
||||||
size: Option<u64>,
|
pub size: Option<u64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Resource for FetchResponseBodyResource {
|
impl Resource for FetchResponseBodyResource {
|
||||||
|
@ -590,8 +590,8 @@ impl Resource for FetchResponseBodyResource {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct HttpClientResource {
|
pub struct HttpClientResource {
|
||||||
client: Client,
|
pub client: Client,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Resource for HttpClientResource {
|
impl Resource for HttpClientResource {
|
||||||
|
|
|
@ -18,6 +18,7 @@ aes.workspace = true
|
||||||
cbc.workspace = true
|
cbc.workspace = true
|
||||||
data-encoding = "2.3.3"
|
data-encoding = "2.3.3"
|
||||||
deno_core.workspace = true
|
deno_core.workspace = true
|
||||||
|
deno_fetch.workspace = true
|
||||||
deno_fs.workspace = true
|
deno_fs.workspace = true
|
||||||
deno_media_type.workspace = true
|
deno_media_type.workspace = true
|
||||||
deno_npm.workspace = true
|
deno_npm.workspace = true
|
||||||
|
@ -46,6 +47,7 @@ path-clean = "=0.1.0"
|
||||||
pbkdf2 = "0.12.1"
|
pbkdf2 = "0.12.1"
|
||||||
rand.workspace = true
|
rand.workspace = true
|
||||||
regex.workspace = true
|
regex.workspace = true
|
||||||
|
reqwest.workspace = true
|
||||||
ring.workspace = true
|
ring.workspace = true
|
||||||
ripemd = "0.1.3"
|
ripemd = "0.1.3"
|
||||||
rsa.workspace = true
|
rsa.workspace = true
|
||||||
|
|
|
@ -206,6 +206,7 @@ deno_core::extension!(deno_node,
|
||||||
ops::zlib::op_zlib_write_async,
|
ops::zlib::op_zlib_write_async,
|
||||||
ops::zlib::op_zlib_init,
|
ops::zlib::op_zlib_init,
|
||||||
ops::zlib::op_zlib_reset,
|
ops::zlib::op_zlib_reset,
|
||||||
|
ops::http::op_node_http_request,
|
||||||
op_node_build_os,
|
op_node_build_os,
|
||||||
ops::require::op_require_init_paths,
|
ops::require::op_require_init_paths,
|
||||||
ops::require::op_require_node_module_paths<P>,
|
ops::require::op_require_node_module_paths<P>,
|
||||||
|
|
101
ext/node/ops/http.rs
Normal file
101
ext/node/ops/http.rs
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
|
use deno_core::error::type_error;
|
||||||
|
use deno_core::error::AnyError;
|
||||||
|
use deno_core::op;
|
||||||
|
use deno_core::url::Url;
|
||||||
|
use deno_core::AsyncRefCell;
|
||||||
|
use deno_core::ByteString;
|
||||||
|
use deno_core::CancelFuture;
|
||||||
|
use deno_core::CancelHandle;
|
||||||
|
use deno_core::OpState;
|
||||||
|
use deno_fetch::get_or_create_client_from_state;
|
||||||
|
use deno_fetch::FetchCancelHandle;
|
||||||
|
use deno_fetch::FetchRequestBodyResource;
|
||||||
|
use deno_fetch::FetchRequestResource;
|
||||||
|
use deno_fetch::FetchReturn;
|
||||||
|
use deno_fetch::HttpClientResource;
|
||||||
|
use deno_fetch::MpscByteStream;
|
||||||
|
use reqwest::header::HeaderMap;
|
||||||
|
use reqwest::header::HeaderName;
|
||||||
|
use reqwest::header::HeaderValue;
|
||||||
|
use reqwest::header::CONTENT_LENGTH;
|
||||||
|
use reqwest::Body;
|
||||||
|
use reqwest::Method;
|
||||||
|
|
||||||
|
#[op]
|
||||||
|
pub fn op_node_http_request(
|
||||||
|
state: &mut OpState,
|
||||||
|
method: ByteString,
|
||||||
|
url: String,
|
||||||
|
headers: Vec<(ByteString, ByteString)>,
|
||||||
|
client_rid: Option<u32>,
|
||||||
|
has_body: bool,
|
||||||
|
) -> Result<FetchReturn, AnyError> {
|
||||||
|
let client = if let Some(rid) = client_rid {
|
||||||
|
let r = state.resource_table.get::<HttpClientResource>(rid)?;
|
||||||
|
r.client.clone()
|
||||||
|
} else {
|
||||||
|
get_or_create_client_from_state(state)?
|
||||||
|
};
|
||||||
|
|
||||||
|
let method = Method::from_bytes(&method)?;
|
||||||
|
let url = Url::parse(&url)?;
|
||||||
|
|
||||||
|
let mut header_map = HeaderMap::new();
|
||||||
|
for (key, value) in headers {
|
||||||
|
let name = HeaderName::from_bytes(&key)
|
||||||
|
.map_err(|err| type_error(err.to_string()))?;
|
||||||
|
let v = HeaderValue::from_bytes(&value)
|
||||||
|
.map_err(|err| type_error(err.to_string()))?;
|
||||||
|
|
||||||
|
header_map.append(name, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut request = client.request(method.clone(), url).headers(header_map);
|
||||||
|
|
||||||
|
let request_body_rid = if has_body {
|
||||||
|
// If no body is passed, we return a writer for streaming the body.
|
||||||
|
let (stream, tx) = MpscByteStream::new();
|
||||||
|
|
||||||
|
request = request.body(Body::wrap_stream(stream));
|
||||||
|
|
||||||
|
let request_body_rid = state.resource_table.add(FetchRequestBodyResource {
|
||||||
|
body: AsyncRefCell::new(tx),
|
||||||
|
cancel: CancelHandle::default(),
|
||||||
|
});
|
||||||
|
|
||||||
|
Some(request_body_rid)
|
||||||
|
} else {
|
||||||
|
// POST and PUT requests should always have a 0 length content-length,
|
||||||
|
// if there is no body. https://fetch.spec.whatwg.org/#http-network-or-cache-fetch
|
||||||
|
if matches!(method, Method::POST | Method::PUT) {
|
||||||
|
request = request.header(CONTENT_LENGTH, HeaderValue::from(0));
|
||||||
|
}
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let cancel_handle = CancelHandle::new_rc();
|
||||||
|
let cancel_handle_ = cancel_handle.clone();
|
||||||
|
|
||||||
|
let fut = async move {
|
||||||
|
request
|
||||||
|
.send()
|
||||||
|
.or_cancel(cancel_handle_)
|
||||||
|
.await
|
||||||
|
.map(|res| res.map_err(|err| type_error(err.to_string())))
|
||||||
|
};
|
||||||
|
|
||||||
|
let request_rid = state
|
||||||
|
.resource_table
|
||||||
|
.add(FetchRequestResource(Box::pin(fut)));
|
||||||
|
|
||||||
|
let cancel_handle_rid =
|
||||||
|
state.resource_table.add(FetchCancelHandle(cancel_handle));
|
||||||
|
|
||||||
|
Ok(FetchReturn {
|
||||||
|
request_rid,
|
||||||
|
request_body_rid,
|
||||||
|
cancel_handle_rid: Some(cancel_handle_rid),
|
||||||
|
})
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
pub mod crypto;
|
pub mod crypto;
|
||||||
|
pub mod http;
|
||||||
pub mod idna;
|
pub mod idna;
|
||||||
pub mod require;
|
pub mod require;
|
||||||
pub mod v8;
|
pub mod v8;
|
||||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -4,15 +4,11 @@
|
||||||
import { notImplemented } from "ext:deno_node/_utils.ts";
|
import { notImplemented } from "ext:deno_node/_utils.ts";
|
||||||
import { urlToHttpOptions } from "ext:deno_node/internal/url.ts";
|
import { urlToHttpOptions } from "ext:deno_node/internal/url.ts";
|
||||||
import {
|
import {
|
||||||
Agent as HttpAgent,
|
|
||||||
ClientRequest,
|
ClientRequest,
|
||||||
IncomingMessageForClient as IncomingMessage,
|
IncomingMessageForClient as IncomingMessage,
|
||||||
type RequestOptions,
|
type RequestOptions,
|
||||||
} from "ext:deno_node/http.ts";
|
} from "ext:deno_node/http.ts";
|
||||||
import type { Socket } from "ext:deno_node/net.ts";
|
import { Agent as HttpAgent } from "ext:deno_node/_http_agent.mjs";
|
||||||
|
|
||||||
export class Agent extends HttpAgent {
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Server {
|
export class Server {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
@ -53,41 +49,61 @@ export function get(...args: any[]) {
|
||||||
return req;
|
return req;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const globalAgent = undefined;
|
export class Agent extends HttpAgent {
|
||||||
|
constructor(options) {
|
||||||
|
super(options);
|
||||||
|
this.defaultPort = 443;
|
||||||
|
this.protocol = "https:";
|
||||||
|
this.maxCachedSessions = this.options.maxCachedSessions;
|
||||||
|
if (this.maxCachedSessions === undefined) {
|
||||||
|
this.maxCachedSessions = 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._sessionCache = {
|
||||||
|
map: {},
|
||||||
|
list: [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const globalAgent = new Agent({
|
||||||
|
keepAlive: true,
|
||||||
|
scheduling: "lifo",
|
||||||
|
timeout: 5000,
|
||||||
|
});
|
||||||
|
|
||||||
/** HttpsClientRequest class loosely follows http.ClientRequest class API. */
|
/** HttpsClientRequest class loosely follows http.ClientRequest class API. */
|
||||||
class HttpsClientRequest extends ClientRequest {
|
class HttpsClientRequest extends ClientRequest {
|
||||||
override defaultProtocol = "https:";
|
override defaultProtocol = "https:";
|
||||||
override async _createCustomClient(): Promise<
|
override _getClient(): Deno.HttpClient | undefined {
|
||||||
Deno.HttpClient | undefined
|
|
||||||
> {
|
|
||||||
if (caCerts === null) {
|
if (caCerts === null) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
if (caCerts !== undefined) {
|
if (caCerts !== undefined) {
|
||||||
return Deno.createHttpClient({ caCerts });
|
return Deno.createHttpClient({ caCerts });
|
||||||
}
|
}
|
||||||
const status = await Deno.permissions.query({
|
// const status = await Deno.permissions.query({
|
||||||
name: "env",
|
// name: "env",
|
||||||
variable: "NODE_EXTRA_CA_CERTS",
|
// variable: "NODE_EXTRA_CA_CERTS",
|
||||||
});
|
// });
|
||||||
if (status.state !== "granted") {
|
// if (status.state !== "granted") {
|
||||||
caCerts = null;
|
// caCerts = null;
|
||||||
return undefined;
|
// return undefined;
|
||||||
}
|
// }
|
||||||
const certFilename = Deno.env.get("NODE_EXTRA_CA_CERTS");
|
const certFilename = Deno.env.get("NODE_EXTRA_CA_CERTS");
|
||||||
if (!certFilename) {
|
if (!certFilename) {
|
||||||
caCerts = null;
|
caCerts = null;
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
const caCert = await Deno.readTextFile(certFilename);
|
const caCert = Deno.readTextFileSync(certFilename);
|
||||||
caCerts = [caCert];
|
caCerts = [caCert];
|
||||||
return Deno.createHttpClient({ caCerts });
|
return Deno.createHttpClient({ caCerts });
|
||||||
}
|
}
|
||||||
|
|
||||||
override _createSocket(): Socket {
|
/*override _createSocket(): Socket {
|
||||||
// deno-lint-ignore no-explicit-any
|
// deno-lint-ignore no-explicit-any
|
||||||
return { authorized: true } as any;
|
return { authorized: true } as any;
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Makes a request to an https server. */
|
/** Makes a request to an https server. */
|
||||||
|
@ -107,15 +123,21 @@ export function request(
|
||||||
// deno-lint-ignore no-explicit-any
|
// deno-lint-ignore no-explicit-any
|
||||||
export function request(...args: any[]) {
|
export function request(...args: any[]) {
|
||||||
let options = {};
|
let options = {};
|
||||||
|
|
||||||
if (typeof args[0] === "string") {
|
if (typeof args[0] === "string") {
|
||||||
options = urlToHttpOptions(new URL(args.shift()));
|
const urlStr = args.shift();
|
||||||
|
options = urlToHttpOptions(new URL(urlStr));
|
||||||
} else if (args[0] instanceof URL) {
|
} else if (args[0] instanceof URL) {
|
||||||
options = urlToHttpOptions(args.shift());
|
options = urlToHttpOptions(args.shift());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args[0] && typeof args[0] !== "function") {
|
if (args[0] && typeof args[0] !== "function") {
|
||||||
Object.assign(options, args.shift());
|
Object.assign(options, args.shift());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
options._defaultAgent = globalAgent;
|
||||||
args.unshift(options);
|
args.unshift(options);
|
||||||
|
|
||||||
return new HttpsClientRequest(args[0], args[1]);
|
return new HttpsClientRequest(args[0], args[1]);
|
||||||
}
|
}
|
||||||
export default {
|
export default {
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
NOTE: This file should not be manually edited. Please edit 'cli/tests/node_compat/config.json' and run 'tools/node_compat/setup.ts' instead.
|
NOTE: This file should not be manually edited. Please edit 'cli/tests/node_compat/config.json' and run 'tools/node_compat/setup.ts' instead.
|
||||||
|
|
||||||
Total: 2933
|
Total: 2935
|
||||||
|
|
||||||
- [abort/test-abort-backtrace.js](https://github.com/nodejs/node/tree/v18.12.1/test/abort/test-abort-backtrace.js)
|
- [abort/test-abort-backtrace.js](https://github.com/nodejs/node/tree/v18.12.1/test/abort/test-abort-backtrace.js)
|
||||||
- [abort/test-abort-fatal-error.js](https://github.com/nodejs/node/tree/v18.12.1/test/abort/test-abort-fatal-error.js)
|
- [abort/test-abort-fatal-error.js](https://github.com/nodejs/node/tree/v18.12.1/test/abort/test-abort-fatal-error.js)
|
||||||
|
@ -1083,6 +1083,7 @@ Total: 2933
|
||||||
- [parallel/test-http-no-content-length.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-http-no-content-length.js)
|
- [parallel/test-http-no-content-length.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-http-no-content-length.js)
|
||||||
- [parallel/test-http-no-read-no-dump.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-http-no-read-no-dump.js)
|
- [parallel/test-http-no-read-no-dump.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-http-no-read-no-dump.js)
|
||||||
- [parallel/test-http-nodelay.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-http-nodelay.js)
|
- [parallel/test-http-nodelay.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-http-nodelay.js)
|
||||||
|
- [parallel/test-http-outgoing-buffer.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-http-outgoing-buffer.js)
|
||||||
- [parallel/test-http-outgoing-destroy.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-http-outgoing-destroy.js)
|
- [parallel/test-http-outgoing-destroy.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-http-outgoing-destroy.js)
|
||||||
- [parallel/test-http-outgoing-destroyed.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-http-outgoing-destroyed.js)
|
- [parallel/test-http-outgoing-destroyed.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-http-outgoing-destroyed.js)
|
||||||
- [parallel/test-http-outgoing-end-cork.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-http-outgoing-end-cork.js)
|
- [parallel/test-http-outgoing-end-cork.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-http-outgoing-end-cork.js)
|
||||||
|
@ -1093,6 +1094,7 @@ Total: 2933
|
||||||
- [parallel/test-http-outgoing-finished.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-http-outgoing-finished.js)
|
- [parallel/test-http-outgoing-finished.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-http-outgoing-finished.js)
|
||||||
- [parallel/test-http-outgoing-first-chunk-singlebyte-encoding.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-http-outgoing-first-chunk-singlebyte-encoding.js)
|
- [parallel/test-http-outgoing-first-chunk-singlebyte-encoding.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-http-outgoing-first-chunk-singlebyte-encoding.js)
|
||||||
- [parallel/test-http-outgoing-message-capture-rejection.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-http-outgoing-message-capture-rejection.js)
|
- [parallel/test-http-outgoing-message-capture-rejection.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-http-outgoing-message-capture-rejection.js)
|
||||||
|
- [parallel/test-http-outgoing-message-inheritance.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-http-outgoing-message-inheritance.js)
|
||||||
- [parallel/test-http-outgoing-message-write-callback.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-http-outgoing-message-write-callback.js)
|
- [parallel/test-http-outgoing-message-write-callback.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-http-outgoing-message-write-callback.js)
|
||||||
- [parallel/test-http-outgoing-properties.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-http-outgoing-properties.js)
|
- [parallel/test-http-outgoing-properties.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-http-outgoing-properties.js)
|
||||||
- [parallel/test-http-outgoing-proto.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-http-outgoing-proto.js)
|
- [parallel/test-http-outgoing-proto.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-http-outgoing-proto.js)
|
||||||
|
|
Loading…
Add table
Reference in a new issue