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

SPICE-0004: HTTP Proxy Support #5

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open

Conversation

bioball
Copy link
Contributor

@bioball bioball commented May 2, 2024

This is a continuation of the design discussion started here: apple/pkl#309

Implementation: apple/pkl#472

@bioball bioball changed the title Add SPICE for http proxy SPICE-0004: HTTP Proxy Support May 2, 2024

==== Environment Variables

Proxies will _not_ be configured via environment variables.
Copy link

Choose a reason for hiding this comment

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

I think this is a mistake. Env vars are the way to configure proxy settings for command-line tools. Nobody wants to configure each tool separately. I’m optimistic that the listed concerns have good enough solutions.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm open to the argument, but: another concern here is: how does this play with --env-var? What happens if you do:

pkl eval --env-var http_proxy=http://some.proxy foo.pkl

It feels like this shouldn't affect proxy settings, because this is ostensibly just a way to configure what read("env:") will return.

But if that doesn't affect the proxy, this is possibly a strange behavior:

# talk via the proxy
export http_proxy=http://some.proxy pkl eval foo.pkl

# does not talk via the proxy
pkl eval --env-var http_proxy=http://some.proxy foo.pkl

There's also plenty of languages/tools whose proxies aren't configured by env vars. Just some quick skimming (as far as I can tell):

  • Node.js
  • Java
  • Rust, Cargo
  • PHP

Copy link

Choose a reason for hiding this comment

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

Java supports OS proxy settings, and there are signs that env vars will be reconsidered. Honoring neither OS settings nor env vars will force users to script a solution specifically for Pkl.

Regarding --env-var, the behavior you described seems fine to me.

It would be very helpful to get input from frequent proxy users. I haven't used a proxy in over a decade.

Choose a reason for hiding this comment

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

Not sure I'm sold on configuring proxies via env vars. Nothing else in Pkl in configured using them, also, It may lead to "works on my machine" problems where you have the right env vars set.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Supporting OS proxy settings sounds more enticing than supporting envvar-based configuration, if that's possible.

proxy: Proxy?
----

==== `PklProject`

Choose a reason for hiding this comment

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

What’s the use case for this?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I am deploying into an environment that needs proxying. Instead of setting it up on my target machine, or setting it up via a script, I can just set it in my PklProject file.

Choose a reason for hiding this comment

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

Do you have evidence that this is useful? Is it practical to only have per-project proxy settings?

Choose a reason for hiding this comment

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

I think the rationale here is that settings.pkl is a user specific configuration, which only leaves PklProject and CLI/Evaluator options left for shared configs. Configuring your proxy every time via CLI doesn't seem ideal, so adding this settings to PklProject allows for a project-wide proxy configuration.

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 have evidence that this is useful? Is it practical to only have per-project proxy settings?

Yeah, this is something that was brought up as a desired use-case from some of our users.

* `--proxy` -- A proxy URL to connect to
* `--noproxy` -- A comma-separated list of hosts to not proxy.

==== pkl-gradle
Copy link

Choose a reason for hiding this comment

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

What’s the use case for Pkl proxy settings that differ from Gradle/JVM proxy settings?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I want to control pkl eval through Gradle, but I want it to otherwise behave exactly like my CLI does.

Copy link

Choose a reason for hiding this comment

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

The correct proxy settings depend on the network you’re on. Can you think of a use case where having different proxy settings for Gradle and the Gradle Pkl plugin is useful? I can’t.


To support this, `HttpClient#Builder` receives two new builder methods:

* `setProxySelector(java.net.ProxySelector proxySelector)`
Copy link

Choose a reason for hiding this comment

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

Is exposing ProxySelector really necessary? (For certificates, we managed to avoid dependencies on java.net classes.)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm open to ideas here!

Copy link

Choose a reason for hiding this comment

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

What motivated you to expose it?

Copy link
Contributor Author

@bioball bioball May 5, 2024

Choose a reason for hiding this comment

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

