-
Notifications
You must be signed in to change notification settings - Fork 972
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
Fixes createSocket being called with null proxy when proxy is null #535
Fixes createSocket being called with null proxy when proxy is null #535
Conversation
@@ -63,7 +63,7 @@ public PlainConnectionSocketFactory() { | |||
|
|||
@Override | |||
public Socket createSocket(final Proxy proxy, final HttpContext context) throws IOException { | |||
return proxy != null ? new Socket(proxy) : new Socket(); |
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.
@Sineaggi This looks wrong. The check for the proxy being non null should be performed by the method.
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.
Then perhaps this code should be
return proxy != null ? new Socket(proxy) : createSocket(context);
As it stands, any overridden implementation of createSocket(HttpContext)
is ignored, which is a breaking change.
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.
@twarner-sofi No, it is not. It is used by the default method of the interface. There is no breaking change
@Internal
default Socket createSocket(Proxy proxy, HttpContext context) throws IOException {
return createSocket(context);
}
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 the interface, yes, but that delegation is not reflected in PlainConnectionSocketFactory's implementation of the method. This class is not final and thus users can extend it, overriding createSocket. If that is incorrect usage and this class was meant to be final, I think that should at least be documented in the class's javadoc.
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.
@twarner-sofi While PlainConnectionSocketFactory
is non final and can be extended, one must be aware of risks of tight coupling through inheritance and risks of subclassing a concrete class and overriding methods that were not meant for extension in the first place. Do not pin this problem on us.
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.
Okay, thanks for confirming that these methods are not meant for extension in the first place. It's unfortunate that they weren't marked final
, or documented as such, but that's fine now.
We'll look into making a fix PR for docker-java.
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 check for the proxy being non null should be performed by the method.
There are two overloads of the method createSocket
in the interface, one that takes a Proxy, the other one doesn't. I don't think it's obvious at first glance that the check for the proxy being non null should ever have to be performed by this method. The documentation for the method even says
via a proxy (generally SOCKS is expected)
which would imply that method is called via a proxy (i.e. the proxy is non-null).
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.
one must be aware of risks of tight coupling through inheritance and risks of subclassing a concrete class and overriding methods that were not meant for extension in the first place
The class in question has no private fields and no hidden internal logic, and has existed virtually unmodified since its creation in 2012. Without warning, this public and non-final class has had a breaking change made to its behavior in a patch release of this library.
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.
@Sineaggi There is no breaking change. The class remains fully API compatible. Any particular modality or implementation details have never been a part of the public contract. You abused class inheritance in your code.
@@ -206,7 +206,7 @@ public Socket createSocket(final HttpContext context) throws IOException { | |||
|
|||
@Override | |||
public Socket createSocket(final Proxy proxy, final HttpContext context) throws IOException { | |||
return proxy != null ? new Socket(proxy) : new Socket(); |
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.
@Sineaggi Same.
@Sineaggi So what? This method will get removed in the next major release. I do not see how this necessitates any additional checks at the higher level. Individual socket factories must be able to handle |
Where does it say that this method will be removed? I couldn't find anything in the javadocs or release notes.
Again, I couldn't find any documentation mentioning as such. Presently the wording would imply createSocket that doesn't take a proxy parameter would be called if there was no proxy, and the new method would be called if there is a proxy. |
If going forward the design of the connection factory class ought to use the new For example, like the following httpclient5/src/main/java/org/apache/hc/client5/http/ssl/SSLConnectionSocketFactory.java
return proxy != null ? new Socket(proxy) : createSocket(context); |
@Sineaggi Sure, I would. Feel free to raise a PR with the proposed changes. |
This is a follow-up to this fix 6d60624 where the null is handled in the implementation.
IMHO the null-check should be pulled out higher, when createSocket is called. As it stands, there's no way for
createSocket(HttpContext
to be called anymore. Any implementation ofConnectionSocketFactory
by way of extending/inheriting existing implementations (SSL or Plain) would get caught by having to override both createSocket(HttpContext) and createSocket(Proxy, HttpContext). This is the case for docker-java, and is causing this issue docker-java/docker-java#2290