为你自己学Go
  • README
  • PART01.Web框架概览
    • 1.01 Web框架概览:学习路线
    • 1.02 Web框架概览-Beego框架分析
    • 1.03 Web框架概览-GIN框架分析
    • 1.04 Web框架概览-Iris框架分析
    • 1.05 Web框架概览-Echo框架分析
  • PART02.Server
    • 2.01 Server详解与面试要点
  • PART03.路由树
    • 3.01 路由树-Beego&GIN&Echo实现与设计总结
    • 3.02 路由树-全静态匹配
    • 3.03 路由树-TDD起步
    • 3.04 路由树-静态匹配测试用例
    • 3.05 路由树-静态匹配之路由查找
    • 3.06 路由树-静态匹配之集成Server
    • 3.07 路由树-通配符匹配之路由注册
    • 3.08 路由树-通配符匹配之路由查找与测试
    • 3.09 路由树-参数路径之基本注册和查找
    • 3.10 路由树-参数路径之校验
    • 3.11 路由树-参数路径之参数值
    • 3.12 路由树-总结与面试要点
  • PART04.课后复习
    • 4.01 课后复习-Server
    • 4.02 课后复习-Route
  • PART05.Context
    • 5.01 Context-简介
    • 5.02 Context-Beego Context设计分析
    • 5.03 Context-Gin Context设计分析
    • 5.04 Context-Echo和Iris的Context设计分析
    • 5.05 Context-处理输入输出总结
    • 5.06 Context-处理输入之Body输入
    • 5.07 Context-处理输入之表单输入
    • 5.08 Context-处理输入之查询参数、路径参数和StringValue
    • 5.09 Context-处理输出
    • 5.10 Context-总结与面试要点
  • PART06.AOP
    • 6.01 AOP简介与不同框架设计概览
    • 6.02 AOP设计方案-Middleware
  • PART07.Middleware
    • 7.01 Middleware-AccessLog
    • 7.02 Middleware-Trace简介和OpenTelemetry
    • 7.03 Middleware-OpenTelemetry测试
    • 7.04 Middleware-OpenTelemetry总结
    • 7.05 Prometheus详解
    • 7.06 Middleware-Prometheus
    • 7.07 Middleware-错误页面
    • 7.08 Middleware-从panic中恢复
    • 7.09 Middleware总结和面试
  • PART08.Review
    • 8.01 课后复习-AOP
    • 8.02 课后复习-Context
    • 8.03 课后复习-Middleware-AccessLog
  • PART09.Appendix
    • 附录1.责任链模式
    • 附录2.生成器模式
    • 附录3.函数选项模式
  • xiaochengxu
    • 01.原力去水印
    • 02.KeePass密码管理:安全轻松的管理您的密码
Powered by GitBook
On this page
  • PART1. 参数路由与通配符路由共存问题
  • 1.1 修改逻辑
  • 1.2 测试
  1. PART03.路由树

3.10 路由树-参数路径之校验

本节课工程结构如下:

(base) yanglei@yuanhong 15-validateParamRoute % tree ./
./
├── context.go
├── handleFunc.go
├── httpServer.go
├── httpServer_test.go
├── node.go
├── router.go
├── router_test.go
└── serverInterface.go

0 directories, 8 files

PART1. 参数路由与通配符路由共存问题

1.1 修改逻辑

上节课中说过,我们的设计中是不准备支持同样的参数路径和通配符匹配一起注册的(即/user/*和/user/:id).

所以从逻辑上来讲,只需要实现:注册参数路由时检测通配符路由是否存在;注册通配符路由时检测参数路由是否存在.若对方存在,则不允许注册即可.

node.go:

// childOrCreate 本方法用于在节点上获取给定的子节点,如果给定的子节点不存在则创建
func (n *node) childOrCreate(segment string) *node {
	// 如果路径为参数 则查找当前节点的参数子节点 或创建一个当前节点的参数子节点 并返回
	if strings.HasPrefix(segment, ":") {
		// 若当前节点存在通配符子节点 则不允许注册参数子节点
		if n.wildcardChild != nil {
			panic("web: 非法路由,已有通配符路由.不允许同时注册通配符路由和参数路由")
		}

		if n.paramChild == nil {
			n.paramChild = &node{
				path: segment,
			}
		}
		return n.paramChild
	}

	// 若路径为通配符 则查找当前节点的通配符子节点 或创建一个当前节点的通配符子节点 并返回
	if segment == "*" {
		// 若当前节点存在参数子节点 则不允许注册通配符子节点
		if n.paramChild != nil {
			panic("web: 非法路由,已有参数路由.不允许同时注册通配符路由和参数路由")
		}

		if n.wildcardChild == nil {
			n.wildcardChild = &node{
				path: segment,
			}
		}
		return n.wildcardChild
	}

	// 如果当前节点的子节点映射为空 则创建一个子节点映射
	if n.children == nil {
		n.children = map[string]*node{}
	}

	res, ok := n.children[segment]
	// 如果没有找到子节点,则创建一个子节点;否则返回找到的子节点
	if !ok {
		res = &node{
			path: segment,
		}
		n.children[segment] = res
	}
	return res
}

1.2 测试

router_test.go:

// TestRouter_findRoute_param_and_wildcard_coexist 测试针对注册参数路由时,已有通配符路由的情况
func TestRouter_findRoute_param_and_wildcard_coexist(t *testing.T) {
	// step1. 注册有冲突的路由
	r := newRouter()
	mockHandleFunc := func(ctx *Context) {}
	r.addRoute(http.MethodGet, "/order/detail/*", mockHandleFunc)

	// step2. 断言非法用例
	assert.Panicsf(t, func() {
		r.addRoute(http.MethodGet, "/order/detail/:id", mockHandleFunc)
	}, "web: 非法路由,已有通配符路由.不允许同时注册通配符路由和参数路由")
}

// TestRouter_findRoute_wildcard_and_param_coexist 测试针对注册通配符路由时,已有参数路由的情况
func TestRouter_findRoute_wildcard_and_param_coexist(t *testing.T) {
	// step1. 注册有冲突的路由
	r := newRouter()
	mockHandleFunc := func(ctx *Context) {}
	r.addRoute(http.MethodGet, "/order/detail/:id", mockHandleFunc)

	// step2. 断言非法用例
	assert.Panicsf(t, func() {
		r.addRoute(http.MethodGet, "/order/detail/*", mockHandleFunc)
	}, "web: 非法路由,已有参数路由.不允许同时注册通配符路由和参数路由")
}

以上两个测试用例均可顺利通过.

Last updated 9 months ago