Conversation
|
I don't really see what this brings other than maybe better ergonomics? The dispatcher interface is already quite extensible? Could this live outside as an npm package? |
mcollina
left a comment
There was a problem hiding this comment.
I see the need for better ergonomics for this, however I would not add any new globals for this. Could this be a feature of Agent instead?
|
At the end of the day, this is simply a proposal.
I expect some back and forth before a final revision.
Personally, I'm not happy with the shape of the API, but I'm happy to take
suggestions.
Additionally, I'm considering switching to a DispatcherDecorator model,
with a AgentBuilder for setting the global dispatcher.
…On Thu, 14 Apr 2022, 15:08 Matteo Collina, ***@***.***> wrote:
***@***.**** requested changes on this pull request.
I see the need for better ergonomics for this, however I would not add any
new globals for this. Could this be a feature of Agent instead?
—
Reply to this email directly, view it on GitHub
<#1338 (review)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AA46MLIICLNLN3DLSUXB6S3VE675FANCNFSM5TLXQTAQ>
.
You are receiving this because you authored the thread.Message ID:
***@***.***>
|
|
Also, I'm having trouble coming up with an API that would not create a
breaking change on a raw Client, whilst also extracting out the
RedirectHandler.
…On Sat, 16 Apr 2022, 02:53 Aron Tsang, ***@***.***> wrote:
At the end of the day, this is simply a proposal.
I expect some back and forth before a final revision.
Personally, I'm not happy with the shape of the API, but I'm happy to take
suggestions.
Additionally, I'm considering switching to a DispatcherDecorator model,
with a AgentBuilder for setting the global dispatcher.
On Thu, 14 Apr 2022, 15:08 Matteo Collina, ***@***.***>
wrote:
> ***@***.**** requested changes on this pull request.
>
> I see the need for better ergonomics for this, however I would not add
> any new globals for this. Could this be a feature of Agent instead?
>
> —
> Reply to this email directly, view it on GitHub
> <#1338 (review)>,
> or unsubscribe
> <https://github.com/notifications/unsubscribe-auth/AA46MLIICLNLN3DLSUXB6S3VE675FANCNFSM5TLXQTAQ>
> .
> You are receiving this because you authored the thread.Message ID:
> ***@***.***>
>
|
|
How would the DispatcherDecorator work? |
|
@mcollina Here is another commit showing what I mean arontsang@d54794f?diff=unified In effect we add to the constructor of Dispatcher Where We then reduce the array of |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1338 +/- ##
==========================================
- Coverage 94.95% 94.67% -0.28%
==========================================
Files 51 53 +2
Lines 4816 4866 +50
==========================================
+ Hits 4573 4607 +34
- Misses 243 259 +16 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
I've just noticed that ProxyAgent could be replaced with a DispatchInterceptor quite trivially. |
mcollina
left a comment
There was a problem hiding this comment.
Good work! Could you run the benchmarks before/after? Could you document this new feature?
Add documentation
docs/api/DispatchInterceptor.md
Outdated
| 'use strict' | ||
|
|
||
| const clearHeadersInterceptor = dispatch => { | ||
| const DecoratorHandler = require('undici/lib/handler/decorator') |
There was a problem hiding this comment.
This is an internal library, let's not document it. If it needs to be exposed, please use the module entry point.
There was a problem hiding this comment.
@mcollina I would prefer this to be exposed. I am actually trying to add support for NTLM undici, which doesn't seem like a great fit for being in mainline.
The only reason I am working on this is the fact that node.js has terrible support for socket based Auth. The socket is abstracted away completely.
Additionally, I suspect opening this up will allow for lots of extensions.
There was a problem hiding this comment.
I've also noticed that http headers being of type ByteArray means that each extension is likely to be to decode utf8 once each...
There was a problem hiding this comment.
Go ahead and expose it in this PR.
I've also noticed that http headers being of type ByteArray means that each extension is likely to be to decode utf8 once each...
What do you mean? Can you make an example?
There was a problem hiding this comment.
@kibertoad this needs fixing, we should not be deep-requiring.
|
@ronag PTAL |
|
I'll have. A look next week. |
|
Thanks
…On Sat, 30 Apr 2022, 00:54 Robert Nagy, ***@***.***> wrote:
I'll have. A look next week.
—
Reply to this email directly, view it on GitHub
<#1338 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/AA46MLIK5FZFIM4M43CUDGLVHQH23ANCNFSM5TLXQTAQ>
.
You are receiving this because you authored the thread.Message ID:
***@***.***>
|
|
I think this can be achieved without modifying existing internals and I think I would maybe prefer that, i.e. implement a const client = undici.intercept(new Client('https://localhost:3000', [
dispatch => function insertHeader(opts, handler){
opts.headers.push('Authorization', 'Bearer [Some token]')
return dispatch(opts, handler)
}
]) |
|
Or maybe: const client = undici.compose(
() => new Client('https://localhost:3000',
dispatch => function insertHeader(opts, handler){
opts.headers.push('Authorization', 'Bearer [Some token]')
return dispatch(opts, handler)
}
) |
undici.request(url, {
decorate: [insertHeaders({ foo: 'bar' }, redirect({ maxRetries: 3 )]
}) |
|
This might need a few iterations and since it doesn't require any internal modifications we should consider whether or not we should first have it as an external package. Not saying we should. Just to consider. |
This would not work for my use case. I NEED to apply the decorator AT the client level of an Agent. The decorator needs to be scoped to a single TCP connection to be able to implement NTLM authentication. |
This works, but it would require an inordinate amount of boiler plate to bring up a full Agent with decorators at the right levels, Agent, Pool, Client etc... |
|
@arontsang Can you provide any details on ? I can't find where in the code this is happening |
docs/api/DispatchInterceptor.md
Outdated
| 'use strict' | ||
|
|
||
| const clearHeadersInterceptor = dispatch => { | ||
| const DecoratorHandler = require('undici/lib/handler/decorator') |
There was a problem hiding this comment.
@kibertoad this needs fixing, we should not be deep-requiring.
docs/api/Pool.md
Outdated
|
|
||
| * **factory** `(origin: URL, opts: Object) => Dispatcher` - Default: `(origin, opts) => new Client(origin, opts)` | ||
| * **connections** `number | null` (optional) - Default: `null` - The number of `Client` instances to create. When set to `null`, the `Pool` instance will create an unlimited amount of `Client` instances. | ||
| * **interceptors.Pool** `Array<DispatchInterceptor>` - Default: `[]` - A list of interceptors that are applied to the dispatch method. Additional logic can be applied (such as, but not limited to: 302 status code handling, authentication, cookies, compression and caching). |
There was a problem hiding this comment.
It's not clear this is { interceptors: { Pool: [] } }
|
@mcollina Comments addressed! |
mcollina
left a comment
There was a problem hiding this comment.
I would avoid introducing any more global settings, could you avoid them? Thanxk
lib/proxy-agent.js
Outdated
| const connect = buildConnector({ ...opts.proxyTls }) | ||
| this[kConnectEndpoint] = buildConnector({ ...opts.requestTls }) | ||
| this[kClient] = new Client({ origin: opts.origin, connect }) | ||
| this[kClient] = new Agent({ origin: opts.origin, connect }) |
There was a problem hiding this comment.
const Client = require('./agent')
const Agent = require('./agent')
Naming was confusing, they were exactly same thing. Am I missing anything?
There was a problem hiding this comment.
Seems more like the import was incorrect?
@mcollina Do you mean new options for Client/Agent/Pool? Where would you place them instead? |
mcollina
left a comment
There was a problem hiding this comment.
lgtm, that text was a leftover from a previous half-botched review
|
Does this support async logic in interceptors? For example, read credentials from the disk in a request interceptor and then add them to request headers. |
|
Also I find it annoying when extending request headers in a request interceptor, the |
|
I would need help with some of this.
I am a dotnet Dev by trade, so a lot of it isn't my wheelhouse, for
example, I don't know the Jest library inside and out...
Would it be better if we put this into a branch?
…On Tue, 28 Jun 2022, 00:01 Matteo Collina, ***@***.***> wrote:
Let's go ahead and land. The code seems reasonable to me so far, minus all
the comments.
I'm 100% ok with semver-major changes on this one.
Maybe we could classify interceptors as experimental?
Could you address them @arontsang <https://github.com/arontsang>? Sorry
for the long wait.
—
Reply to this email directly, view it on GitHub
<#1338 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/AA46MLL6GODF7EIVJEFHAKDVRHF7HANCNFSM5TLXQTAQ>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
|
It can, but, that would get very complicated when we get to the point of
having half a dozen of these things
…On Sat, 30 Apr 2022, 02:07 Robert Nagy, ***@***.***> wrote:
I think this can be achieved without modifying existing internals and I
think I would maybe prefer that, i.e. implement a
compose/decorate/intercept (or other name) function that implements a
compose dispatcher that applies this logic. So it would essentially be
possible to do the following without any modification of existing code:
const insertHeaderInterceptor = dispatch => {
return function InterceptedDispatch(opts, handler){
opts.headers.push('Authorization', 'Bearer [Some token]')
return dispatch(opts, handler)
}}
const client = undici.intercept(new Client('https://localhost:3000', [ insertHeaderInterceptor ])
—
Reply to this email directly, view it on GitHub
<#1338 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/AA46MLNQYNHYTC7F5R6PARTVHQQNLANCNFSM5TLXQTAQ>
.
You are receiving this because you authored the thread.Message ID:
***@***.***>
|
* Create DispatchInterceptors * Add Unit Tests, fix DispatchHandler typescript Add documentation * Switch to simple null check and shortcircuit bind * Add typescript test for Dispatcher events * Move build intecepted dispatch to top level * Restore lost method * Fix TS error * Address code review comments * Fix linting * Type improvements * Fix TS tests * Address code review comments * Fix TS test * Fix types * Address comments * Fix client construction Co-authored-by: Igor Savin <iselwin@gmail.com>
* Create DispatchInterceptors * Add Unit Tests, fix DispatchHandler typescript Add documentation * Switch to simple null check and shortcircuit bind * Add typescript test for Dispatcher events * Move build intecepted dispatch to top level * Restore lost method * Fix TS error * Address code review comments * Fix linting * Type improvements * Fix TS tests * Address code review comments * Fix TS test * Fix types * Address comments * Fix client construction Co-authored-by: Igor Savin <iselwin@gmail.com>
This adds a plugin system that allows decorators to be added to the DispatchHandler as part of a pipeline.
I expect to see in future plugins such as (but not limited to):
This should support #491