mirror of
https://github.com/denoland/deno.git
synced 2024-11-24 15:19:26 -05:00
fix(node/http): use fake socket and proper url handling (#19340)
Fixes https://github.com/denoland/deno/issues/19349 --------- Co-authored-by: Bartek Iwańczuk <biwanczuk@gmail.com>
This commit is contained in:
parent
c76f9a0227
commit
5aca8b9e5d
3 changed files with 49 additions and 41 deletions
|
@ -195,11 +195,14 @@ Deno.test("[node/http] request default protocol", async () => {
|
||||||
// @ts-ignore IncomingMessageForClient
|
// @ts-ignore IncomingMessageForClient
|
||||||
// deno-lint-ignore no-explicit-any
|
// deno-lint-ignore no-explicit-any
|
||||||
let clientRes: any;
|
let clientRes: any;
|
||||||
|
// deno-lint-ignore no-explicit-any
|
||||||
|
let clientReq: any;
|
||||||
server.listen(() => {
|
server.listen(() => {
|
||||||
const req = http.request(
|
clientReq = http.request(
|
||||||
// deno-lint-ignore no-explicit-any
|
// deno-lint-ignore no-explicit-any
|
||||||
{ host: "localhost", port: (server.address() as any).port },
|
{ host: "localhost", port: (server.address() as any).port },
|
||||||
(res) => {
|
(res) => {
|
||||||
|
assert(res.socket instanceof EventEmitter);
|
||||||
assertEquals(res.complete, false);
|
assertEquals(res.complete, false);
|
||||||
res.on("data", () => {});
|
res.on("data", () => {});
|
||||||
res.on("end", () => {
|
res.on("end", () => {
|
||||||
|
@ -210,13 +213,14 @@ Deno.test("[node/http] request default protocol", async () => {
|
||||||
promise2.resolve();
|
promise2.resolve();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
req.end();
|
clientReq.end();
|
||||||
});
|
});
|
||||||
server.on("close", () => {
|
server.on("close", () => {
|
||||||
promise.resolve();
|
promise.resolve();
|
||||||
});
|
});
|
||||||
await promise;
|
await promise;
|
||||||
await promise2;
|
await promise2;
|
||||||
|
assert(clientReq.socket instanceof EventEmitter);
|
||||||
assertEquals(clientRes!.complete, true);
|
assertEquals(clientRes!.complete, true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -596,3 +600,24 @@ Deno.test("[node/http] ClientRequest PUT", async () => {
|
||||||
await def;
|
await def;
|
||||||
assertEquals(body, "hello world");
|
assertEquals(body, "hello world");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Deno.test("[node/http] ClientRequest search params", async () => {
|
||||||
|
let body = "";
|
||||||
|
const def = deferred();
|
||||||
|
const req = http.request({
|
||||||
|
host: "localhost:4545",
|
||||||
|
path: "search_params?foo=bar",
|
||||||
|
}, (resp) => {
|
||||||
|
resp.on("data", (chunk) => {
|
||||||
|
body += chunk;
|
||||||
|
});
|
||||||
|
|
||||||
|
resp.on("end", () => {
|
||||||
|
def.resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
req.once("error", (e) => def.reject(e));
|
||||||
|
req.end();
|
||||||
|
await def;
|
||||||
|
assertEquals(body, "foo=bar");
|
||||||
|
});
|
||||||
|
|
|
@ -267,6 +267,9 @@ const kError = Symbol("kError");
|
||||||
|
|
||||||
const kUniqueHeaders = Symbol("kUniqueHeaders");
|
const kUniqueHeaders = Symbol("kUniqueHeaders");
|
||||||
|
|
||||||
|
class FakeSocket extends EventEmitter {
|
||||||
|
}
|
||||||
|
|
||||||
/** ClientRequest represents the http(s) request from the client */
|
/** ClientRequest represents the http(s) request from the client */
|
||||||
class ClientRequest extends OutgoingMessage {
|
class ClientRequest extends OutgoingMessage {
|
||||||
defaultProtocol = "http:";
|
defaultProtocol = "http:";
|
||||||
|
@ -541,6 +544,7 @@ class ClientRequest extends OutgoingMessage {
|
||||||
this.onSocket(createConnection(optsWithoutSignal));
|
this.onSocket(createConnection(optsWithoutSignal));
|
||||||
}
|
}
|
||||||
}*/
|
}*/
|
||||||
|
this.onSocket(new FakeSocket());
|
||||||
|
|
||||||
const url = this._createUrlStrFromOptions();
|
const url = this._createUrlStrFromOptions();
|
||||||
|
|
||||||
|
@ -570,41 +574,12 @@ class ClientRequest extends OutgoingMessage {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
onSocket(socket, err) {
|
// TODO(bartlomieju): handle error
|
||||||
if (this.destroyed || err) {
|
onSocket(socket, _err) {
|
||||||
this.destroyed = true;
|
nextTick(() => {
|
||||||
|
this.socket = socket;
|
||||||
// deno-lint-ignore no-inner-declarations
|
this.emit("socket", socket);
|
||||||
function _destroy(req, err) {
|
});
|
||||||
if (!req.aborted && !err) {
|
|
||||||
err = connResetException("socket hang up");
|
|
||||||
}
|
|
||||||
if (err) {
|
|
||||||
req.emit("error", err);
|
|
||||||
}
|
|
||||||
req._closed = true;
|
|
||||||
req.emit("close");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (socket) {
|
|
||||||
if (!err && this.agent && !socket.destroyed) {
|
|
||||||
socket.emit("free");
|
|
||||||
} else {
|
|
||||||
finished(socket.destroy(err || this[kError]), (er) => {
|
|
||||||
if (er?.code === "ERR_STREAM_PREMATURE_CLOSE") {
|
|
||||||
er = null;
|
|
||||||
}
|
|
||||||
_destroy(this, er || err);
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_destroy(this, err || this[kError]);
|
|
||||||
} else {
|
|
||||||
//tickOnSocket(this, socket);
|
|
||||||
//this._flush();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// deno-lint-ignore no-explicit-any
|
// deno-lint-ignore no-explicit-any
|
||||||
|
@ -737,16 +712,19 @@ class ClientRequest extends OutgoingMessage {
|
||||||
const auth = this.auth;
|
const auth = this.auth;
|
||||||
const host = this.host ?? this.hostname ?? "localhost";
|
const host = this.host ?? this.hostname ?? "localhost";
|
||||||
const hash = this.hash ? `#${this.hash}` : "";
|
const hash = this.hash ? `#${this.hash}` : "";
|
||||||
const search = this.search ? this.search : "";
|
|
||||||
const defaultPort = this.agent?.defaultPort;
|
const defaultPort = this.agent?.defaultPort;
|
||||||
const port = this.port ?? defaultPort ?? 80;
|
const port = this.port ?? defaultPort ?? 80;
|
||||||
let path = this.path ?? "/";
|
let path = this.path ?? "/";
|
||||||
if (!path.startsWith("/")) {
|
if (!path.startsWith("/")) {
|
||||||
path = "/" + path;
|
path = "/" + path;
|
||||||
}
|
}
|
||||||
return `${protocol}//${auth ? `${auth}@` : ""}${host}${
|
const url = new URL(
|
||||||
port === 80 ? "" : `:${port}`
|
`${protocol}//${auth ? `${auth}@` : ""}${host}${
|
||||||
}${path}${search}${hash}`;
|
port === 80 ? "" : `:${port}`
|
||||||
|
}${path}`,
|
||||||
|
);
|
||||||
|
url.hash = hash;
|
||||||
|
return url.href;
|
||||||
}
|
}
|
||||||
|
|
||||||
setTimeout(msecs: number, callback?: () => void) {
|
setTimeout(msecs: number, callback?: () => void) {
|
||||||
|
|
|
@ -1085,6 +1085,11 @@ async fn main_server(
|
||||||
));
|
));
|
||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
(_, "/search_params") => {
|
||||||
|
let query = req.uri().query().map(|s| s.to_string());
|
||||||
|
let res = Response::new(Body::from(query.unwrap_or_default()));
|
||||||
|
Ok(res)
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let mut file_path = testdata_path();
|
let mut file_path = testdata_path();
|
||||||
file_path.push(&req.uri().path()[1..]);
|
file_path.push(&req.uri().path()[1..]);
|
||||||
|
|
Loading…
Reference in a new issue