mirror of
https://github.com/denoland/deno.git
synced 2024-12-03 17:08:35 -05:00
fix double request initiation
This commit is contained in:
parent
d19c5a73e1
commit
881fe46d3f
3 changed files with 127 additions and 46 deletions
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
|
use std::fmt::Debug;
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::task::Context;
|
use std::task::Context;
|
||||||
|
@ -82,6 +83,14 @@ pub struct NodeHttpClientResponse {
|
||||||
url: String,
|
url: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Debug for NodeHttpClientResponse {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
f.debug_struct("NodeHttpClientResponse")
|
||||||
|
.field("url", &self.url)
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl deno_core::Resource for NodeHttpClientResponse {
|
impl deno_core::Resource for NodeHttpClientResponse {
|
||||||
fn name(&self) -> Cow<str> {
|
fn name(&self) -> Cow<str> {
|
||||||
"nodeHttpClientResponse".into()
|
"nodeHttpClientResponse".into()
|
||||||
|
@ -266,11 +275,17 @@ pub async fn op_node_http_await_response(
|
||||||
.resource_table
|
.resource_table
|
||||||
.take::<NodeHttpClientResponse>(rid)?;
|
.take::<NodeHttpClientResponse>(rid)?;
|
||||||
let resource = Rc::try_unwrap(resource)
|
let resource = Rc::try_unwrap(resource)
|
||||||
.map_err(|_| bad_resource("NodeHttpClientResponse"))?;
|
.map_err(|_| bad_resource("NodeHttpClientResponse"));
|
||||||
|
eprintln!("resource: {resource:?}");
|
||||||
|
let resource = resource?;
|
||||||
|
|
||||||
let res = resource.response.await?;
|
eprintln!("op_node_http_await_response: awating for res");
|
||||||
|
let res = resource.response.await;
|
||||||
|
eprintln!("op_node_http_await_response: res: {res:?}");
|
||||||
|
let res = res?;
|
||||||
|
|
||||||
let status = res.status();
|
let status = res.status();
|
||||||
|
eprintln!("op_node_http_await_response: {status}");
|
||||||
let mut res_headers = Vec::new();
|
let mut res_headers = Vec::new();
|
||||||
for (key, val) in res.headers().iter() {
|
for (key, val) in res.headers().iter() {
|
||||||
res_headers.push((key.as_str().into(), val.as_bytes().into()));
|
res_headers.push((key.as_str().into(), val.as_bytes().into()));
|
||||||
|
@ -568,7 +583,7 @@ impl Stream for NodeHttpResourceToBodyAdapter {
|
||||||
Ok(buf) if buf.is_empty() => Poll::Ready(None),
|
Ok(buf) if buf.is_empty() => Poll::Ready(None),
|
||||||
Ok(buf) => {
|
Ok(buf) => {
|
||||||
let bytes: Bytes = buf.to_vec().into();
|
let bytes: Bytes = buf.to_vec().into();
|
||||||
eprintln!("buf: {:?}", bytes.len());
|
eprintln!("buf: {:?}", bytes);
|
||||||
this.1 = Some(this.0.clone().read(64 * 1024));
|
this.1 = Some(this.0.clone().read(64 * 1024));
|
||||||
Poll::Ready(Some(Ok(bytes)))
|
Poll::Ready(Some(Ok(bytes)))
|
||||||
}
|
}
|
||||||
|
|
|
@ -391,7 +391,11 @@ Object.defineProperties(
|
||||||
msg._implicitHeader();
|
msg._implicitHeader();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
return msg._send(chunk, encoding, callback);
|
return msg._send(chunk, encoding, callback);
|
||||||
|
} catch (error) {
|
||||||
|
console.log("error from msg._send()", error);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// deno-lint-ignore no-explicit-any
|
// deno-lint-ignore no-explicit-any
|
||||||
|
@ -510,24 +514,36 @@ Object.defineProperties(
|
||||||
/** Right after socket is ready, we need to writeHeader() to setup the request and
|
/** Right after socket is ready, we need to writeHeader() to setup the request and
|
||||||
* client. This is invoked by onSocket(). */
|
* client. This is invoked by onSocket(). */
|
||||||
_flushHeaders() {
|
_flushHeaders() {
|
||||||
if (this.socket) {
|
console.trace("_flushHeaders", {
|
||||||
if (!this._headerSent) {
|
socket: !!this.socket,
|
||||||
this._writeHeader();
|
headerSent: this._headerSent,
|
||||||
|
});
|
||||||
|
if (this.socket && !this._headerSent) {
|
||||||
this._headerSent = true;
|
this._headerSent = true;
|
||||||
}
|
this._writeHeader();
|
||||||
} else {
|
} else {
|
||||||
// deno-lint-ignore no-console
|
// deno-lint-ignore no-console
|
||||||
console.warn("socket not found");
|
console.warn("socket not found");
|
||||||
}
|
}
|
||||||
|
console.trace("_flushHeaders after", {
|
||||||
|
socket: !!this.socket,
|
||||||
|
headerSent: this._headerSent,
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
// deno-lint-ignore no-explicit-any
|
// deno-lint-ignore no-explicit-any
|
||||||
_send(data: any, encoding?: string | null, callback?: () => void) {
|
_send(data: any, encoding?: string | null, callback?: () => void) {
|
||||||
console.trace("send invoked");
|
console.trace("send invoked", {
|
||||||
|
data: new TextDecoder().decode(data.slice(-20, -1)),
|
||||||
|
});
|
||||||
// if socket is ready, write the data after headers are written.
|
// if socket is ready, write the data after headers are written.
|
||||||
// if socket is not ready, buffer data in outputbuffer.
|
// if socket is not ready, buffer data in outputbuffer.
|
||||||
if (this.socket && !this.socket.connecting) {
|
if (this.socket && !this.socket.connecting) {
|
||||||
if (!this._headerSent && this._header !== null) {
|
console.log("writing headers again:", {
|
||||||
|
headerSent: this._headerSent,
|
||||||
|
header: this._header,
|
||||||
|
});
|
||||||
|
if (!this._headerSent) {
|
||||||
this._writeHeader();
|
this._writeHeader();
|
||||||
this._headerSent = true;
|
this._headerSent = true;
|
||||||
}
|
}
|
||||||
|
@ -591,9 +607,20 @@ Object.defineProperties(
|
||||||
data = new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
|
data = new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
|
||||||
}
|
}
|
||||||
if (data.buffer.byteLength > 0) {
|
if (data.buffer.byteLength > 0) {
|
||||||
|
console.log("waiting for bodyWriter to be ready", {
|
||||||
|
data: new TextDecoder().decode(data.slice(-20, -1)),
|
||||||
|
});
|
||||||
this._bodyWriter.ready.then(() => {
|
this._bodyWriter.ready.then(() => {
|
||||||
|
console.log("bodyWriter is ready", {
|
||||||
|
desirezedSize: this._bodyWriter.desiredSize,
|
||||||
|
});
|
||||||
if (this._bodyWriter.desiredSize > 0) {
|
if (this._bodyWriter.desiredSize > 0) {
|
||||||
this._bodyWriter.write(data).then(() => {
|
this._bodyWriter.write(data).then(() => {
|
||||||
|
console.log("writing done: ", {
|
||||||
|
last_bytes: new TextDecoder().decode(data.slice(-20, -1)),
|
||||||
|
length: data.length,
|
||||||
|
buffer: this.outputData.length,
|
||||||
|
});
|
||||||
callback?.();
|
callback?.();
|
||||||
if (this.outputData.length == 0) {
|
if (this.outputData.length == 0) {
|
||||||
this.emit("finish");
|
this.emit("finish");
|
||||||
|
@ -739,7 +766,8 @@ Object.defineProperties(
|
||||||
|
|
||||||
const { header } = state;
|
const { header } = state;
|
||||||
this._header = header + "\r\n";
|
this._header = header + "\r\n";
|
||||||
this._headerSent = false;
|
// console.log("_headerSent set to false");
|
||||||
|
// this._headerSent = false;
|
||||||
|
|
||||||
// Wait until the first body chunk, or close(), is sent to flush,
|
// Wait until the first body chunk, or close(), is sent to flush,
|
||||||
// UNLESS we're sending Expect: 100-continue.
|
// UNLESS we're sending Expect: 100-continue.
|
||||||
|
|
|
@ -398,6 +398,7 @@ class ClientRequest extends OutgoingMessage {
|
||||||
if (typeof optsWithoutSignal.createConnection === "function") {
|
if (typeof optsWithoutSignal.createConnection === "function") {
|
||||||
const oncreate = once((err, socket) => {
|
const oncreate = once((err, socket) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
|
console.log("emitting error", { err });
|
||||||
this.emit("error", err);
|
this.emit("error", err);
|
||||||
} else {
|
} else {
|
||||||
this.onSocket(socket);
|
this.onSocket(socket);
|
||||||
|
@ -423,6 +424,7 @@ class ClientRequest extends OutgoingMessage {
|
||||||
}
|
}
|
||||||
|
|
||||||
_writeHeader() {
|
_writeHeader() {
|
||||||
|
console.trace("_writeHeader invoked");
|
||||||
const url = this._createUrlStrFromOptions();
|
const url = this._createUrlStrFromOptions();
|
||||||
|
|
||||||
const headers = [];
|
const headers = [];
|
||||||
|
@ -451,7 +453,7 @@ class ClientRequest extends OutgoingMessage {
|
||||||
(async () => {
|
(async () => {
|
||||||
try {
|
try {
|
||||||
const parsedUrl = new URL(url);
|
const parsedUrl = new URL(url);
|
||||||
console.log("starting conn");
|
console.trace("starting conn");
|
||||||
let baseConnRid = this.socket.rid;
|
let baseConnRid = this.socket.rid;
|
||||||
console.log("socket:", baseConnRid);
|
console.log("socket:", baseConnRid);
|
||||||
if (this._encrypted) {
|
if (this._encrypted) {
|
||||||
|
@ -463,7 +465,16 @@ class ClientRequest extends OutgoingMessage {
|
||||||
alpnProtocols: ["http/1.0", "http/1.1"],
|
alpnProtocols: ["http/1.0", "http/1.1"],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
const [rid, connRid] = await op_node_http_request_with_conn(
|
let rid;
|
||||||
|
let connRid;
|
||||||
|
try {
|
||||||
|
console.log(
|
||||||
|
"sending request with conn",
|
||||||
|
this._bodyWriteRid,
|
||||||
|
baseConnRid,
|
||||||
|
this._encrypted,
|
||||||
|
);
|
||||||
|
[rid, connRid] = await op_node_http_request_with_conn(
|
||||||
this.method,
|
this.method,
|
||||||
url,
|
url,
|
||||||
headers,
|
headers,
|
||||||
|
@ -471,13 +482,24 @@ class ClientRequest extends OutgoingMessage {
|
||||||
baseConnRid,
|
baseConnRid,
|
||||||
this._encrypted,
|
this._encrypted,
|
||||||
);
|
);
|
||||||
console.log("request rid:", rid);
|
} catch (error) {
|
||||||
|
console.error("error from request with conn", error);
|
||||||
|
}
|
||||||
// Emit request ready to let the request body to be written.
|
// Emit request ready to let the request body to be written.
|
||||||
|
try {
|
||||||
await op_node_http_wait_for_connection(connRid);
|
await op_node_http_wait_for_connection(connRid);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("error from wait for connection", error);
|
||||||
|
}
|
||||||
console.log("request ready");
|
console.log("request ready");
|
||||||
this.emit("requestReady");
|
this.emit("requestReady");
|
||||||
const res = await op_node_http_await_response(rid);
|
let res;
|
||||||
console.log("response received");
|
try {
|
||||||
|
res = await op_node_http_await_response(rid);
|
||||||
|
console.log("response received", { res });
|
||||||
|
} catch (error) {
|
||||||
|
console.log("error from await response", error);
|
||||||
|
}
|
||||||
const incoming = new IncomingMessageForClient(this.socket);
|
const incoming = new IncomingMessageForClient(this.socket);
|
||||||
incoming.req = this;
|
incoming.req = this;
|
||||||
this.res = incoming;
|
this.res = incoming;
|
||||||
|
@ -516,13 +538,19 @@ class ClientRequest extends OutgoingMessage {
|
||||||
if (this.method === "CONNECT") {
|
if (this.method === "CONNECT") {
|
||||||
throw new Error("not implemented CONNECT");
|
throw new Error("not implemented CONNECT");
|
||||||
}
|
}
|
||||||
|
let upgradeRid;
|
||||||
const upgradeRid = await op_node_http_fetch_response_upgrade(
|
try {
|
||||||
|
upgradeRid = await op_node_http_fetch_response_upgrade(
|
||||||
res.responseRid,
|
res.responseRid,
|
||||||
);
|
);
|
||||||
|
} catch (error) {
|
||||||
|
console.log("error from fetch response upgrade", error);
|
||||||
|
}
|
||||||
assert(typeof res.remoteAddrIp !== "undefined");
|
assert(typeof res.remoteAddrIp !== "undefined");
|
||||||
assert(typeof res.remoteAddrIp !== "undefined");
|
assert(typeof res.remoteAddrIp !== "undefined");
|
||||||
const conn = new TcpConn(
|
let conn;
|
||||||
|
try {
|
||||||
|
conn = new TcpConn(
|
||||||
upgradeRid,
|
upgradeRid,
|
||||||
{
|
{
|
||||||
transport: "tcp",
|
transport: "tcp",
|
||||||
|
@ -536,9 +564,17 @@ class ClientRequest extends OutgoingMessage {
|
||||||
port: 80,
|
port: 80,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
const socket = new Socket({
|
} catch (error) {
|
||||||
|
console.log("error from new connectin");
|
||||||
|
}
|
||||||
|
let socket;
|
||||||
|
try {
|
||||||
|
socket = new Socket({
|
||||||
handle: new TCP(constants.SERVER, conn),
|
handle: new TCP(constants.SERVER, conn),
|
||||||
});
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.log("error from new Socket", error);
|
||||||
|
}
|
||||||
|
|
||||||
this.upgradeOrConnect = true;
|
this.upgradeOrConnect = true;
|
||||||
|
|
||||||
|
@ -568,8 +604,10 @@ class ClientRequest extends OutgoingMessage {
|
||||||
// Node.js seems ignoring this error
|
// Node.js seems ignoring this error
|
||||||
} else if (err.message.includes("The signal has been aborted")) {
|
} else if (err.message.includes("The signal has been aborted")) {
|
||||||
// Remap this error
|
// Remap this error
|
||||||
|
console.log("emitting socket hung up error");
|
||||||
this.emit("error", connResetException("socket hang up"));
|
this.emit("error", connResetException("socket hang up"));
|
||||||
} else {
|
} else {
|
||||||
|
console.log("emitting error event", err);
|
||||||
this.emit("error", err);
|
this.emit("error", err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue