mirror of
https://github.com/denoland/deno.git
synced 2024-12-01 16:51:13 -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::cell::RefCell;
|
||||
use std::fmt::Debug;
|
||||
use std::pin::Pin;
|
||||
use std::rc::Rc;
|
||||
use std::task::Context;
|
||||
|
@ -82,6 +83,14 @@ pub struct NodeHttpClientResponse {
|
|||
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 {
|
||||
fn name(&self) -> Cow<str> {
|
||||
"nodeHttpClientResponse".into()
|
||||
|
@ -266,11 +275,17 @@ pub async fn op_node_http_await_response(
|
|||
.resource_table
|
||||
.take::<NodeHttpClientResponse>(rid)?;
|
||||
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();
|
||||
eprintln!("op_node_http_await_response: {status}");
|
||||
let mut res_headers = Vec::new();
|
||||
for (key, val) in res.headers().iter() {
|
||||
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) => {
|
||||
let bytes: Bytes = buf.to_vec().into();
|
||||
eprintln!("buf: {:?}", bytes.len());
|
||||
eprintln!("buf: {:?}", bytes);
|
||||
this.1 = Some(this.0.clone().read(64 * 1024));
|
||||
Poll::Ready(Some(Ok(bytes)))
|
||||
}
|
||||
|
|
|
@ -391,7 +391,11 @@ Object.defineProperties(
|
|||
msg._implicitHeader();
|
||||
}
|
||||
|
||||
try {
|
||||
return msg._send(chunk, encoding, callback);
|
||||
} catch (error) {
|
||||
console.log("error from msg._send()", error);
|
||||
}
|
||||
},
|
||||
|
||||
// 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
|
||||
* client. This is invoked by onSocket(). */
|
||||
_flushHeaders() {
|
||||
if (this.socket) {
|
||||
if (!this._headerSent) {
|
||||
this._writeHeader();
|
||||
console.trace("_flushHeaders", {
|
||||
socket: !!this.socket,
|
||||
headerSent: this._headerSent,
|
||||
});
|
||||
if (this.socket && !this._headerSent) {
|
||||
this._headerSent = true;
|
||||
}
|
||||
this._writeHeader();
|
||||
} else {
|
||||
// deno-lint-ignore no-console
|
||||
console.warn("socket not found");
|
||||
}
|
||||
console.trace("_flushHeaders after", {
|
||||
socket: !!this.socket,
|
||||
headerSent: this._headerSent,
|
||||
});
|
||||
},
|
||||
|
||||
// deno-lint-ignore no-explicit-any
|
||||
_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 not ready, buffer data in outputbuffer.
|
||||
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._headerSent = true;
|
||||
}
|
||||
|
@ -591,9 +607,20 @@ Object.defineProperties(
|
|||
data = new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
|
||||
}
|
||||
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(() => {
|
||||
console.log("bodyWriter is ready", {
|
||||
desirezedSize: this._bodyWriter.desiredSize,
|
||||
});
|
||||
if (this._bodyWriter.desiredSize > 0) {
|
||||
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?.();
|
||||
if (this.outputData.length == 0) {
|
||||
this.emit("finish");
|
||||
|
@ -739,7 +766,8 @@ Object.defineProperties(
|
|||
|
||||
const { header } = state;
|
||||
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,
|
||||
// UNLESS we're sending Expect: 100-continue.
|
||||
|
|
|
@ -398,6 +398,7 @@ class ClientRequest extends OutgoingMessage {
|
|||
if (typeof optsWithoutSignal.createConnection === "function") {
|
||||
const oncreate = once((err, socket) => {
|
||||
if (err) {
|
||||
console.log("emitting error", { err });
|
||||
this.emit("error", err);
|
||||
} else {
|
||||
this.onSocket(socket);
|
||||
|
@ -423,6 +424,7 @@ class ClientRequest extends OutgoingMessage {
|
|||
}
|
||||
|
||||
_writeHeader() {
|
||||
console.trace("_writeHeader invoked");
|
||||
const url = this._createUrlStrFromOptions();
|
||||
|
||||
const headers = [];
|
||||
|
@ -451,7 +453,7 @@ class ClientRequest extends OutgoingMessage {
|
|||
(async () => {
|
||||
try {
|
||||
const parsedUrl = new URL(url);
|
||||
console.log("starting conn");
|
||||
console.trace("starting conn");
|
||||
let baseConnRid = this.socket.rid;
|
||||
console.log("socket:", baseConnRid);
|
||||
if (this._encrypted) {
|
||||
|
@ -463,7 +465,16 @@ class ClientRequest extends OutgoingMessage {
|
|||
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,
|
||||
url,
|
||||
headers,
|
||||
|
@ -471,13 +482,24 @@ class ClientRequest extends OutgoingMessage {
|
|||
baseConnRid,
|
||||
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.
|
||||
try {
|
||||
await op_node_http_wait_for_connection(connRid);
|
||||
} catch (error) {
|
||||
console.error("error from wait for connection", error);
|
||||
}
|
||||
console.log("request ready");
|
||||
this.emit("requestReady");
|
||||
const res = await op_node_http_await_response(rid);
|
||||
console.log("response received");
|
||||
let res;
|
||||
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);
|
||||
incoming.req = this;
|
||||
this.res = incoming;
|
||||
|
@ -516,13 +538,19 @@ class ClientRequest extends OutgoingMessage {
|
|||
if (this.method === "CONNECT") {
|
||||
throw new Error("not implemented CONNECT");
|
||||
}
|
||||
|
||||
const upgradeRid = await op_node_http_fetch_response_upgrade(
|
||||
let upgradeRid;
|
||||
try {
|
||||
upgradeRid = await op_node_http_fetch_response_upgrade(
|
||||
res.responseRid,
|
||||
);
|
||||
} catch (error) {
|
||||
console.log("error from fetch response upgrade", error);
|
||||
}
|
||||
assert(typeof res.remoteAddrIp !== "undefined");
|
||||
assert(typeof res.remoteAddrIp !== "undefined");
|
||||
const conn = new TcpConn(
|
||||
let conn;
|
||||
try {
|
||||
conn = new TcpConn(
|
||||
upgradeRid,
|
||||
{
|
||||
transport: "tcp",
|
||||
|
@ -536,9 +564,17 @@ class ClientRequest extends OutgoingMessage {
|
|||
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),
|
||||
});
|
||||
} catch (error) {
|
||||
console.log("error from new Socket", error);
|
||||
}
|
||||
|
||||
this.upgradeOrConnect = true;
|
||||
|
||||
|
@ -568,8 +604,10 @@ class ClientRequest extends OutgoingMessage {
|
|||
// Node.js seems ignoring this error
|
||||
} else if (err.message.includes("The signal has been aborted")) {
|
||||
// Remap this error
|
||||
console.log("emitting socket hung up error");
|
||||
this.emit("error", connResetException("socket hang up"));
|
||||
} else {
|
||||
console.log("emitting error event", err);
|
||||
this.emit("error", err);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue