-
Notifications
You must be signed in to change notification settings - Fork 120
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
Add support to unix sockets #153
Conversation
lib/finch.ex
Outdated
@@ -54,7 +54,8 @@ defmodule Finch do | |||
doc: """ | |||
These options are passed to `Mint.HTTP.connect/4` whenever a new connection is established. \ | |||
`:mode` is not configurable as Finch must control this setting. Typically these options are \ | |||
used to configure proxying, https settings, or connect timeouts. | |||
used to configure proxying, https settings, or connect timeouts. \ | |||
When connecting to unix sockets a hostname must be provided. |
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.
Not sure if it should add "localhost"
as the default hostname for this scenario or just leave it up to the client to specify one, any thoughts?
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 think it would be a much nicer API if we could add this as the default for socket connections
83cc0f7
to
147fb37
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.
Thanks for getting the ball rolling here! This is a great start, and it has helped uncover an issue with the API we were hoping to provide
lib/finch.ex
Outdated
@@ -54,7 +54,8 @@ defmodule Finch do | |||
doc: """ | |||
These options are passed to `Mint.HTTP.connect/4` whenever a new connection is established. \ | |||
`:mode` is not configurable as Finch must control this setting. Typically these options are \ | |||
used to configure proxying, https settings, or connect timeouts. | |||
used to configure proxying, https settings, or connect timeouts. \ | |||
When connecting to unix sockets a hostname must be provided. |
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 think it would be a much nicer API if we could add this as the default for socket connections
lib/finch.ex
Outdated
@@ -133,6 +135,9 @@ defmodule Finch do | |||
:default -> | |||
{:ok, destination} | |||
|
|||
{:local, unix_socket} -> | |||
{:ok, {:http, {:local, unix_socket}, 0}} |
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.
This is making me think that we might have to use a different format for the pool configuration, rather than just {:local, unix_socket}
. We can't assume it will be :http so I guess we should revisit the previous suggestion of using a scheme like http+unix://
or https+unix://
but I am definitely open to new ideas as well.
To sum it up, the issue is that pools are started based on the pool configuration. When a pool is started, it registers itself with the Registry, using the {scheme, host, port} as the key. Then when we make a request, based on the request uri, we get the same {scheme, host, port} tuple and use that to query the Registry for the corresponding pool. Therefore, in order to match the request to the correctly configured pool, we need to be able to extract the full {scheme, host, port} tuple from the key that we provide in the pool configuration map.
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.
Yeah, it's a real shame that http+unix://
isn't standardised. See whatwg/url#577.
As was mentioned before, I think a bit of a problem with the http+unix
scheme is the socket path vs resource path distinction needs to be made and it means either escaping the socket path which is ugly or figuring out the socket path which seems brittle.
Another idea is to explicitly mention schema in the pool config:
pools = %{
{:local, :http, path} # or {:http, {:local, path}}, {:http, path}, etc
}
Finch.build(:get, "http://localhost/v1.41/_ping", unix_socket: "/var/run/docker.sock")
|> Finch.request()
notice we have the http://
in our url so we can match that with the pool. But yeah, on the other hand it is a bit ugly that we're arbitrarily setting the hostname which seems to be ignored. (On the flip side, if there's a server implementation that cares about the hostname, this approach is beneficial.)
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.
Ah right, good point about distinguishing between the socket path and the resource path :( I also considered adding the protocol to the tuple that we provide in the pool config, but I did not like the fact that it would be so different from the args that are passed to Finch.build/5
. Maybe that is not such a big deal though?
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.
Using socket should just work with the lazy :default pool, right? I think it will and so I think that most users would not need to even explicitly configure it. And for those that do, it seems so niche use case that it is perhaps fine that it is a little ugly :)
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 point, in that case {:http, {:local, socket_path}}
seems the best to me. Maybe we should also allow Scratch that, the hostname should be provided via conn_opts if it should be something other than {:http, hostname, {:local, socket_path}}
in case the server requires a hostname other than localhost (maybe this would be necessary for TLS?)localhost
.
6247f99
to
a98bfee
Compare
a98bfee
to
3a1850b
Compare
This is ready for another review @sneako @wojtekmach |
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.
LGTM!
test/finch_test.exs
Outdated
|
||
start_supervised!({Finch, name: MyFinch}) | ||
|
||
Finch.build(:get, "http://localhost/", [], nil, unix_socket: socket_path) |
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.
Maybe we should add assert {:ok, %{status: 200}} =
to this case and the next one?
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 think it's good to ensure that the response was successfully parsed, I've added the asserts
Great work @cgerling ! Just a couple minor comments, but overall this looks good! |
Ah and it looks like there are a few things that credo is complaining about too (don't worry about the failing tests on 1.7.4/19.x, we need to fix that after some recent changes) |
91500b1
to
6cab10c
Compare
Co-authored-by: Wojtek Mach <[email protected]>
Thanks @cgerling ! |
Closes https://github.com/keathley/finch/issues/139
This PR doesn't add support to connect with UNIX sockets through HTTPS, I wasn't sure how to do it without changing a lot of stuff so let me know if there is a "right way" to implement it