Giter VIP home page Giter VIP logo

Comments (15)

leppert avatar leppert commented on July 20, 2024 3

As for your case, wouldn't it be easier (and less dependent on the internals) to just create a server and do server.emit('connection', yourInputStream) and then send request events to the output stream?

For anyone else curious about a minimal way to utilize these parsers, as mentioned above, here's a code snippet.

import { createServer, request } from 'http'
import { PassThrough } from 'node:stream'

const parseRequest = (data) => new Promise(resolve =>
  createServer()
    .on('request', resolve)
    .on('connection', stream => stream.write(data))
    .emit('connection', new PassThrough())
)
const parseResponse = (data) => new Promise(resolve =>
  request({ createConnection: () => new PassThrough() })
    .on('socket', stream => stream.write(data))
    .on('response', resolve)
)

const parsedRequest = await parseRequest(Buffer.from('GET / HTTP/1.1\r\nHost: example.com\r\n\r\n'))
const parsedResponse = await parseResponse(Buffer.from('HTTP/1.1 200 OK\r\n\r\n'))

For other ways of accessing these parsers, see here: gr3p1p3/transparent-proxy#30

from llhttp.

indutny avatar indutny commented on July 20, 2024

Hello!

That stackoverflow page is referring to http-parser-js which is a JavaScript port of http-parser. I believe it is still possible to use this module, because it doesn't use any C/C++ bindings at all.

It is not clear what you'd like to do, however. Do you want to run old HTTP parser or new HTTP parser? Do you want to run it manually (i.e. outside of http.createServer()/http.request)?

from llhttp.

Mickael-van-der-Beek avatar Mickael-van-der-Beek commented on July 20, 2024

@indutny Thanks for the quick answer!

You're right, I linked to the wrong snippet, I meant to link to the native bindings: https://stackoverflow.com/a/42003256

Yes, the idea would be to run the new HTTP parser that you wrote, llhttp, but manually in Node.js in a similar way than in the stackoverflow answer.
I'd like to pipe a Node.js stream into the parser that would then pipe the response headers and body back into a stream.
I know how to write the stream interfaces so that's ok, I'm just looking for a way to run the llhttp part.

I know that this is pretty much what the HTTP module does, but I'd like to be able to recreate something similar on my own.

from llhttp.

indutny avatar indutny commented on July 20, 2024

The process.binding(...) should work without any changes on your end since llhttp and http-parser are interoperable (at least when it comes to their JS APIs).

from llhttp.

Mickael-van-der-Beek avatar Mickael-van-der-Beek commented on July 20, 2024

Hmm, then I'm encountering a bug I believe in [email protected] and [email protected] on OSX, for this short test case (which would work on the old parser):

cconst HTTPParser = process.binding('http_parser').HTTPParser;

const httpParser = new HTTPParser(HTTPParser.REQUEST);

httpParser[HTTPParser.kOnHeadersComplete] = () => console.log('headers=', arguments);

httpParser.execute(Buffer.from(
  'GET /test HTTP/1.1\r\n' +
  'Host: www.example.com\r\n' +
  '\r\n'
));

I'm getting the following error:

node(55269,0x10df1a5c0) malloc: can't allocate region
*** mach_vm_map(size=9007066110754816) failed (error code=3)
node(55269,0x10df1a5c0) malloc: *** set a breakpoint in malloc_error_break to debug
libc++abi.dylib: terminating with uncaught exception of type std::bad_alloc: std::bad_alloc
fish: 'node http-parser-test.js' terminated by signal SIGABRT (Abort)

from llhttp.

Mickael-van-der-Beek avatar Mickael-van-der-Beek commented on July 20, 2024

Wow, it's actually even weirder than I thought.
If I run the program multiple times, it will sometimes fail with the error I posted above:

node(55465,0x1097d65c0) malloc: can't allocate region
*** mach_vm_map(size=27105212221095936) failed (error code=3)
node(55465,0x1097d65c0) malloc: *** set a breakpoint in malloc_error_break to debug
libc++abi.dylib: terminating with uncaught exception of type std::bad_alloc: std::bad_alloc
Abort trap: 6

sometimes with only the abort trap error:

Abort trap: 6

and then a few times:

Segmentation fault: 11

Even on the latest version, v13.7.0.

from llhttp.

indutny avatar indutny commented on July 20, 2024

It is likely that there is some mandatory callback missing. Let me see.

As for your case, wouldn't it be easier (and less dependent on the internals) to just create a server and do server.emit('connection', yourInputStream) and then send request events to the output stream?

from llhttp.

indutny avatar indutny commented on July 20, 2024

Ah, you haven't initialized the parser:

  parser.initialize(
    HTTPParser.REQUEST,
    new HTTPServerAsyncResource('HTTPINCOMINGMESSAGE', socket)
  );

As I said before, it is not easy to use this outside of Node.js core...

from llhttp.

Mickael-van-der-Beek avatar Mickael-van-der-Beek commented on July 20, 2024

Thanks for the follow-up!
Even with the correct initialisation parameters (which I mocked), I seem to keep getting the same errors described above.
The updated snippet is now:

const { Socket } = require('net');
const HTTPParser = process.binding('http_parser').HTTPParser;

class HTTPServerAsyncResource {
  constructor(type, socket) {
    this.type = type;
    this.socket = socket;
  }
}

const httpParser = new HTTPParser(
  HTTPParser.REQUEST,
  new HTTPServerAsyncResource('HTTPINCOMINGMESSAGE', new Socket())
);

httpParser[HTTPParser.kOnHeadersComplete] = () => console.log('headers=', arguments);

httpParser.execute(Buffer.from(
  'GET /test HTTP/1.1\r\n' +
  'Host: www.example.com\r\n' +
  '\r\n'
));

I understand that it's tricky but I would still like to try to call the parser manually because it was possible in the past and it let's you try out a lot of things on the parser directly.

from llhttp.

indutny avatar indutny commented on July 20, 2024

Could you try calling .initialize() on the parser?

from llhttp.

Mickael-van-der-Beek avatar Mickael-van-der-Beek commented on July 20, 2024

@indutny It seems to work now. Thank you very much for the support and sorry for asking silly questions. :)

Have a nice evening.

from llhttp.

indutny avatar indutny commented on July 20, 2024

Np at all. Glad it worked! You have a good evening as well!

from llhttp.

kettanaito avatar kettanaito commented on July 20, 2024

For those wondering, getting HTTPParser from the bindings has been deprecated. If you absolutely must, import it from the node:_http_common module instead:

import { HTTPParser } from 'node:_http_common'

from llhttp.

rickmed avatar rickmed commented on July 20, 2024

is import { HTTPParser } from 'node:_http_common' a public api? if not, can it be?

from llhttp.

ShogunPanda avatar ShogunPanda commented on July 20, 2024

It's not a public API and there is no need for it to be.
llhttp can be used in JS by using its WASM version, just like undici does.
See: https://github.com/nodejs/undici/blob/219da8b7b3fea7e38a7644b8bc35fe6fec97d66e/lib/dispatcher/client-h1.js#L139

from llhttp.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.