front

package module
v0.1.20260225024405 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 25, 2026 License: MIT Imports: 49 Imported by: 0

README

front

这是一个简单的http/https/ws/wss均衡负载、故障转移路由/代理,通过刷新配置不中断地:

  • 监听占用等待
  • 动态后端
  • 路径继承
  • 自定权重
  • 故障转移
  • 自定义头
  • 多种轮询
  • 请求路径过滤
  • 请求头过滤
  • 请求数据过滤

支持嵌入到其他项目中/独立运行

命令行参数:

Usage of ./main:
  -adminPath string
        adminPath, eg:/123/12/
  -adminPort int
        adminPort, eg:10908
  -c string
        config file (default "main.json")
  -dbFile string
        dbFile, eg./log/20060102150405.sqlite
  -decrypt string
        decrypt stdin with pri.pem, and output stdout
  -encrypt string
        encrypt stdin with pub.pem, and output stdout
  -genKey
        gen new pub.pem and pri.pem
  -logFile string
        logFile
  -noDebugLog
        noDebugLog
  -noLog
        noLog
  -reload
        reload, when adminPort/adminPath set
  -restart
        restart, when adminPort/adminPath set
  -stop
        stop, when adminPort/adminPath set

示例:

[
    {
        "addr": "127.0.0.1:10000",
        "routes": [
            {
                "name": "route1",
                "path": ["/"],
                "pathAdd": true,
                "filiters": [{
                    "reqUri": {
                        "accessRule": "!{stop}",
                        "items": {
                            "stop": "(main\\.json)"
                        }
                    }
                }],
                "backs": [
                    {
                        "name": "back1",
                        "to": "./",
                        "weight": "1"
                    }
                ]
            }
        ]
    }
]
curl http://127.0.0.1:10000/
<!doctype html>
<meta name="viewport" content="width=device-width">
<pre>
<a href="front.run">front.run</a>
<a href="main.json">main.json</a>
<a href="main.log">main.log</a>
</pre>

curl http://127.0.0.1:10000/main.json -I
HTTP/1.1 403 Forbidden
X-Front-Error: ErrPatherCheckFail
Date: Wed, 30 Oct 2024 17:50:22 GMT

curl http://127.0.0.1:10000/main.log -I
HTTP/1.1 200 OK
Accept-Ranges: bytes
Content-Length: 1700014
Content-Type: text/x-log; charset=utf-8
Last-Modified: Wed, 30 Oct 2024 17:51:23 GMT
Date: Wed, 30 Oct 2024 17:51:23 GMT

处理流程:

请求将从上至下尝试route的filiter(reqAddr、reqHost、reqUri、reqHeader),匹配成功时,再根据route中back的filiter进行过滤,并按rollRule进行排序,然后逐个尝试,若某个back成功响应,则结束本次请求的处理

配置:

为json数组格式[],下面为数组中的其中一个{},下述字段倾斜的,表示不会根据配置动态加载

config:

  • addr: string 监听端口 例:0.0.0.0:8081
  • matchRule: string 匹配规则,默认prefixprefix:当未匹配到时,返回最近的/匹配, all:当未匹配到时,返回404
  • reqIdLoop: uint 请求id环大小,用于日志识别请求,默认1000
  • copyBlocks:{} 转发的块
    • size: string 转发的块大小,默认16K
    • num: int 转发的块数量,默认1000
  • retryBlocks: {} 重试, 当停用时,不进行重试。其他情况:1.当所有块都在使用中时,不进行重试。2.当请求没有Content-Length时,将会重试。
    • size: string 重试的块大小,当请求body超过配置的大小时,将会导致无法继续失败回落,默认1M
    • num: int 重试的块数量,默认0,为0时停用重试
  • tls: {} 启用tls, 默认空
    • pub: string 公钥pem路径,支持从http/https获取
    • key: string 私钥pem路径,支持从http/https获取
    • decrypt: []string cmd解密key,公/私钥会通过stdin输入,并使用stdout输出作为实际使用公/私钥,为空时不执行
  • routes: [] 路由
    • name: string 路由名称,将在日志中显示
    • path: []string 路由路径
    • rollRule: string 可选
      • order(按顺序,每次都从第一个开始尝试)
      • loop(轮流)
      • disableC_MinFirst(禁用数较少的优先)
      • dealingC_MinFirst(连接数较少的优先)
      • chosenC_MinFirst(被选择较少的优先)
      • (使用rand.Shuffle随机,默认)
    • alwaysUp: bool 总是在线,当所有后端都在禁用时,启用被禁用次数最少的一个后端
    • setting... 将会给backs默认值
    • backs: [] 后端
      • name: string 后端名称,将在日志中显示
      • to: string 后端地址,说明如下:
        • 为空时,将会默认返回200
        • 含有://时,例s://www.baidu.com,会根据客户端自动添加http or ws在地址前
        • 不含://时,将会尝试解析成本地文件,当指向zip文件,将尝试读取
      • weight: string uint 权重,按routes中的全部back的权重比分配,当权重为0时,将停止新请求的进入
      • alwaysUp: bool 总是在线
      • setting...

