Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Node.js HTTP #97

Open
wants to merge 6 commits into
base: feature/fiberless
Choose a base branch
from
Open

Conversation

leonardoventurini
Copy link
Contributor

@leonardoventurini leonardoventurini commented Jul 17, 2023

Intercept all HTTP requests by wrapping addRequest from the internal HTTP Agent (_http_agent).

If the HTTP request is already tracked by the hijacks for meteor/http or meteor/fetch then we defer to them by using a ALS flag.

It tracks the requests namespaced as the library name node:http.

Added remeda as an alternative to underscore and eliminated some unused lodash standalone modules I had added. We need a good library like these for more declarative and readable code, and remeda looks like a great fit.

@leonardoventurini leonardoventurini marked this pull request as ready for review July 17, 2023 15:26
lib/async/als.js Outdated Show resolved Hide resolved
res.end('done');
}).listen();

addAsyncTest('HTTP - node:http - client request', async function (test) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There probably should be a test for:

  • calling HTTP.get, and synchronously (without awaiting HTTP.get) call node:http afterwards
  • do the same thing for fetch

This will ensure that isHTTPAlreadyTracked is cleaned up correctly.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it does pollute the current context and leaks even when both are awaited... having a hard time thinking on a variable or parameter to use to prevent the duplication.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried using a separate store with run and it worked fine. I think we can use Meteor.Environment on Meteor 2.

tests/_helpers/http.js Outdated Show resolved Hide resolved
lib/hijack/http.js Outdated Show resolved Hide resolved
lib/hijack/http.js Outdated Show resolved Hide resolved
@@ -92,3 +98,43 @@ if (Package['fetch']) {
}
};
}

const { Agent } = require('_http_agent');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to use the node: prefix here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought it would cause problems with older Node versions but it does work

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we backport to Meteor 2, we wouldn't be able to use it there.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, makes sense, will check if future Node.js versions enforce the prefix and implement a workaround.

@@ -21,6 +23,8 @@ if (Package['http']) {
return originalCall.apply(this, arguments);
}

mergeEnterWith({ isHttpAlreadyTracked: true });
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there another option for storing isHttpAlreadyTracked? That would make it easier to backport this for Meteor 2.

Does the HTTP and fetch packages synchronously create the request? If so, we could use a variable to track it. Another option might be to wrap it with a Meteor Environment Variable.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried using Meteor.EnvironmentVariable but the withValue wraps the logic into a promise and causes problems with errors being thrown inside it (uncaught error, instead of propagating upstream). Will research a better way... in the meantime I asked the guys at Meteor what they think of removing the async/await here:

image

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are a number of bugs with Meteor.EnvironmentVariable in Meteor 3 at the moment. We could maybe wait on this until those get fix.

Does the HTTP and fetch packages synchronously create the request? If so, we could use a variable to track it.

Do you know if this would work?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could not find a way to use a variable to do that, there are simply too many layers between the calls, but using run and a new als store did the trick. The Meteor.EnvironmentVariable should work on Meteor 2 as an alternative I think.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants