pkg/client: fix method to find a server in the config

http://camlistore.org/issue/325

Change-Id: I4aa6d5103848b73ed169ab7d7de3a60a33723b79
This commit is contained in:
mpl 2014-01-06 22:14:46 -08:00
parent 8a970d23f0
commit 3f13d1a043
4 changed files with 102 additions and 21 deletions

View File

@ -126,7 +126,7 @@ const maxParallelHTTP = 5
// The provided server is either "host:port" (assumed http, not https) or a URL prefix, with or without a path, or a server alias from the client configuration file. A server alias should not be confused with a hostname, therefore it cannot contain any colon or period.
// Errors are not returned until subsequent operations.
func New(server string) *Client {
if !isHostname(server) {
if !isURLOrHostPort(server) {
configOnce.Do(parseConfig)
serverConf, ok := config.Servers[server]
if !ok {
@ -560,10 +560,11 @@ func (c *Client) blobPrefix() (string, error) {
return pfx, nil
}
// discoRoot returns the user defined server for this client. It prepends "https://" if no scheme was specified.
func (c *Client) discoRoot() string {
s := c.server
if !strings.HasPrefix(s, "http") {
s = "http://" + s
s = "https://" + s
}
return s
}

View File

@ -99,7 +99,7 @@ func parseConfig() {
for alias, vei := range servers {
// An alias should never be confused with a host name,
// so we forbid anything looking like one.
if isHostname(alias) {
if isURLOrHostPort(alias) {
log.Fatalf("Server alias %q looks like a hostname; \".\" or \";\" are not allowed.", alias)
}
serverMap, ok := vei.(map[string]interface{})
@ -125,8 +125,8 @@ func parseConfig() {
}
}
// isHostname return true if s looks like a host name, i.e it has at least a scheme or contains a period or a colon.
func isHostname(s string) bool {
// isURLOrHostPort returns true if s looks like a URL, or a hostname, i.e it starts with a scheme and/or it contains a period or a colon.
func isURLOrHostPort(s string) bool {
return strings.HasPrefix(s, "http://") ||
strings.HasPrefix(s, "https://") ||
strings.Contains(s, ".") || strings.Contains(s, ":")
@ -213,8 +213,10 @@ func serverKeyId() string {
return keyId
}
// cleanServer returns the canonical URL of the provided server, which must be a URL, IP, host (with dot), or host/ip:port.
// The returned canonical URL will have trailing slashes removed and be prepended with "https://" if no scheme is provided.
func cleanServer(server string) string {
if !isHostname(server) {
if !isURLOrHostPort(server) {
log.Fatalf("server %q does not look like a server address and could be confused with a server alias. It should look like [http[s]://]foo[.com][:port] with at least one of the optional parts.", server)
}
// Remove trailing slash if provided.
@ -235,7 +237,7 @@ func serverOrDie() string {
return cleanServer(s)
}
if flagServer != "" {
if !isHostname(flagServer) {
if !isURLOrHostPort(flagServer) {
configOnce.Do(parseConfig)
serverConf, ok := config.Servers[flagServer]
if ok {
@ -276,8 +278,7 @@ func (c *Client) useTLS() bool {
return strings.HasPrefix(c.server, "https://")
}
// SetupAuth sets the client's authMode from the client
// configuration file or from the environment.
// SetupAuth sets the client's authMode from the client configuration file or from the environment.
func (c *Client) SetupAuth() error {
// env var always takes precendence
authMode, err := auth.FromEnv()
@ -299,17 +300,14 @@ func (c *Client) SetupAuth() error {
return err
}
// serverAuth returns the auth scheme for server from the config, or the empty string if the server was not found in the config.
func serverAuth(server string) string {
configOnce.Do(parseConfig)
if config == nil {
alias := config.Alias(server)
if alias == "" {
return ""
}
for _, serverConf := range config.Servers {
if serverConf.Server == server {
return serverConf.Auth
}
}
return ""
return config.Servers[alias].Auth
}
// SetupAuthFromString configures the clients authentication mode from
@ -420,14 +418,14 @@ func (c *Client) initTrustedCerts() {
}
}
// serverTrustedCerts returns the trusted certs for server from the config.
func serverTrustedCerts(server string) []string {
configOnce.Do(parseConfig)
for _, serverConf := range config.Servers {
if serverConf.Server == server {
return serverConf.TrustedCerts
}
alias := config.Alias(server)
if alias == "" {
return nil
}
return nil
return config.Servers[alias].TrustedCerts
}
func (c *Client) getTrustedCerts() []string {

63
pkg/client/config_test.go Normal file
View File

@ -0,0 +1,63 @@
/*
Copyright 2014 The Camlistore Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package client
import (
"testing"
"camlistore.org/pkg/types/clientconfig"
)
func TestAliasFromConfig(t *testing.T) {
servers := map[string]*clientconfig.Server{
"foo": {
Server: "http://foo.com",
},
"foobar": {
Server: "http://foo.com/bar",
},
"foobaz": {
Server: "http://foo.com/baz",
},
"foobarlong": {
Server: "http://foo.com/bar/long",
},
}
config := &clientconfig.Config{
Servers: servers,
}
urlWant := map[string]string{
"http://foo.com/bs": "foo",
"http://foo.com": "foo",
"http://foo.com/bar/index-mysql": "foobar",
"http://foo.com/bar": "foobar",
"http://foo.com/baz/index-kv": "foobaz",
"http://foo.com/baz": "foobaz",
"http://foo.com/bar/long/disco": "foobarlong",
"http://foo.com/bar/long": "foobarlong",
}
for url, want := range urlWant {
alias := config.Alias(url)
if alias == "" {
t.Errorf("url %v matched nothing, wanted %v", url, want)
continue
}
if alias != want {
t.Errorf("url %v matched %v, wanted %v", url, alias, want)
}
}
}

View File

@ -17,6 +17,10 @@ limitations under the License.
// Package clientconfig provides types related to the client configuration file.
package clientconfig
import (
"strings"
)
// Config holds the values from the JSON client config file.
type Config struct {
Servers map[string]*Server `json:"servers"` // maps server alias to server config.
@ -32,3 +36,18 @@ type Server struct {
IsDefault bool `json:"default,omitempty"` // whether this server is the default one.
TrustedCerts []string `json:"trustedCerts,omitempty"` // list of trusted certificates fingerprints.
}
// Alias returns the alias of the server from conf that matches server, or the empty string if no match. A match means the server from the config is a prefix of the input server. The longest match prevails.
func (conf *Config) Alias(server string) string {
longestMatch := ""
serverAlias := ""
for alias, serverConf := range conf.Servers {
if strings.HasPrefix(server, serverConf.Server) {
if len(serverConf.Server) > len(longestMatch) {
longestMatch = serverConf.Server
serverAlias = alias
}
}
}
return serverAlias
}