Repository: hasura/graphql-engine
File: cli/cli.go (Go)

Code before:
	// APIPaths (optional) API paths for server
	APIPaths *ServerAPIPaths `yaml:"api_paths,omitempty"`

	ParsedEndpoint *url.URL `yaml:"-"`
}

// GetVersionEndpoint provides the url to contact the version API
func (s *ServerConfig) GetVersionEndpoint() string {
	nurl := *s.ParsedEndpoint
	nurl.Path = path.Join(nurl.Path, s.APIPaths.Version)
	return nurl.String()
}

// ParseEndpoint ensures the endpoint is valid.
func (s *ServerConfig) ParseEndpoint() error {
	nurl, err := url.ParseRequestURI(s.Endpoint)
	if err != nil {
		return err
	}
	s.ParsedEndpoint = nurl
	return nil
}

// GetServerClient returns the http client for server
func (s *ServerConfig) GetServerClient(config *tls.Config) *http.Client {
	if config != nil {
		tr := &http.Transport{TLSClientConfig: config}
		client := &http.Client{Transport: tr}
		return client
	} else {
		client := &http.Client{Transport: http.DefaultTransport}
		return client
	}
}

// Config represents configuration required for the CLI to function
type Config struct {
	// Version of the config.
	Version ConfigVersion `yaml:"version,omitempty"`

	// ServerConfig to be used by CLI to contact server.
	ServerConfig `yaml:",inline"`

	// MetadataDirectory defines the directory where the metadata files were stored.
	MetadataDirectory string `yaml:"metadata_directory,omitempty"`
	// MigrationsDirectory defines the directory where the migration files were stored.
	MigrationsDirectory string `yaml:"migrations_directory,omitempty"`
	// ActionConfig defines the config required to create or generate codegen for an action.
	ActionConfig *types.ActionExecutionConfig `yaml:"actions,omitempty"`
}


Review comment (suggestion):
```suggestion
	client := &http.Client{Transport: http.DefaultTransport}
	if config != nil {
	    tr := &http.Transport{TLSClientConfig: config}
	    client.Transport = tr
	}
	return client
```

Code after:
	// APIPaths (optional) API paths for server
	APIPaths *ServerAPIPaths `yaml:"api_paths,omitempty"`
	// InsecureSkipTLSVerify - indicates if TLS verification is disabled or not.
	InsecureSkipTLSVerify bool `yaml:"insecure_skip_tls_verify,omitempty"`
	// CAPath - Path to a cert file for the certificate authority
	CAPath string `yaml:"certificate_authority,omitempty"`

	ParsedEndpoint *url.URL `yaml:"-"`

	TLSConfig *tls.Config `yaml:"-"`

	HTTPClient *http.Client `yaml:"-"`
}

// GetVersionEndpoint provides the url to contact the version API
func (s *ServerConfig) GetVersionEndpoint() string {
	nurl := *s.ParsedEndpoint
	nurl.Path = path.Join(nurl.Path, s.APIPaths.Version)
	return nurl.String()
}

// GetQueryEndpoint provides the url to contact the query API
func (s *ServerConfig) GetQueryEndpoint() string {
	nurl := *s.ParsedEndpoint
	nurl.Path = path.Join(nurl.Path, s.APIPaths.Query)
	return nurl.String()
}

// ParseEndpoint ensures the endpoint is valid.
func (s *ServerConfig) ParseEndpoint() error {
	nurl, err := url.ParseRequestURI(s.Endpoint)
	if err != nil {
		return err
	}
	s.ParsedEndpoint = nurl
	return nil
}

// SetTLSConfig - sets the TLS config
func (s *ServerConfig) SetTLSConfig() error {
	if s.InsecureSkipTLSVerify {
		s.TLSConfig = &tls.Config{InsecureSkipVerify: true}
	}
	if s.CAPath != "" {
		// Get the SystemCertPool, continue with an empty pool on error
		rootCAs, _ := x509.SystemCertPool()
		if rootCAs == nil {
			rootCAs = x509.NewCertPool()
		}
		// read cert
		certPath, _ := filepath.Abs(s.CAPath)