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

Allow direct proxy configuration #435

Merged
merged 10 commits into from May 25, 2017
Merged

Conversation

leeavital
Copy link
Contributor

@leeavital leeavital commented May 24, 2017

This allows users to bypass the proxy settings set at the JVM with -Dhttps.proxyHost/-Dhttps.proxyPort. This can be useful if you are using a third-party library which needs to make proxied http calls, but the library does not allow you to set an external proxy.

Previously okhttp would default to using a direct connection if the proxy failed, but that changed in 3.5.0 (https://github.com/square/okhttp/blob/master/CHANGELOG.md)


This change is Reviewable

Copy link
Contributor

@ash211 ash211 left a comment

Choose a reason for hiding this comment

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

I think going direct instead of using a proxy is specified by passing an absent into the optional proxy configuration higher up in the API, on the ClientConfig.

Is leaving ClientConfig#proxy() empty not going direct?


/**
* The hostname and port of the HTTP/HTTPS Proxy. Recognized formats include those recognized by {@link
* com.google.common.net.HostAndPort}, for instance {@code foo.com:80}, {@code 192.168.3.100:8080}, etc.
*/
public abstract String hostAndPort();
public abstract Optional<String> hostAndPort();
Copy link
Contributor

Choose a reason for hiding this comment

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

this is an API break that would affect consumers

Copy link
Contributor Author

Choose a reason for hiding this comment

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

true. I can add a (deprecated) method that returns a non-optional String and throws when the type is direct. That should not break any existing consumers.

@leeavital
Copy link
Contributor Author

@ash211 ommiting the proxy setting will use ProxySelect.getDefault().select(uri), which will respect settings like http.proxyHost. I'm forced to use those flags because I'm using a third-party library which needs to be proxied, but doesn't let me set the proxy at the library level

@markelliot
Copy link
Contributor

markelliot commented May 24, 2017 via email

@leeavital
Copy link
Contributor Author

The third party library is forcing me to configure proxy settings globally. I need to tell service created by http-remoting to explicitly ignore those global settings.

@uschi2000
Copy link
Contributor

uschi2000 commented May 24, 2017 via email

@leeavital
Copy link
Contributor Author

Ok, could I can change/add to the names of the Type enum so it reads:

enum Type {
    noProxy, systemProxy, proxy
}

and leave the rest of my PR the same? I don't think that breaks any existing config

@leeavital
Copy link
Contributor Author

Actually, I think my current approach does this exactly what you want. the default is the system proxy, you can configure directly use of a special proxy or a direct proxy

@uschi2000
Copy link
Contributor

uschi2000 commented May 24, 2017

but the config space is a little weird, for instance i could say proxy=direct and still specify a hostAndIPort.

@leeavital
Copy link
Contributor Author

There are preconditions that prevent you from doing that

@uschi2000
Copy link
Contributor

let me summarize what i understand the possible valid configurations are:

usesSystemProxy:
  uris: 
    - https://foo

usesExplicitProxy:
  uris: 
    - https://foo
  proxy:
    hostAndPort: myProxy:8080

# same as above
usesExplicitProxy2:
  uris: 
    - https://foo
  proxy:
    type: http
    hostAndPort: myProxy:8080

usesNoProxyEvenIfSystemProxyIsSet:
  uris: 
    - https://foo
  proxy:
    type: direct

and these configurations are invalid:

invalidDirect:
  uris: 
    - https://foo
  proxy:
    type: direct
    hostAndPort: myProxy:8080

there are still undefined cases, e.g., type=http, but no hostAndPort given

@leeavital
Copy link
Contributor Author

You're right, that's a mistake on my part. Is the ask that I fix that (it should trigger a failure) or that I change the configuration further?

@leeavital
Copy link
Contributor Author

@uschi2000 the case you mentioned is handled correctly now

@ash211 I had to do some interesting naming because of erasure issues, but I managed to get it so the existing source API is unbroken

/**
* Use a direct connection. This option will bypass any JVM-level configured proxy settings.
*/
direct,
Copy link
Contributor

Choose a reason for hiding this comment

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

other enums in this project are UPPER_CASE, please do the same here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

These leak into the configuration, which usually doesn't contain upper case values. Glad to change, but that's why I had made this particular enum lowercase

Copy link
Contributor

Choose a reason for hiding this comment

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

SslConfiguration uses UPPER_CASE, i think. What are example of lower-case configs?

/**
* The hostname and port of the HTTP/HTTPS Proxy. Recognized formats include those recognized by {@link
* com.google.common.net.HostAndPort}, for instance {@code foo.com:80}, {@code 192.168.3.100:8080}, etc.
*/
public abstract String hostAndPort();
@JsonProperty("hostAndPort")
Copy link
Contributor

Choose a reason for hiding this comment

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

these are snake case host-and-port usually, but might also need to support hostAndPort for backcompat

Copy link
Contributor Author

Choose a reason for hiding this comment

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

See the builder specified below. This supports deserializing in snake-case and serializing in camel

Copy link
Contributor Author

Choose a reason for hiding this comment

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

do you mean deserializing the camel-cased hostAndPort? I don't think that was ever supported because of the annotation @JsonDeserialize(builder = ProxyConfiguration.Builder.class)

@@ -36,45 +36,105 @@
@Style(visibility = Style.ImplementationVisibility.PACKAGE, builder = "new")
public abstract class ProxyConfiguration {
Copy link
Contributor

Choose a reason for hiding this comment

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

please update the ServiceConfiguration#proxyConfiguration docs: if absent, uses system proxy configuration.


/**
* Credentials if the proxy needs authentication.
*/
public abstract Optional<BasicCredentials> credentials();

@Value.Default
Copy link
Contributor

Choose a reason for hiding this comment

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

document default.

Preconditions.checkArgument(host.hasPort(), "Given hostname does not contain a port number: " + host);
switch (type()) {
case http:
HostAndPort host = HostAndPort.fromString(maybeHostAndPort().get());
Copy link
Contributor

Choose a reason for hiding this comment

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

doesn't this NPE when type=http and no host is specified?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Nice catch yes

@leeavital
Copy link
Contributor Author

enum is now upper cased

}

if (credentials().isPresent()) {
Preconditions.checkArgument(type() == Type.HTTP, "credentials only valid for http proxies");
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: "for HTTP proxies"

switch (type()) {
case HTTP:
Preconditions.checkArgument(maybeHostAndPort().isPresent(), "host-and-port must be "
+ "configured for an http proxy");
Copy link
Contributor

Choose a reason for hiding this comment

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

HTTP

Copy link
Contributor

@uschi2000 uschi2000 left a comment

Choose a reason for hiding this comment

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

one last nit, sorry. otherwise looks good to me.

@uschi2000
Copy link
Contributor

@ash211 anything left regarding the serialization format?

@ash211
Copy link
Contributor

ash211 commented May 25, 2017

@uschi2000 I'm good as long as it's not a backcompat break! Doesn't look like it, but I'm not familiar with Jackson intricacies

@uschi2000 uschi2000 merged commit c26fc9f into palantir:develop May 25, 2017
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