@@ -3,9 +3,11 @@ package main
33import (
44 "encoding/json"
55 "flag"
6+ "fmt"
67 "io"
78 "log"
89 "net"
10+ "net/http"
911 "net/url"
1012 "os"
1113 "path/filepath"
@@ -107,6 +109,20 @@ func normalizeDashHelp(args []string) []string {
107109 return args
108110}
109111
112+ func parseEndpoint (endpoint string ) (* url.URL , error ) {
113+ u , err := url .ParseRequestURI (strings .TrimSuffix (endpoint , "/" ))
114+ if err != nil {
115+ return nil , err
116+ }
117+ if ! (u .Scheme == "http" || u .Scheme == "https" ) {
118+ return nil , errors .Newf ("Invalid scheme %s. Require http or https" , u .Scheme )
119+ }
120+ if u .Host == "" {
121+ return nil , errors .Newf ("Empty host" )
122+ }
123+ return u , nil
124+ }
125+
110126var cfg * config
111127
112128// config represents the config format.
@@ -118,12 +134,13 @@ type config struct {
118134 ProxyURL * url.URL
119135 ProxyPath string
120136 ConfigFilePath string
137+ EndpointURL * url.URL
121138}
122139
123140// apiClient returns an api.Client built from the configuration.
124141func (c * config ) apiClient (flags * api.Flags , out io.Writer ) api.Client {
125142 return api .NewClient (api.ClientOpts {
126- Endpoint : c . Endpoint ,
143+ EndpointURL : c . EndpointURL ,
127144 AccessToken : c .AccessToken ,
128145 AdditionalHeaders : c .AdditionalHeaders ,
129146 Flags : flags ,
@@ -133,7 +150,8 @@ func (c *config) apiClient(flags *api.Flags, out io.Writer) api.Client {
133150 })
134151}
135152
136- // readConfig reads the config file from the given path.
153+ // readConfig reads the config from the standard config file, the (deprecated) user-specified config file,
154+ // the environment variables, and the (deprecated) command-line flags.
137155func readConfig () (* config , error ) {
138156 cfgFile := * configPath
139157 userSpecified := * configPath != ""
@@ -189,9 +207,21 @@ func readConfig() (*config, error) {
189207 cfg .Proxy = envProxy
190208 }
191209
210+ // Lastly, apply endpoint flag if set
211+ if endpoint != nil && * endpoint != "" {
212+ cfg .Endpoint = * endpoint
213+ }
214+
215+ if endpointURL , err := parseEndpoint (cfg .Endpoint ); err != nil {
216+ return nil , errors .Newf ("invalid endpoint: %s" , cfg .Endpoint )
217+ } else {
218+ cfg .EndpointURL = endpointURL
219+ cfg .Endpoint = endpointURL .String ()
220+ }
221+
192222 if cfg .Proxy != "" {
193223
194- parseEndpoint := func (endpoint string ) (scheme string , address string ) {
224+ parseProxyEndpoint := func (endpoint string ) (scheme string , address string ) {
195225 parts := strings .SplitN (endpoint , "://" , 2 )
196226 if len (parts ) == 2 {
197227 return parts [0 ], parts [1 ]
@@ -205,7 +235,7 @@ func readConfig() (*config, error) {
205235 return slices .Contains (urlSchemes , scheme )
206236 }
207237
208- scheme , address := parseEndpoint (cfg .Proxy )
238+ scheme , address := parseProxyEndpoint (cfg .Proxy )
209239
210240 if isURLScheme (scheme ) {
211241 endpoint := cfg .Proxy
@@ -227,11 +257,19 @@ func readConfig() (*config, error) {
227257 return nil , errors .Newf ("Invalid proxy configuration: %w" , err )
228258 }
229259 if ! isValidUDS {
230- return nil , errors .Newf ("invalid proxy socket: %s" , path )
260+ return nil , errors .Newf ("Invalid proxy socket: %s" , path )
231261 }
232262 cfg .ProxyPath = path
233263 } else {
234- return nil , errors .Newf ("invalid proxy endpoint: %s" , cfg .Proxy )
264+ return nil , errors .Newf ("Invalid proxy endpoint: %s" , cfg .Proxy )
265+ }
266+ } else {
267+ // no SRC_PROXY; check for the standard proxy env variables HTTP_PROXY, HTTPS_PROXY, and NO_PROXY
268+ if u , err := http .ProxyFromEnvironment (& http.Request {URL : cfg .EndpointURL }); err != nil {
269+ // when there's an error, the value for the env variable is not a legit URL
270+ return nil , fmt .Errorf ("Invalid HTTP_PROXY or HTTPS_PROXY value: %w" , err )
271+ } else {
272+ cfg .ProxyURL = u
235273 }
236274 }
237275
@@ -242,20 +280,9 @@ func readConfig() (*config, error) {
242280 return nil , errConfigAuthorizationConflict
243281 }
244282
245- // Lastly, apply endpoint flag if set
246- if endpoint != nil && * endpoint != "" {
247- cfg .Endpoint = * endpoint
248- }
249-
250- cfg .Endpoint = cleanEndpoint (cfg .Endpoint )
251-
252283 return & cfg , nil
253284}
254285
255- func cleanEndpoint (urlStr string ) string {
256- return strings .TrimSuffix (urlStr , "/" )
257- }
258-
259286// isValidUnixSocket checks if the given path is a valid Unix socket.
260287//
261288// Parameters:
0 commit comments