1
0
Fork 0
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:
Satya Rohith 2024-10-15 16:46:09 +05:30
parent d19c5a73e1
commit 881fe46d3f
No known key found for this signature in database
GPG key ID: B2705CF40523EB05
3 changed files with 127 additions and 46 deletions

View file

@ -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)))
} }

View file

@ -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.

View file

@ -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);
} }
} }