139 lines
3.1 KiB
Go
139 lines
3.1 KiB
Go
package service_http
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"net/http"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/eolinker/eosc"
|
|
"github.com/eolinker/goku-eosc/upstream"
|
|
|
|
http_context "github.com/eolinker/goku-eosc/node/http-context"
|
|
|
|
"github.com/eolinker/goku-eosc/service"
|
|
)
|
|
|
|
var (
|
|
ErrorStructType = errors.New("error struct type")
|
|
)
|
|
|
|
type serviceWorker struct {
|
|
id string
|
|
name string
|
|
driver string
|
|
desc string
|
|
timeout time.Duration
|
|
rewriteURL string
|
|
retry int
|
|
scheme string
|
|
proxyAddr string
|
|
upstream upstream.IUpstream
|
|
}
|
|
|
|
//Id 返回服务实例 worker id
|
|
func (s *serviceWorker) Id() string {
|
|
return s.id
|
|
}
|
|
|
|
func (s *serviceWorker) Start() error {
|
|
return nil
|
|
}
|
|
|
|
//Reset 重置服务实例的配置
|
|
func (s *serviceWorker) Reset(conf interface{}, workers map[eosc.RequireId]interface{}) error {
|
|
data, ok := conf.(*Config)
|
|
if !ok {
|
|
return fmt.Errorf("need %s,now %s", eosc.TypeNameOf((*Config)(nil)), eosc.TypeNameOf(conf))
|
|
}
|
|
if worker, has := workers[data.Upstream]; has {
|
|
s.desc = data.Desc
|
|
s.timeout = time.Duration(data.Timeout) * time.Millisecond
|
|
s.rewriteURL = data.RewriteURL
|
|
s.retry = data.Retry
|
|
s.scheme = data.Scheme
|
|
u, ok := worker.(upstream.IUpstream)
|
|
if ok {
|
|
s.upstream = u
|
|
return nil
|
|
}
|
|
} else {
|
|
worker, has = workers[eosc.RequireId(fmt.Sprintf("%s@%s", data.Upstream, "upstream"))]
|
|
if has {
|
|
s.desc = data.Desc
|
|
s.timeout = time.Duration(data.Timeout) * time.Millisecond
|
|
s.rewriteURL = data.RewriteURL
|
|
s.retry = data.Retry
|
|
s.scheme = data.Scheme
|
|
u, ok := worker.(upstream.IUpstream)
|
|
if ok {
|
|
s.upstream = u
|
|
return nil
|
|
}
|
|
return nil
|
|
}
|
|
}
|
|
return errors.New("fail to create serviceWorker")
|
|
|
|
}
|
|
|
|
func (s *serviceWorker) Stop() error {
|
|
return nil
|
|
}
|
|
|
|
//CheckSkill 检查目标能力是否存在
|
|
func (s *serviceWorker) CheckSkill(skill string) bool {
|
|
return service.CheckSkill(skill)
|
|
}
|
|
|
|
//Name 返回服务名
|
|
func (s *serviceWorker) Name() string {
|
|
return s.name
|
|
}
|
|
|
|
//Desc 返回服务的描述
|
|
func (s *serviceWorker) Desc() string {
|
|
return s.desc
|
|
}
|
|
|
|
//Retry 返回服务的重试次数
|
|
func (s *serviceWorker) Retry() int {
|
|
return s.retry
|
|
}
|
|
|
|
//Timeout 返回服务的超时时间
|
|
func (s *serviceWorker) Timeout() time.Duration {
|
|
return s.timeout
|
|
}
|
|
|
|
//Scheme 返回服务的scheme
|
|
func (s *serviceWorker) Scheme() string {
|
|
return s.scheme
|
|
}
|
|
|
|
//ProxyAddr 返回服务的代理地址
|
|
func (s *serviceWorker) ProxyAddr() string {
|
|
return s.proxyAddr
|
|
}
|
|
|
|
//Handle 将服务发送到负载
|
|
func (s *serviceWorker) Handle(w http.ResponseWriter, r *http.Request, router service.IRouterRule) error {
|
|
// 构造context
|
|
ctx := http_context.NewContext(r, w)
|
|
// 设置目标URL
|
|
ctx.ProxyRequest.SetTargetURL(recombinePath(r.URL.Path, router.Location(), s.rewriteURL))
|
|
response, err := s.upstream.Send(ctx, s)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
fmt.Println(string(response.Body()))
|
|
return nil
|
|
}
|
|
|
|
//recombinePath 生成新的目标URL
|
|
func recombinePath(requestURL, location, targetURL string) string {
|
|
newRequestURL := strings.Replace(requestURL, location, "", 1)
|
|
return fmt.Sprintf("%s/%s", strings.TrimSuffix(targetURL, "/"), strings.TrimPrefix(newRequestURL, "/"))
|
|
}
|