-
Notifications
You must be signed in to change notification settings - Fork 927
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
Reuse VirtualHostBuilder on the same hostnamePattern #5418
Conversation
aab4ec5
to
906334e
Compare
906334e
to
90a50c6
Compare
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.
Overall, it looks great.
return normalizeDefaultHostname(defaultHostname).equals(this.defaultHostname); | ||
} | ||
|
||
boolean equalsHostnamePattern(String hostnamePattern) { |
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.
What do you think of parsing hostnamePattern
before calling this method? Otherwise, the same hostnamePattern
will be parsed as many virtual hosts.
boolean equalsHostnamePattern(String hostnamePattern) { | |
boolean equalsHostnamePattern(String validhostnamePattern, int port) { |
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.
Thank you for the advice. Before I modify it, I'd like to know your intend exactly.
If I modify as you suggest, hostnamePattern
is parsed using HostAndPort
by the part which calls this method and passed. (e.g. ServiceBuilder.virtualHost(String hostnamePattern)), is it correct?
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.
@ikhoon I applied your comment as I understand. PTAL 🙏
core/src/main/java/com/linecorp/armeria/server/VirtualHostBuilder.java
Outdated
Show resolved
Hide resolved
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #5418 +/- ##
============================================
+ Coverage 74.04% 74.09% +0.04%
- Complexity 20871 20986 +115
============================================
Files 1809 1819 +10
Lines 76857 77332 +475
Branches 9809 9880 +71
============================================
+ Hits 56912 57300 +388
- Misses 15304 15375 +71
- Partials 4641 4657 +16 ☔ View full report in Codecov by Sentry. |
fc34ae2
to
7e57f3d
Compare
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.
Hey~ thanks for the PR and good to see you here. 😆
Left some suggestions. PTAL.
final Optional<VirtualHostBuilder> vhost = | ||
virtualHostBuilders.stream() | ||
.filter(v -> !v.defaultVirtualHost() && | ||
v.equalsHostnamePattern(hostAndPort.getHost(), |
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.
The hostname
is normalized thus this won't still find the builder if the name contains unicode.
hostnamePattern = IDN.toASCII(hostnamePattern, IDN.ALLOW_UNASSIGNED); |
So how about validating and normalizing it before we find it?
Then we can just set the hostnamePattern
and port
directly to VirtualHostBuilder
not to call HostAndPort.fromString()
and validate it again.
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.
Good idea. But, I don't fully understand your suggestion. Could you check I understand is correct?
Then we can just set the hostnamePattern and port directly to VirtualHostBuilder not to call HostAndPort.fromString() and validate it again.
- validate and normalize in
ServerBuilder.virtualHost(hostnamePattern)
- if exists on same hostname, return it
- if not exists,
VirtualHostBuilder.hostnamePattern(hostnamePattern, port)
calls VirtualHostBuilder.hostnamePatter(hostnamePattern, port)
sets directly hostnamePattern and port without validation and normalization
In 4, I'm worried about the hostnamePattern is able to be set without validation somewhere.
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.
In 4, I'm worried about the hostnamePattern is able to be set without validation somewhere.
That's a good question. I believe that if we make the method package-private, we don't have to worry about it because a user can't just use the method to set the properties directly.
If you worry about it, we can also add the validation logic in the method but I don't believe we really need it. 😉
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.
Oh, I didn't think about package-private
! great job 👍 Thank you for the suggestion!
core/src/main/java/com/linecorp/armeria/server/ServerBuilder.java
Outdated
Show resolved
Hide resolved
core/src/main/java/com/linecorp/armeria/server/ServerBuilder.java
Outdated
Show resolved
Hide resolved
final int port = hostAndPort.getPortOrDefault(-1); | ||
for (VirtualHostBuilder virtualHostBuilder : virtualHostBuilders) { | ||
if (!virtualHostBuilder.defaultVirtualHost() && | ||
virtualHostBuilder.equalsDefaultHostname(defaultHostname) && |
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.
What are your thoughts on utilizing hostnamePattern
and port
for the equality check and removing the defaultHostname
check? Since hostnamePattern
is solely used to identify the virtual host, I believe we can consider two virtual hosts as identical if their hostnamePattern
matches.
return DefaultRoutingContext.of(serverConfig.findVirtualHost(hostname, port), |
mappingBuilder.add(virtualHost.hostnamePattern(), virtualHost); |
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.
What do you think of raising an exception if a defaultHostname
is registered for the same hostnamePattern
before?
It may be controversial that defaultHostname
is ignored silently.
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.
That's a good suggestion. I think we can
- set the
defaultHostname
if the previousvirtualHostBuilder
does not have thedefaultHostname
- raise an exception if the
defaultHostname
of the previousvirtualHostBuilder
not null and It's not the same with the parameterdefaultHostname
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.
A couple thoughts regarding the proposal:
- Even before this PR, a
defaultHostname
could be ignored if there were multiple virtual hosts with the samehostnamePattern
- The suggested behavior tries to guarantee uniqueness of (
hostName
,defaultHostname
,port
). However, the mutability ofdefaultHostname
,hostnamePattern
,port
does not guarantee this.
Rather, I propose:
- All methods that can mutate
hostnamePattern
are deprecatedVirtualHostBuilder#hostnamePattern(String)
is deprecated
- All methods that do not receive a single
hostnamePattern
orport
are deprecatedServerBuilder#virtualHost(String,String)
is deprecated, since the additionaldefaultHostname
makes it unclear whichVirtualHostBuilder
is returned.ServerBuilder#withVirtualHost(Customizer)
is deprecated. It is not compatible with theVirtualHostBuilder
reuse functionality. If needed, we could add aServerBuilder#withVirtualHost(String, Customizer)
,ServerBuilder#withVirtualHost(int,Customizer)
instead.
This would make it clear that only hostnamePattern
or port
will be used for checking reusability of VirtualHostBuilder
.
In terms of implementation plan, I propose we assume that the @Deprecated
methods do not support VirtualHostBuilder
reusability. We can simply remove the deprecated methods in the next major release which gives a straightforward upgrade plan as well.
Regarding this PR, I propose that this method is simply deprecated and we only support ServerBuilder#virtualHost(String)
instead.
Thoughts @line/dx ?
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.
That's a good idea. 👍 It's time to cleanup the API.
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.
That sounds great to me.
If needed, we could add a ServerBuilder#withVirtualHost(String, Customizer)
It would be better than deprecation without a replacement. Some forks prefer explicit code blocks over the fluent style.
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.
I'm sorry for late checking.
Regarding this PR, I propose that this method is simply deprecated and we only support ServerBuilder#virtualHost(String) instead.
I understand that I need to apply changes to ServerBuilder#virtualHost(String)
in this PR. I'll remove the changes of ServerBuilder#virtualHost(String, String)
.
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.
I'll remove the changes of ServerBuilder#virtualHost(String, String).
Thanks!
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.
Thanks for the effort! Looks good overall 👍 👍 👍
final int port = hostAndPort.getPortOrDefault(-1); | ||
for (VirtualHostBuilder virtualHostBuilder : virtualHostBuilders) { | ||
if (!virtualHostBuilder.defaultVirtualHost() && | ||
virtualHostBuilder.equalsDefaultHostname(defaultHostname) && |
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.
A couple thoughts regarding the proposal:
- Even before this PR, a
defaultHostname
could be ignored if there were multiple virtual hosts with the samehostnamePattern
- The suggested behavior tries to guarantee uniqueness of (
hostName
,defaultHostname
,port
). However, the mutability ofdefaultHostname
,hostnamePattern
,port
does not guarantee this.
Rather, I propose:
- All methods that can mutate
hostnamePattern
are deprecatedVirtualHostBuilder#hostnamePattern(String)
is deprecated
- All methods that do not receive a single
hostnamePattern
orport
are deprecatedServerBuilder#virtualHost(String,String)
is deprecated, since the additionaldefaultHostname
makes it unclear whichVirtualHostBuilder
is returned.ServerBuilder#withVirtualHost(Customizer)
is deprecated. It is not compatible with theVirtualHostBuilder
reuse functionality. If needed, we could add aServerBuilder#withVirtualHost(String, Customizer)
,ServerBuilder#withVirtualHost(int,Customizer)
instead.
This would make it clear that only hostnamePattern
or port
will be used for checking reusability of VirtualHostBuilder
.
In terms of implementation plan, I propose we assume that the @Deprecated
methods do not support VirtualHostBuilder
reusability. We can simply remove the deprecated methods in the next major release which gives a straightforward upgrade plan as well.
Regarding this PR, I propose that this method is simply deprecated and we only support ServerBuilder#virtualHost(String)
instead.
Thoughts @line/dx ?
gentle ping @yejinio 🙇 |
1f4ca74
to
224907a
Compare
I've added a small commit which
Let me know if the changes don't make sense 🙇 |
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.
Changes look good to me 👍 👍 👍
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.
@yejinio Thanks for your contribution! 🚀🚀
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.
@yejinio Thank you very much for all your hard work! 🙇
Motivation:
I registered each virtual host with the same hostname, the registered routes cannot be not found. Because
VirtualHostBuilder
creates new builder even if hostname is the same. However, it does reuse them on the same port.So, I think it's better to reuse them on the same hostname.
Modifications:
ServerBuilder.virtualHost(hostnamePattern)
andServerBuilder.virtualHost(defaultHostname, hostnamePattern)
checks whether there isbuilders
with the same hostname. If there is, returns this builder.Result:
VirtualHostBuilder
on the same hostname.