8000 GitHub - zhbok/eudore: I am using the go web server framework to learn the http protocol.
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

zhbok/eudore

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Eudore

本框架为个人学习研究的重框架,每周最多同步更新一次,未稳定前不欢迎issue、pr、using,可查看http及go web框架相关文档,交流q群373278915。

Features

  • 核心全部接口化,支持重写Application、Context、Request、Response、Router、Middleware、Logger、Server、Config、Cache、Bind、Render、View。
  • 对象语义明确,框架源码简单易懂注释多,无注释部分变动可能较大。

Lsit

功能列表,在未稳定前不会编写演示

  • Application
  • 程序启动流程自定义实现,内置两种
  • server异步启动
  • 完全配置化启动程序
  • Context
  • Context与server完全解耦
  • 根据Content-type自动序列化数据
  • 根据Accept反序列化数据
  • 内部重定向支持
  • http2 push
  • Config
  • 配置库集成
  • 支持基于路径读写对象
  • map和结构体相互转换
  • 数据类型转换工具
  • 生成对象帮助信息
  • Server
  • 支持net/http启动server
  • 支持fasthttp启动server
  • 重新实现http协议server
  • http2协议两种server支持
  • fastcgi协议两种server支持
  • websocket协议支持
  • 重新实现websocket协议
  • 支持TLS和双向TLS
  • 自动自签TLS证书
  • quic协议支持
  • http3协议学不动了
  • server热重启支持
  • server后台启动
  • Router
  • 零内存复制快速路由器实现
  • 严格路由匹配顺序
  • RESTful风格基于方法的路由注册匹配
  • 基于Host进行路由注册匹配
  • 路由器注册初始化时请求处理
  • 组路由注册支持
  • 全局中间件注册
  • 组级中间件注册
  • api级中间件注册
  • 路由默认参数
  • 默认参数匹配注册中间件
  • 路由匹配参数捕获
  • 路由匹配参数校验
  • 路由匹配参数正则捕捉
  • 路由匹配通配符捕捉
  • 路由匹配通配符校验
  • 路由匹配通配符正则捕捉
  • Logger
  • 初始化期间日志处理
  • 日志条目属性支持
  • 自定义模板格式化
  • 日志写入到es
  • View
  • 多模板库接入
  • Mvc
  • mvc支持
  • before和after执行
  • 控制器函数输出参数
  • Tools
  • 程序启动命令解析
  • 信号响应支持
  • SRI值自动设置
  • 自动http2 push
  • http代理实现
  • pprof支持
  • expvar支持
  • 运行时对象数据显示
  • Middleware
  • gzip压缩
  • 限流
  • 黑名单
  • Session实现

issue

setting 基于配置初始化对象未实现

缺少完整websocket实现,仅有upgrade部分

config-eudore未测试,已实现通过路径设置获得属性。

组件Set方法等待config-eudore实现后复用功能

fasthttp不支持多端口和hijack

handlefile处理304缓存

mvc未完善

Component

组件名称 介绍 定义库
router-radix 使用基数树实现标准功能路由器 内置
router-full 使用基数树实现完整功能路由器 内置
router-init 初始时使用的路由处理 github.com/eudore/eudore/component/router/init
router-host 匹配host路由到不同路由器处理 github.com/eudore/eudore/component/router/host
logger-init 初始化日志处理,保存日志由设置的日志对象处理 内置
logger-std 基础日志库实现 内置
logger-elastic 将日志直接输出到es中 未更新、github.com/eudore/eudore/component/eslogger
server-std 使用net/http封装标准库Server 内置
server-eudore 使用protocol库封装Server github.com/eudore/eudore/component/server/eudore
server-fasthttp 使用fasthttp启动服务 github.com/eudore/eudore/component/server/fasthttp
cache-map 使用Sync.Map实现的缓存 内置
cache-group 使用前缀匹配的多缓存组合 内置
config-map 使用map[string]interface{}存储配置 内置
config-eudore 使用反射来操作结构体和map自由嵌套的配置对象 内置
view-std 使用标准库html/template渲染模板 内置、未测试

Example

Example部分未更新

Application

Application默认有两种实现Core和Eudore,Core只有启动函数,Eudore多一些辅助 8000 数封装。

func main() {
	// 运行core
	core := eudore.NewCore()
	go core.Run()

	// 运行eudore
	e := eudore.NewEudore()
	e.Run()
}