setting: setting代指下述各配置

  • pathAdd: bool 将客户端访问的路径附加在path上 例:/api/req => /ws => /ws/api/req

  • splicing: int 当客户端支持cookie时,将会固定使用后端多少秒,默认不启用

  • ctxToSec: float64 当后端响应超过(ws则指初次返回时间)指定秒,将会errBanSec。由于请求已发送,为避免重复请求,故不重试,响应504

  • errToSec: float64 当得到后端响应时,超过(ws则指初次返回时间)指定秒,将会errBanSec

  • errBanSec: int 当后端错误时(指连接失败,不指后端错误响应),将会禁用若干秒

  • insecureSkipVerify: bool 忽略不安全的tls证书

  • verifyPeerCer: string 路径,校验服务器证书,使用intermediate_ca

  • proxy: string 使用proxy进行请求,支持socks5:\\http:\\https:\\(仅http、https、ws、wss有效)

  • filiters: []

    filiters中同个{}为和关系,不同{}为或关系

    • reqAddr:{} 请求后端前,请求Addr过滤器
      • accessRule:string 布尔表达式,为true时才通过,例{id}|(!{id2}&{id3})
      • items: map[string]string
        • id: matchExp
    • reqHost:{} 请求后端前,请求Host过滤器
      • accessRule:string 布尔表达式,为true时才通过,例{id}|(!{id2}&{id3})
      • items: map[string]string
        • id: matchExp
    • reqUri:{} 请求后端前,请求路径过滤器
      • accessRule:string 布尔表达式,为true时才通过,例{id}|(!{id2}&{id3})
      • items: map[string]string
        • id: matchExp
    • reqHeader:{} 请求后端前,请求头处理器
      • accessRule:string 布尔表达式,为true时才通过
      • items: map[string]{}
        • id:
          • key: string header头
          • matchExp: string
    • resHeader:{} 返回后端的响应前,请求头处理器
      • accessRule:string 布尔表达式,为true时才通过
      • items: map[string]{}
        • id:
          • key: string header头
          • matchExp: string
    • reqBody:{} 请求后端前,请求数据过滤器(仅route层有效)
      • action: string 可选accessdeny
      • reqSize: string 限定请求数据大小,默认为1M
      • matchExp: string access时如不匹配将结束请求。deny时如匹配将结束请求
    • reqFunc:{} 请求后端前,调用方法
      • filiter: func(r *http.Request)(pass bool) 当通过编程方式启动时,将调用注册的方法
    • resFunc:{} 返回后端响应前,调用方法(仅http、https、ws、wss时有效)
      • filiter: func(req *http.Request, res *http.Response)(pass bool) 当通过编程方式启动时,将调用注册的方法
  • dealer: {}

    • reqUri:[] 请求后端前,路径处理器
      • action: string 可选replace
      • matchExp: string replace时结合value进行替换
      • value: string replace时结合matchExp进行替换。
    • reqHeader:[] 请求后端前,请求头处理器
      • action: string 可选replaceadddelset
      • key: string 具体处理哪个头
      • matchExp: string replace时结合value进行替换
      • value: string replace时结合matchExp进行替换。add时将附加值。set时将覆盖值。
    • resHeader:[] 返回后端的响应前,请求头处理器
      • action: string 可选adddelset
      • key: string 具体处理哪个头
      • matchExp: string replace时结合value进行替换
      • value: string replace时结合matchExp进行替换。add时将附加值。set时将覆盖值。
    • resBody:[] 返回后端响应前,数据处理器(仅http、https有效),使用转发块进行处理
      • action: string 可选replace
      • matchExp: string replace时结合value进行替换
      • value: string replace时结合matchExp进行替换。
    • resStatus:{} 返回后端响应前,修改响应码(仅to为空、http、https时有效)
      • matchExp: string 正则表达式
      • value: int

