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

Make Http2MultiplexHandler construction require explicit distinction between server and client #12546

Closed
wants to merge 3 commits into from

Conversation

yawkat
Copy link
Contributor

@yawkat yawkat commented Jul 1, 2022

Motivation:

Because Http2MultiplexHandler attempts to infer isServer from the channel type (ServerChannel), it can't be used in an EmbeddedChannel for HTTP server testing.

Modification:

Deprecate the old Http2MultiplexHandler constructors, and replace them with forClient and forServer factory methods, similar to Http2FrameCodecBuilder.

Result:

  • Http2MultiplexHandler can be used in an EmbeddedChannel
  • construction is a bit more clear, as you can't pass an upgradeHandler to a server multiplexer anymore, where it would never be used anyway

…between server and client

Motivation:

Because Http2MultiplexHandler attempts to infer `isServer` from the channel type (`ServerChannel`), it can't be used in an `EmbeddedChannel` for HTTP server testing.

Modification:

Deprecate the old Http2MultiplexHandler constructors, and replace them with `forClient` and `forServer` factory methods, similar to `Http2FrameCodecBuilder`.

Result:

- `Http2MultiplexHandler` can be used in an EmbeddedChannel
- construction is a bit more clear, as you can't pass an `upgradeHandler` to a server multiplexer anymore, where it would never be used anyway
Copy link
Member

@normanmaurer normanmaurer left a comment

Choose a reason for hiding this comment

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

only one nit.. Looks great otherwise

yawkat and others added 2 commits July 1, 2022 12:28
…ltiplexHandler.java

Co-authored-by: Norman Maurer <norman_maurer@apple.com>
*/
@Deprecated
Copy link
Contributor

Choose a reason for hiding this comment

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

is deprecation actually necessary? This change helps for small edge case (testing, with EmbeddedChannel only - but many use real channels for testing), otherwise current API is sufficient. It would force netty users onto new API for no practical gain.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

it's not like they have to be removed in 4.x, but it seems weird to have both the factory and the constructor.

*/
@Deprecated
Copy link
Contributor

Choose a reason for hiding this comment

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

is deprecation actually necessary? This change helps for small edge case (testing, with EmbeddedChannel only - but many use real channels for testing), otherwise current API is sufficient. It would force netty users onto new API for no practical gain.

@mostroverkhov
Copy link
Contributor

mostroverkhov commented Jul 2, 2022

@yawkat also wondering if public class EmbeddedServerChannel extends EmbeddedChannel implements ServerChannel would work for tests, instead of updating http2 handlers API for testing purposes.

@yawkat
Copy link
Contributor Author

yawkat commented Jul 4, 2022

Yes it's a possible workaround, but it seems like a worse solution.

@mostroverkhov
Copy link
Contributor

It addresses the root cause - aims to solve testing problem by extending test code. And is alternative to patching 1 production codec with new API to sidestep the fact that test EmbeddedChannel (this is connection mock) does not have parent channel (on server side, this is connection factory).

So for "clean" solution you should instead have

static class EmbeddedServerChannel extends EmbeddedChannel implements ServerChannel {
 }

and add ctor to EmbeddedChannel that accepts parentChannel

public EmbeddedChannel(Channel parent) {
       this(parent, EmbeddedChannelId.INSTANCE, true, false, EMPTY_HANDLERS);
}

I am pretty sure your test then passes with

EmbeddedChannel embeddedChannel = new EmbeddedChannel(new EmbeddedServerChannel());

If you want to fix the problem today w/o patching netty at all, then

static class EmbeddedServerChannel extends EmbeddedChannel implements ServerChannel {

        @Override
        public Channel parent() {
            return this;
        }
    }

Hope this explanation is helpful.

@normanmaurer
Copy link
Member

It addresses the root cause - aims to solve testing problem by extending test code. And is alternative to patching 1 production codec with new API to sidestep the fact that test EmbeddedChannel (this is connection mock) does not have parent channel (on server side, this is connection factory).

So for "clean" solution you should instead have

static class EmbeddedServerChannel extends EmbeddedChannel implements ServerChannel {
 }

and add ctor to EmbeddedChannel that accepts parentChannel

public EmbeddedChannel(Channel parent) {
       this(parent, EmbeddedChannelId.INSTANCE, true, false, EMPTY_HANDLERS);
}

I am pretty sure your test then passes with

EmbeddedChannel embeddedChannel = new EmbeddedChannel(new EmbeddedServerChannel());

If you want to fix the problem today w/o patching netty at all, then

static class EmbeddedServerChannel extends EmbeddedChannel implements ServerChannel {

        @Override
        public Channel parent() {
            return this;
        }
    }

Hope this explanation is helpful.

Actually there is already a constructor that takes a parent. So with this in mind we should just close this. Thanks @mostroverkhov for stepping in

@yawkat
Copy link
Contributor Author

yawkat commented Jul 5, 2022

Note that EmbeddedChannel is not used only for testing. And there are other byte-carrying channels too (including the ones introduced by this multiplex handler!), where adding the marker interface is not feasible. By the same reasoning, we could change Http2FrameCodecBuilder to deduce the server-ness from the context, instead of the forClient/forServer approach. Why use deduction in one case but not in others?

I also don't see the downside to this change. It does not remove any methods. And the class is even @UnstableApi.

@normanmaurer
Copy link
Member

@yawkat while I agree that the change is not "bad" I also think that there is no really "need / benefit" for the change.

@normanmaurer
Copy link
Member

/cc @chrisvest @trustin thoughts ?

@yawkat
Copy link
Contributor Author

yawkat commented Jul 5, 2022

Fair enough. We can always reconsider if someone else hits this in a situation where a workaround is harder.

@chrisvest
Copy link
Contributor

There are not many cases where a server-or-not check comes up. Making EmbeddedChannel behave more similar to other channels (by adding a server-sibling) is the better option, in my opinion. For Netty 5 we can add an isServer method to Channel so we no longer need to infer this information, but can just ask (and override if need be).

@yawkat
Copy link
Contributor Author

yawkat commented Jul 5, 2022 via email

@yawkat
Copy link
Contributor Author

yawkat commented Feb 26, 2024

@chrisvest @normanmaurer I've found another case where this check fails. When you get a SocketChannel from inetd or systemd with socket activation (either through System.inheritedChannel(), or through new EpollSocketChannel(fd)), then the channel won't have a ServerChannel parent even though it is a server-side channel. For nio this can probably be fixed by using new NioSocketChannel(new FakeServerChannel(), (SocketChannel) System.inheritedChannel()) where FakeServerChannel is an EmbeddedChannel that implements ServerChannel as described above. However for epoll no such constructor exists, and it is again an ugly solution anyway.

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.

None yet

4 participants