vaya al complemento 1.8 use una interfaz personalizada

Quiero usar una interfaz personalizada basada en el complemento go, pero descubrí que no es compatible.

Definición de filtro.
package filter

import (
    "net/http"

    "github.com/valyala/fasthttp"
)

// Context filter context
type Context interface {
    SetStartAt(startAt int64)
    SetEndAt(endAt int64)
    GetStartAt() int64
    GetEndAt() int64

    GetProxyServerAddr() string
    GetProxyOuterRequest() *fasthttp.Request
    GetProxyResponse() *fasthttp.Response
    NeedMerge() bool

    GetOriginRequestCtx() *fasthttp.RequestCtx

    GetMaxQPS() int

    ValidateProxyOuterRequest() bool

    InBlacklist(ip string) bool
    InWhitelist(ip string) bool

    IsCircuitOpen() bool
    IsCircuitHalf() bool

    GetOpenToCloseFailureRate() int
    GetHalfTrafficRate() int
    GetHalfToOpenSucceedRate() int
    GetOpenToCloseCollectSeconds() int

    ChangeCircuitStatusToClose()
    ChangeCircuitStatusToOpen()

    RecordMetricsForRequest()
    RecordMetricsForResponse()
    RecordMetricsForFailure()
    RecordMetricsForReject()

    GetRecentlyRequestSuccessedCount(sec int) int
    GetRecentlyRequestCount(sec int) int
    GetRecentlyRequestFailureCount(sec int) int
}

// Filter filter interface
type Filter interface {
    Name() string

    Pre(c Context) (statusCode int, err error)
    Post(c Context) (statusCode int, err error)
    PostErr(c Context)
}

// BaseFilter base filter support default implemention
type BaseFilter struct{}

// Pre execute before proxy
func (f BaseFilter) Pre(c Context) (statusCode int, err error) {
    return http.StatusOK, nil
}

// Post execute after proxy
func (f BaseFilter) Post(c Context) (statusCode int, err error) {
    return http.StatusOK, nil
}

// PostErr execute proxy has errors
func (f BaseFilter) PostErr(c Context) {

}

Este paquete está en mi proyecto de aplicación go.

cargar archivo de complemento
package proxy

import (
    "errors"
    "plugin"
    "strings"

    "github.com/fagongzi/gateway/pkg/conf"
    "github.com/fagongzi/gateway/pkg/filter"
)

var (
    // ErrKnownFilter known filter error
    ErrKnownFilter = errors.New("unknow filter")
)

const (
    // FilterHTTPAccess access log filter
    FilterHTTPAccess = "HTTP-ACCESS"
    // FilterHeader header filter
    FilterHeader = "HEAD" // process header fiter
    // FilterXForward xforward fiter
    FilterXForward = "XFORWARD"
    // FilterBlackList blacklist filter
    FilterBlackList = "BLACKLIST"
    // FilterWhiteList whitelist filter
    FilterWhiteList = "WHITELIST"
    // FilterAnalysis analysis filter
    FilterAnalysis = "ANALYSIS"
    // FilterRateLimiting limit filter
    FilterRateLimiting = "RATE-LIMITING"
    // FilterCircuitBreake circuit breake filter
    FilterCircuitBreake = "CIRCUIT-BREAKE"
    // FilterValidation validation request filter
    FilterValidation = "VALIDATION"
)

func newFilter(filterSpec *conf.FilterSpec) (filter.Filter, error) {
    if filterSpec.External {
        return newExternalFilter(filterSpec)
    }

    input := strings.ToUpper(filterSpec.Name)

    switch input {
    case FilterHTTPAccess:
        return newAccessFilter(), nil
    case FilterHeader:
        return newHeadersFilter(), nil
    case FilterXForward:
        return newXForwardForFilter(), nil
    case FilterAnalysis:
        return newAnalysisFilter(), nil
    case FilterBlackList:
        return newBlackListFilter(), nil
    case FilterWhiteList:
        return newWhiteListFilter(), nil
    case FilterRateLimiting:
        return newRateLimitingFilter(), nil
    case FilterCircuitBreake:
        return newCircuitBreakeFilter(), nil
    case FilterValidation:
        return newValidationFilter(), nil
    default:
        return nil, ErrKnownFilter
    }
}

func newExternalFilter(filterSpec *conf.FilterSpec) (filter.Filter, error) {
    p, err := plugin.Open(filterSpec.ExternalPluginFile)
    if err != nil {
        return nil, err
    }

    s, err := p.Lookup("NewExternalFilter")
    if err != nil {
        return nil, err
    }

    sf := s.(func() (filter.Filter, error))
    return sf()
}

Este es el código del complemento de carga en mi proyecto de aplicación go

package main

import (
    "C"
    "strings"
    "time"

    "github.com/CodisLabs/codis/pkg/utils/log"
    "github.com/fagongzi/gateway/pkg/filter"
    "github.com/valyala/fasthttp"
)

// AccessFilter record the http access log
// log format: $remoteip "$method $path" $code "$agent" $svr $cost
type AccessFilter struct {
}

// NewExternalFilter create a External filter
func NewExternalFilter() (filter.Filter, error) {
    return &AccessFilter{}, nil
}

// Name return name of this filter
func (f *AccessFilter) Name() string {
    return "HTTP-ACCESS"
}

// Pre pre process
func (f *AccessFilter) Pre(c filter.Context) (statusCode int, err error) {
    return 200, nil
}

// Post execute after proxy
func (f *AccessFilter) Post(c filter.Context) (statusCode int, err error) {
    cost := (c.GetStartAt() - c.GetEndAt())

    log.Infof("%s %s \"%s\" %d \"%s\" %s %s",
        GetRealClientIP(c.GetOriginRequestCtx()),
        c.GetOriginRequestCtx().Method(),
        c.GetProxyOuterRequest().RequestURI(),
        c.GetProxyResponse().StatusCode(),
        c.GetOriginRequestCtx().UserAgent(),
        c.GetProxyServerAddr(),
        time.Duration(cost))

    return 200, nil
}

// PostErr post error process
func (f *AccessFilter) PostErr(c filter.Context) {

}

// GetRealClientIP get read client ip
func GetRealClientIP(ctx *fasthttp.RequestCtx) string {
    xforward := ctx.Request.Header.Peek("X-Forwarded-For")
    if nil == xforward {
        return strings.SplitN(ctx.RemoteAddr().String(), ":", 2)[0]
    }

    return strings.SplitN(string(xforward), ",", 2)[0]
}

Esta es la definición de complemento, está en mi proyecto de complemento. El proyecto de complemento y el proyecto de aplicación go son proyectos diferentes.

Encontré errores:
panic: interface conversion: plugin.Symbol is func() (filter.Filter, error), not func() (filter.Filter, error)

Puede encontrar el código en este proyecto https://github.com/fagongzi/gateway/tree/go18-plugin-support.

filter.Filter está en paquete / paquete de filtro.load plugin file en proxy / factory.goplugin go file Está en otro proyecto.

Respuestas a la pregunta(1)

Su respuesta a la pregunta