可以使用的环境变量(仅能单独使用,不能和字符串拼合等):

  • $remote_addr:当存在X-Real-IP头时,取其值,否则取请求端的远程地址。在dealer.reqHeader.valuedealer.resHeader.value可用

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrRedirect          = errors.New("ErrRedirect")
	ErrNoHttp            = errors.New("ErrNoHttp")
	ErrNoWs              = errors.New("ErrNoWs")
	ErrCopy              = errors.New("ErrCopy")
	ErrReqReBodyFail     = errors.New("ErrReqReBodyFail")
	ErrReqReBodyFull     = errors.New("ErrReqReBodyFull")
	ErrReqReBodyOverflow = errors.New("ErrReqReBodyOverflow")
	ErrReqRetry          = errors.New("ErrReqRetry")
	ErrReqCreFail        = errors.New("ErrReqCreFail")
	ErrReqDoFail         = errors.New("ErrReqDoFail")
	ErrResDoFail         = errors.New("ErrResDoFail")
	ErrResFail           = errors.New("ErrResFail")
	ErrResTO             = errors.New("ErrResTO")
	ErrUriTooLong        = errors.New("ErrUriTooLong")
	ErrCheckFail         = errors.New("ErrCheckFail")
	ErrPatherCheckFail   = errors.New("ErrPatherCheckFail")
	ErrHeaderCheckFail   = errors.New("ErrHeaderCheckFail")
	ErrFuncCheckFail     = errors.New("ErrFuncCheckFail")
	ErrBodyCheckFail     = errors.New("ErrBodyCheckFail")
	ErrAllBacksFail      = errors.New("ErrAllBacksFail")
	ErrBackFail          = errors.New("ErrBackFail")
	ErrNoRoute           = errors.New("ErrNoRoute")
	ErrReUp              = errors.New("ErrReUp")
	ErrDealReqUri        = errors.New("ErrDealReqUri")
	ErrDealReqHeader     = errors.New("ErrDealReqHeader")
	ErrDealResHeader     = errors.New("ErrDealResHeader")
	ErrCerVerify         = errors.New("ErrCerVerify")
)
View Source
var ErrDuplicatePath = errors.New(`ErrDuplicatePath`)
View Source
var (
	ErrEmptyVerifyPeerCerByte = errors.New("ErrEmptyVerifyPeerCerByte")
)

Functions

func BatchRLock added in v0.1.20250905024930

func BatchRLock(backs []*Back) iter.Seq2[int, *Back]

func DialContext added in v0.1.20231214143418

func DialContext(ctx context.Context, urlStr string, requestHeader http.Header, chosenBack *Back) (net.Conn, *http.Response, error)

func Load added in v0.1.20250621222422

func Load(configF *pfile.File, configS *[]Config) error

加载

func LoadX509PubKey added in v0.1.20240323030221

func LoadX509PubKey(certPEMBlock []byte) tls.Certificate

func MarkRetry added in v0.1.20241009015120

func MarkRetry(e error) error

func Test

func Test(ctx context.Context, port int, logger *plog.Log)

测试

func Upgrade added in v0.1.20231214143418

func Upgrade(w http.ResponseWriter, r *http.Request, responseHeader http.Header) (net.Conn, error)

Types

type Back

type Back struct {
	UpT         time.Time `json:"upT"`
	LastChosenT time.Time `json:"lastChosenT"`
	LastFailT   time.Time `json:"lastFailT"`
	DisableC    uint      `json:"disableC"`
	DealingC    uint      `json:"dealingC"`
	ChosenC     uint      `json:"chosenC"`

	Name     string `json:"name"`
	To       string `json:"to"`
	Weight   uint   `json:"weight,string"`
	AlwaysUp bool   `json:"alwaysUp"`

	Setting
	// contains filtered or unexported fields
}

func (*Back) Disable added in v0.1.20231203025759

func (t *Back) Disable()

func (*Back) Enable added in v0.1.20251029055502

func (t *Back) Enable()

