Thanks for understanding, I'm really noob in c/c++ languages.
Prerequisites:
I'm trying to create http-parser.js/ts lib at the lowest possible cost. Moreover, I want my own parser work with node.js readable/writable streams for more flexibility.
Research:
I found out that node.js uses the code from node_http_parser.cc. Here's is the node.js tests where the abovementioned code is used. As you can see, there is a line parser.consume(socket._handle);. It accepts net.Socket _handle value. And I really can't understand what is this. As far as I understand, Here is that c++ method. So, the Consume method accept (<net.Socket>socket)._handle and then cast this one to the StreamBase stream value via StreamBase::FromObject(args[0].As<Object>());.
Question:
I'm trying to find out, is it possible to use parser.consume with node.js streams? Maybe, there are some workarounds for this task?
Example:
const { HTTPParser } = process.binding('http_parser');
const parser = new HTTPParser(HTTPParser.RESPONSE, false);
parser.initialize(
HTTPParser.RESPONSE,
{},
0,
0,
);
interface CustomDuplex {
readable: ReadableStream<ArrayBuffer>,
writable: WritableStream<ArrayBuffer>
}
const duplex : CustomDuplex; // it will come from anywhere in the program;
parser[HTTPParser.kOnHeadersComplete] = (...args : any) => {
console.log("args: ", args);
};
parser.consume(duplex); // using duplex instead of socket._handle
Of course, now it fails. I lost a lot time of and realized that socket._handle is sort of a pointer or smth on TCPWrap, which is StreamBase actually in c++.
P.S: if someone wants to see the full example of the usage http_parser:
import * as net from "node:net";
// @ts-ignore
const {HTTPParser} = process.binding("http_parser");
const port = 8081;
const server = net.createServer();
server.listen(port, () => {
console.log(`Server listen on: http://localhost:${port}\r\n`);
connect(port);
});
server.unref();
// server.on("connection", onConnectionRaw); // uncomment to see the raw http query
server.on("connection", onConnection);
async function onConnection(socket : net.Socket) {
const parser = new HTTPParser(HTTPParser.REQUEST, false);
parser.initialize(
HTTPParser.REQUEST,
{},
0,
0,
);
parser[HTTPParser.kOnHeadersComplete] = (...args : any) => {
console.log("Parsed request via node_http_parser.cc!");
console.log("args: ", args);
socket.write("HTTP/1.1 200 OK\r\n\r\n");
socket.end();
};
// @ts-ignore
parser.consume(socket._handle);
}
async function onConnectionRaw(socket : net.Socket) {
console.log("Raw request");
socket.once("readable", () => {
let httpRequest = "";
let readResult;
while (readResult = socket.read()) {
httpRequest += readResult.toString();
}
console.log("Request from client:\r\n", httpRequest);
socket.write("HTTP/1.1 200 OK\r\n\r\n");
socket.end(() => {
console.log("Server closed the connection!");
});
})
}
/**
* send request to our parser
* @see {onConnection}
* @param port
*/
async function connect(port : number) {
console.log("Client sends the request!");
const response = await fetch(`http://localhost:${port}/path/to-resource`, {method: "GET"});
console.log(`Client got the response with statusCode==${response.status} and causeReason==${response.statusText}`);
}