The goal is to allow users to configure Pkl's proxy the same way their application's proxy is configured. setProxy(proxyAddress, List<URI> noProxy) is our bespoke implementation. Having this method means that those that are already using ProxySelector can configure our client the same way.

Some prior art; both java.net.HttpClient and okhttp accept ProxySelector.

Copy link

Choose a reason for hiding this comment

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

Of course java.net.HttpClient accepts ProxySelector. But with every java.net type added, it becomes more difficult to ever have another implementation of org.pkl.util.http.HttpClient (say NettyHttpClient). It’s better to wait until there is a proven need for “those that are already using ProxySelector can configure our client the same way”, then make an informed decision. That’s why I didn’t expose HttpClient.sendAsync—it’s not yet needed, and with virtual threads added in Java 21, it may never be needed.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

But with every java.net type added, it becomes more difficult to ever have another implementation of org.pkl.util.http.HttpClient (say NettyHttpClient).

I'm not sure why this is desirable. Can you elaborate?

----

[[new-stdlib-module]]
==== New stdlib module: `pkl.Proxy`

Choose a reason for hiding this comment

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

Having a stdlib module just for proxy settings feels strange.
Can’t this be part of pkl.settings, even if pkl.Project needs it too (which I’m not convinced of)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Both pkl.settings and pkl.Project need this, and neither is a logical subset of the other, so it feels cleanest to put it in a separate module.

We can also put it in base.pkl, but that affects the global namespace, which doesn't feel great.

We also possibly should put redirect rules in there, so maybe this intermediary module should be called HttpSettings, with proxy and rewrite rules both being in there.

Copy link

Choose a reason for hiding this comment

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

If a new stdlib module is needed, its scope should definitely be wider than proxy settings.

Is any of the following attractive?

  1. pkl.Project extends pkl.settings
  2. pkl.Project has a property of type pkl.settings
  3. pkl.Project and pkl.settings have a common base module

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Out of those three, I think the third one might be a reasonable approach; will play around with that a little bit.


* HTTPS proxies
* SOCKS proxies
* Alternative authentication methods (e.g. setting the `Proxy-Authorization` header)
Copy link

Choose a reason for hiding this comment

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

Alternative to what? As far as I can tell, this spice doesn’t propose any auth support. (I believe this is the right way to start given how little is offered by the JDK.)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Originally, I figured we would just use basic auth, but I'm backing off on that idea due to security concerns.

Co-authored-by: translatenix <119817707+translatenix@users.noreply.github.com>
bioball added a commit to bioball/pkl that referenced this pull request May 3, 2024
Following design of SPICE-0004: apple/pkl-evolution#5
bioball added a commit to bioball/pkl that referenced this pull request May 3, 2024
Following design of SPICE-0004: apple/pkl-evolution#5

==== Environment Variables

Proxies will _not_ be configured via environment variables.

Choose a reason for hiding this comment

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

Not sure I'm sold on configuring proxies via env vars. Nothing else in Pkl in configured using them, also, It may lead to "works on my machine" problems where you have the right env vars set.

proxy: Proxy?
----

==== `PklProject`

Choose a reason for hiding this comment

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

I think the rationale here is that settings.pkl is a user specific configuration, which only leaves PklProject and CLI/Evaluator options left for shared configs. Configuring your proxy every time via CLI doesn't seem ideal, so adding this settings to PklProject allows for a project-wide proxy configuration.

[[new-stdlib-module]]
==== New stdlib module: `pkl.Proxy`

A new stdlib module is added called `pkl.Proxy`, that is used by `pkl.settings` and `pkl.Project`.

Choose a reason for hiding this comment

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

Calling it pkl.HttpSettings would future-proof if for when URL rewriting arrives, though this can be done in said SPICE.


== Alternatives considered

TBD

Choose a reason for hiding this comment

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

URL rewriting was a considered alternative, but after some thought we found out they don't fully overlap and there may be a need for both.

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

3 participants