func (*Back) Id added in v0.1.20240305005058

func (t *Back) Id() string

func (*Back) IsLive added in v0.1.20231203025759

func (t *Back) IsLive() bool

func (*Back) SwapSign added in v0.1.20231209195503

func (t *Back) SwapSign(logger *plog.Log)

type Blocks added in v0.1.20250421162659

type Blocks struct {
	Size string `json:"size,omitempty"`

	Num int `json:"num,omitempty"`
	// contains filtered or unexported fields
}

type Config

type Config struct {
	Addr string `json:"addr"`
	TLS  struct {
		Pub     string   `json:"pub,omitempty"`
		Key     string   `json:"key,omitempty"`
		Decrypt []string `json:"decrypt,omitempty"`
	} `json:"tls"`
	RetryBlocks  Blocks             `json:"retryBlocks"`
	RetryBlocksI pool.BlocksI[byte] `json:"-"`
	MatchRule    string             `json:"matchRule"`
	CopyBlocks   Blocks             `json:"copyBlocks"`
	BlocksI      pool.BlocksI[byte] `json:"-"`

	Routes []Route `json:"routes"`

	ReqIdLoop int `json:"reqIdLoop"`
	// contains filtered or unexported fields
}

func (*Config) Run added in v0.1.20240305005058

func (t *Config) Run(rootCtx context.Context, logger *plog.Log)

Run会创建协程,启动服务,并阻塞直到rootCtx.Done,rootCtx.Done之后,

func (*Config) SwapSign added in v0.1.20240303164122

func (t *Config) SwapSign(ctx context.Context, logger *plog.Log)

type ErrCanRetry added in v0.1.20241009015120

type ErrCanRetry struct {
	// contains filtered or unexported fields
}

type File added in v0.1.20231209073216

type File interface {
	Read(data []byte) (int, error)
}

type HandshakeError added in v0.1.20231214143418

type HandshakeError struct {
	// contains filtered or unexported fields
}

func (HandshakeError) Error added in v0.1.20231214143418

func (t HandshakeError) Error() string

type Pather added in v0.1.20250927162358

type Pather struct {
	Per    *Pather
	Next   *Pather
	Dealer *Route
	// contains filtered or unexported fields
}

func NewPather added in v0.1.20250927162358

func NewPather() *Pather

func (*Pather) Add added in v0.1.20250927162358

func (t *Pather) Add(r *Route)

func (*Pather) Del added in v0.1.20250927162358

func (t *Pather) Del(r *Route)

func (*Pather) Range added in v0.1.20250927162358

func (t *Pather) Range() iter.Seq[*Route]

func (*Pather) Size added in v0.1.20250927162358

func (t *Pather) Size() (i uint32)

type Route

type Route struct {
	Name string `json:"name"`

	Path []string `json:"path"`

	RollRule string `json:"rollRule,omitempty"`
	AlwaysUp bool   `json:"alwaysUp"`
	Setting

	Backs []Back `json:"backs"`
	// contains filtered or unexported fields
}

func (*Route) FiliterBackByRequest added in v0.1.20240305005058

func (t *Route) FiliterBackByRequest(r *http.Request) []*Back

func (*Route) Id added in v0.1.20240305172524

func (t *Route) Id() string

func (*Route) SwapSign

func (t *Route) SwapSign(logger *plog.Log)

func (*Route) WR added in v0.1.20250927162358

func (t *Route) WR(reqId uint32, routePath string, logger *plog.Log, reqBuf *reqBufS, w http.ResponseWriter, r *http.Request) (err error)

type Setting added in v0.1.20240321070814

type Setting struct {
	PathAdd            bool               `json:"pathAdd"`
	CtxToSec           float64            `json:"ctxToSec"`
	ErrToSec           float64            `json:"errToSec"`
	Splicing           int                `json:"splicing"`
	ErrBanSec          int                `json:"errBanSec"`
	InsecureSkipVerify bool               `json:"insecureSkipVerify"`
	VerifyPeerCer      string             `json:"verifyPeerCer,omitempty"`
	Proxy              string             `json:"proxy,omitempty"`
	Filiters           []*filiter.Filiter `json:"filiters,omitempty"`
	Dealer             dealer.Dealer      `json:"dealer,omitempty"`
	// contains filtered or unexported fields
}

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL