-
Notifications
You must be signed in to change notification settings - Fork 183
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
Server-side AsyncContext
initialized in lifecycle observer is lost
#3111
Conversation
Motivation: If users put any data into `AsyncContext` inside `HttpLifecycleObserver` configured via `HttpServerBuilder.lifecycleObserver(...)` it won't be visible for filters and service because `ClearAsyncContextHttpServiceFilter` is appended after `HttpLifecycleObserverServiceFilter` inside `applyInternalFilters`. Modifications: 1. Move `ClearAsyncContextHttpServiceFilter` from the beginning of `noOffloadServiceFilters` to `applyInternalFilters`. However, this move discovered another bug in path that handles `noOffloadServiceFilters.isEmpty()` case because it never adds `OffloadingFilter`. 2. Refactor `listenForService` method to always make a copy of filters lists, then prepend/append internal filters to those copies in easy to read/understand way, and construct a single filters `Stream` for `buildService` method. 3. Refactor `OffloadingFilter` to act as a regular filter factory instead of taking all further `serviceFilters` as pre-built factory. 4. Rename `ClearAsyncContextHttpServiceFilter` singleton instance. 5. Fix another bug when `OptionalSslNegotiator` binder takes a raw service instead of `filteredService` (user-defined filters were never applied for this path). 6. Modify `AbstractHttpServiceAsyncContextTest` to test `AsyncContext` propagation from lifecycle observer and non-offloading filters. 7. Modify `AbstractHttpServiceAsyncContextTest` to test `AsyncContext` initialized by early/late connection acceptor is not visible at request path. 8. Add `BlockingHttpServiceAsyncContextTest` and `HttpServiceAsyncContextTest` to make sure `AsyncContext` propagation for blocking/async aggregated services is also tested. 9. Use `ParameterizedTest` where possible. Results: 1. `AsyncContext` initialized inside server's lifecycle observer is visible through filter chain and services. 2. Construction of server-side filter chain is consistent and sequential. 3. Filters are applied for servers with optional TLS.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Change looks good to me, I think it is an improvement also in follow-ability through the filter bootstrapping of the server. Just one nit, feel free to ignore.
One separate thing @idelpivnitskiy - since it changes the code quite a bit, just wanted to make sure that it is double checked that the new order is good and nothing ended up accidentally in the wrong spot of the filter chain. Doesn't look like it to me, just checking.
servicetalk-http-netty/src/main/java/io/servicetalk/http/netty/DefaultHttpServerBuilder.java
Show resolved
Hide resolved
There are existing tests to validate most of the features and ordering:
|
…pple#3111) Motivation: If users put any data into `AsyncContext` inside `HttpLifecycleObserver` configured via `HttpServerBuilder.lifecycleObserver(...)` it won't be visible for filters and service because `ClearAsyncContextHttpServiceFilter` is appended after `HttpLifecycleObserverServiceFilter` inside `applyInternalFilters`. Modifications: 1. Move `ClearAsyncContextHttpServiceFilter` from the beginning of `noOffloadServiceFilters` to `applyInternalFilters`. However, this move discovered another bug in path that handles `noOffloadServiceFilters.isEmpty()` case because it never adds `OffloadingFilter`. 2. Refactor `listenForService` method to always make a copy of filters lists, then prepend/append internal filters to those copies in easy to read/understand way, and construct a single filters `Stream` for `buildService` method. 3. Refactor `OffloadingFilter` to act as a regular filter factory instead of taking all further `serviceFilters` as pre-built factory. 4. Rename `ClearAsyncContextHttpServiceFilter` singleton instance. 5. Fix another bug when `OptionalSslNegotiator` binder takes a raw service instead of `filteredService` (user-defined filters were never applied for this path). 6. Modify `AbstractHttpServiceAsyncContextTest` to test `AsyncContext` propagation from lifecycle observer and non-offloading filters. 7. Modify `AbstractHttpServiceAsyncContextTest` to test `AsyncContext` initialized by early/late connection acceptor is not visible at request path. 8. Add `BlockingHttpServiceAsyncContextTest` and `HttpServiceAsyncContextTest` to make sure `AsyncContext` propagation for blocking/async aggregated services is also tested. 9. Use `ParameterizedTest` where possible. Results: 1. `AsyncContext` initialized inside server's lifecycle observer is visible through filter chain and services. 2. Construction of server-side filter chain is consistent and sequential. 3. Filters are applied for servers with optional TLS.
Motivation:
If users put any data into
AsyncContext
insideHttpLifecycleObserver
configured viaHttpServerBuilder.lifecycleObserver(...)
it won't be visible for filters and service becauseClearAsyncContextHttpServiceFilter
is appended afterHttpLifecycleObserverServiceFilter
insideapplyInternalFilters
.Modifications:
ClearAsyncContextHttpServiceFilter
from the beginning ofnoOffloadServiceFilters
toapplyInternalFilters
. However, this move discovered another bug in path that handlesnoOffloadServiceFilters.isEmpty()
case because it never addsOffloadingFilter
.listenForService
method to always make a copy of filters lists, then prepend/append internal filters to those copies in easy to read/understand way, and construct a single filtersStream
forbuildService
method.OffloadingFilter
to act as a regular filter factory instead of taking all furtherserviceFilters
as pre-built factory.ClearAsyncContextHttpServiceFilter
singleton instance.OptionalSslNegotiator
binder takes a raw service instead offilteredService
(user-defined filters were never applied for this path).AbstractHttpServiceAsyncContextTest
to testAsyncContext
propagation from lifecycle observer and non-offloading filters.AbstractHttpServiceAsyncContextTest
to testAsyncContext
initialized by early/late connection acceptor is not visible at request path.BlockingHttpServiceAsyncContextTest
andHttpServiceAsyncContextTest
to make sureAsyncContext
propagation for blocking/async aggregated services is also tested.ParameterizedTest
where possible.Results:
AsyncContext
initialized inside server's lifecycle observer is visible through filter chain and services.