3

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

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.