Server

Server是eudore用于启动http服务的顶级接口对象之一。

func main() {
	e := eudore.NewEudore()
	// 直接设置Server对象
	e.Server, _ = eudore.NewServer("server-std", nil)

	// 加载Server组件,设置一个启动端口,设置超时时间
	e.RegisterComponent("server", &eudore.ServerConfigGeneral{
		Addr:	"8088",
		ReadTimeout:	12 * time.Second,
		WriteTimeout:	4 * time.Second,
	})

	// 启动多个端口
	// 端口8085:设置证书、开启https http2、关闭双向htttps
	e.RegisterComponent("server-multi", &eudore.ServerMultiConfig{
		Configs:	[]interface{}{
			&eudore.ServerConfigGeneral{
				Name:	"server",
				Addr:	"8085",
				Https:	true,
				Http2:	true,
				Mutual:	false,
				Certfile:	"/etc/...",
				Keyfile:	"/etc/...",
			},
			&eudore.ServerConfigGeneral{
				Name:	"server",
				Addr:	"8086",
			},
		},
	})
	e.Run()
}

Logger

NewEudore创建App时,会创建logger-init日志组件,实现LoggerInitHandler接口,改组件会将日志条目存储起来,直到加载下一个日志组件时,使用新日志组件处理所有存储的日子条目。

logger-std的Std用于输出标准输出;若Path为空会强制Std为true;Format会使用存储的LoggerFormatFunc函数,若无法匹配会使用text/template模板格式化日志。

func main() {
	e := eudore.NewEudore()
	e.Debug("init 1")
	e.Get("/get", get)
	e.Post("/post", post)
	e.RegisterComponent("logger-std", &eudore.LoggerStdConfig{
		Std:	true,
		Path:	"access.log",
		Level:	"debug",
//		Format:	"json",
		Format:	`[{{.Timestamp.Format "Jan 02, 2006 15:04:05 UTC"}}] {{.Level}}: {{.Message}}`,
	})
	e.Debug("init 2")
	e.Run()
}

Router and Middleware

router-std路由器支持组路由、组级中间件、路径参数、通配符参数、默认参数。

router-full路由器支持组路由、组级中间件、路径参数、通配符参数、默认参数、参数校验、通配符校验,未实现多参数正则捕捉。

可实现Router接口重写路由器。

curl -XGET http://localhost:8088/api/v1/

curl -XGET http://localhost:8088/api/v1/get/eudore

curl -XGET http://localhost:8088/api/v1/set/eudore

package main

import (
	"github.com/eudore/eudore"
	"github.com/eudore/eudore/middleware/logger"
	"github.com/eudore/eudore/middleware/recover"
)

// eudore core
func main() {
	// 创建App
	app := eudore.NewCore()
	app.RegisterComponent("logger-std", &eudore.LoggerStdConfig{
		Std:	true,
		Level:	eudore.LogDebug,
		Format:	"json",
	})
	// 全局级请求处理中间件
	app.AddMiddleware(
		logger.NewLogger(eudore.GetRandomString).Handle,
	)

	// 创建子路由器
	// apiv1 := eudore.NewRouterClone(app.Router)
	apiv1 := app.Group("/api/v1 version:v1")
	// 路由级请求处理中间件
	apiv1.AddMiddleware(recover.RecoverFunc)
	{
		apiv1.GetFunc("/get/:name", handleget)
		// Api级请求处理中间件
		apiv1.AnyFunc("/*", handlepre1, handleparam)
	}
	// 默认路由
	app.AnyFunc("/*path", func(ctx eudore.Context){
		ctx.WriteString(ctx.Method() + " " + ctx.Path())
		ctx.WriteString("\nstar param: " + " " + ctx.GetParam("path"))
	})
	// 启动server
	app.Listen(":8088")
	app.Run()
}

func handleget(ctx eudore.Context) {
	ctx.Debug("Get: " + ctx.GetParam("name"))
	ctx.WriteString("Get: " + ctx.GetParam("name"))
}
func handlepre1(ctx eudore.Context) {
	ctx.WriteString("\nhandlepre1\n")
}
func handleparam(ctx eudore.Context) {
	ctx.WriteString(ctx.GetParam("*"))
}

Jwt and Session

