blob: b613d24be7b148c8b7fcecddceccd70449e326b0 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 resolver
import (
"errors"
"log"
"net/url"
"fmt"
"github.com/apache/servicecomb-mesher/proxy/config"
"github.com/go-chassis/openlog"
)
var drMap = make(map[string]DestinationResolver)
//DestinationResolverPlugins is a map
var DestinationResolverPlugins map[string]func() DestinationResolver
//SelfEndpoint is a string
var SelfEndpoint = "#To be init#"
//DefaultPlugin is a constant which stores default plugin name
const DefaultPlugin = "host"
//ErrUnknownResolver is of type error
var ErrUnknownResolver = errors.New("unknown Destination Resolver")
//DestinationResolver is a interface with Resolve method
type DestinationResolver interface {
Resolve(remoteIP, host, rawURI string, header map[string]string) (string, string, error)
}
//DefaultDestinationResolver is a struct
//mesher as sidecar must use DefaultDestinationResolver
type DefaultDestinationResolver struct {
}
//Resolve resolves service's endpoint
//service may have multiple port for same protocol
func (dr *DefaultDestinationResolver) Resolve(remoteIP, host, rawURI string, header map[string]string) (string, string, error) {
u, err := url.Parse(rawURI)
if err != nil {
openlog.Error("Can not parse url: " + err.Error())
return "", "", err
}
if u.Host == "" {
return "", "", errors.New(`Invalid uri, please check:
1, For provider, mesher listens on external ip
2, Set http_proxy as mesher address, before sending request`)
}
if u.Host == SelfEndpoint {
return "", "", errors.New(`uri format must be: http://serviceName/api`)
}
return u.Hostname(), u.Port(), nil
}
//New function returns new DefaultDestinationResolver struct object
func New() DestinationResolver {
return &DefaultDestinationResolver{}
}
//GetDestinationResolver returns destinationResolver pointer
func GetDestinationResolver(name string) DestinationResolver {
return drMap[name]
}
//InstallDestinationResolverPlugin function installs new plugin
func InstallDestinationResolverPlugin(name string, newFunc func() DestinationResolver) {
DestinationResolverPlugins[name] = newFunc
log.Printf("Installed DestinationResolver Plugin, name=%s", name)
}
//SetDefaultDestinationResolver set the a default implementation for a protocol, so that you don't need to set config file
func SetDefaultDestinationResolver(name string, dr DestinationResolver) {
drMap[name] = dr
log.Printf("Installed default DestinationResolver for [%s]", name)
}
func init() {
DestinationResolverPlugins = make(map[string]func() DestinationResolver)
InstallDestinationResolverPlugin(DefaultPlugin, New)
SetDefaultDestinationResolver("http", &DefaultDestinationResolver{})
}
//Init function reads config and initiates it
func Init() error {
if config.GetConfig().Plugin != nil {
for name, v := range config.GetConfig().Plugin.DestinationResolver {
if v == "" {
v = DefaultPlugin
}
f, ok := DestinationResolverPlugins[v]
if !ok {
return fmt.Errorf("unknown destination resolver [%s]", v)
}
drMap[name] = f()
}
}
return nil
}