-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Allow query parameters for ParseURL #1884
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
Conversation
This is in preparation for supporting query parameters in ParseURL: - use an expected *Options instance to execute assertions on - extract assertions into helper function - enable parallel testing - condense test table
This looks good, we could make code a little bit cleaner: type queryOptions struct {
q *url.Values
}
// Err returns the first encountered error.
func (q *queryOptions) Err() error {}
func (q *queryOptions) Int64(name string) (int64, ok) {}
q := queryOptions{q: u.Query()}
if db, ok := q.Int64("db"); ok {}
if maxRetries, ok := q.Int64("max_retries"); ok {}
if err := q.Err(); err != nil {
return err
} What do you think? |
Great suggestion. I'll start working on that. |
@vmihailenco Done. |
5edaee8
to
e611262
Compare
I have one question left: In the doc string, I've written
However, this code will currently fail: ParseURL("redis://user@localhost/?username=admin")
//=> redis: unexpected option: username I feel like, this is the correct behaviour, but it's inconsistent with the way other (duplicate) parameters are handled: opts, _ := ParseURL("redis://user@localhost/0?db=1")
//=> opts.Database == 1 We've got basically three options here:
@vmihailenco, do you have a preference? |
Looks like
I think this code should continue to fail (option #2). |
Okay, I'll update the doc string later, I'm currently a bit busy with different things. |
Before this change, ParseURL would only accept a very restricted set of URLs (it returned an error, if it encountered any parameter). This commit introduces the ability to process URLs like redis://localhost/1?dial_timeout=10s and similar. Go programs which were providing a configuration tunable (e.g. CLI flag, config entry or environment variable) to configure the Redis connection now don't need to perform this task themselves.
@vmihailenco Done. |
Thanks - this looks very good 👍 I am going to steal this for https://github.com/uptrace/bun/tree/master/driver/pgdriver configuration :) |
Sure, go ahead 😀 |
Background
In my Go programs, I usually want to modiffy the database connection options using CLI flags or environment variables. For example, to tune Postgres connections, I can set an environment variable like
PG="postgres://user@localhost:5432/testdb?sslmode=verify-full&connect_timeout=10" ./myprog
This is very handy for containerized applications.
In the Go program, one only needs to pass that string into
ParseConfig
:Issue
With the Go Redis library, this is not so simple:
Here, the library requires me to either setup and parse additional flags/env vars, or extract the parameters from the URL before passing it to
ParseURL
.Implementation details
This PR addresses this issue, by allowing (a subset of) the
Option
fields to be expressed as query parameters.I've settled on the following behaviour:
max_retries=2
→opt.MaxRetries == 2
pool_fifo=true
→opt.PoolFIFO == true
reflect
packageScheme
,Host
,UserInfo
fieldsbool
,int
,time.Duration
string
is notably absent, because allOption
string fields are already covered (but adding support is trivially easy)opt.TLSConfig
) are not supported yet. If they would ever be, someone needs to decide how to represent them as query parameters (cf.tls_config_insecure_skip_verify=true
vs.tls_config.insecure_skip_verify=true
vs.tls_config[insecure_skip_verify]=true
)opt.OnConnect
) are not supported, and probably will never betime.ParseDuration
read_timeout=60
==read_timeout=1m
→opt.ReadTimeout == time.Minute
redis://.../0?db=1&db=2
→opt.DB == 2