func main() {
	core := eudore.NewCore()
	core.AddHandler(
		jwt.NewJwt(jwt.NewVerifyHS256("1234")),
		eudore.HandlerFunc(session.SessionFunc),
	)
	core.Any("/", any)
	core.Run()
}

func any(ctx *eudore.Context) {
	ctx.Info(ctx.Value(eudore.ValueJwt))
	ctx.Info(ctx.Value(eudore.ValueSession))

	// inti
	sess := cast.NewMap(ctx.Value(eudore.ValueJwt))
	// get
	ctx.Info(sess.GetInt("uid"))
	// set
	sess.Set("name", "ky2")
	// release,未实现检查map是否变化然后自动释放。
	ctx.SetValue(eudore.ValueSession, sess)

	// inti
	jwt := cast.NewMap(ctx.Value(eudore.ValueSession))
	// get
	ctx.Info(jwt.Get("exp"))
}

Ram

资源访问管理

github.com/eudore/eudore/middleware/ram包共有acl、pbac、rbac、shell四种鉴权方式。

ram.RamHttp对象定义:

type RamHttp struct {
    RamHandler
    GetId     GetIdFunc
    GetAction GetActionFunc
    Forbidden ForbiddenFunc
}
type RamHttp
    func NewRamHttp(rams ...RamHandler) *RamHttp
    func (r *RamHttp) Handle(ctx eudore.Context)
    func (r *RamHttp) Set(f1 GetIdFunc, f2 GetActionFunc, f3 ForbiddenFunc) *RamHttp

RamHttp需要Set设置获取id、获取行为、403执行,三个行为参数。

// bug
package main

import (
	"strconv"
	"github.com/eudore/eudore"
	"github.com/eudore/eudore/middleware/ram"
	"github.com/eudore/eudore/middleware/ram/acl"
)

func main() {
	app := eudore.NewCore()	
	eudore.SetComponent(app.Logger, eudore.LoggerHandleFunc(eudore.LoggerHandleJson))
	// add
	ramAcl := acl.NewAcl()
	ramAcl.AddAllowPermission(1, []string{"Show", "Get"})
	app.AddHandler(
		ram.NewRamHttp(
			// 执行acl鉴权
			ramAcl,
			// rbac.NewRbac(),
			// 默认执行拒绝
			ram.DenyHander,
		).Set(getid, nil, nil),
	)

	app.AnyFunc("/:id/:action ss:00", func(ctx eudore.Context) {
		ctx.Info(ctx.GetParam("action"))
		ctx.WriteString("Allow " + ctx.GetParam("action"))
	})
	app.AnyFunc("/", func(ctx eudore.Context) {
		ctx.Info(ctx.Path())
	})
	// start
	app.Listen(":8088")
	app.Run()
}

func getid(ctx eudore.Context) int {
	i, err := strconv.Atoi(ctx.GetParam("id"))
	if err != nil {
		return 0
	}
	return i
}

Websocket

目前没有独立的websocket库,且不与net/http兼容,推荐使用github.com/gobwas/ws库。

eudore.UpgradeHttp获取net.Conn链接并写入建立请求响应,然后wsutil库读写数据。

ctx.Response().Hijack()可以直接获得原始tcp连接,然后读取header判断请求,写入101数据,再操作websocket连接。

package main

import (
	"github.com/eudore/eudore"
	"github.com/gobwas/ws/wsutil"
)

func main() {
	app := eudore.NewCore()
	eudore.SetComponent(app.Logger, eudore.LoggerHandleFunc(eudore.LoggerHandleJson))
	app.RegisterComponent(eudore.ComponentRouterEmptyName, eudore.HandlerFunc(func(ctx eudore.Context){
		conn, _, err := eudore.UpgradeHttp(ctx) 
		if err != nil {
			// handle error
			ctx.Error(err)
		}
		go func() {
			defer conn.Close()

		
4D2B
	for {
				msg, op, err := wsutil.ReadClientData(conn)
				if err != nil {
					ctx.Error(err)
					// handle error
				}
				ctx.Info(string(msg))
				err = wsutil.WriteServerMessage(conn, op, msg)
				if err != nil {
					// handle error
				}
			}
		}()
	}))

	app.Listen(":8088")
	app.Run()
}

About

I am using the go web server framework to learn the http protocol.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Go 100.0%
0