到目前为止,服务是可以正常运行了,但是,我们并没有对接口的访问做方法限制。因为之前的代码我们是照抄go的原生http库,无法满足我们的预期,所以,我们需要对代码进行一定的修改
修改Route方法
首先我们需要在Route方法中添加method参数,用来接收请求方法
type Srever interface{
Route(method string, pattern string, handleFunc func(ctx *Context))
Start(address string) error
}
在对应的方法接收器中也要添加对应的参数
func (s *sdkHttpServer) Route(method string, pattern string, handleFunc func(ctx *Context)) {
http.HandleFunc(pattern,func(writer http.ResponseWriter,request *http.Request)){
ctx := NewContext(writer,request)
handleFunc(ctx)
}
}
但是http.HandleFunc没有method参数,我们可以考虑用下面的方式来实现
func (s *sdkHttpServer) Route(method string, pattern string, handleFunc func(ctx *Context)) {
http.HandleFunc(pattern,func(writer http.ResponseWriter,request *http.Request)){
if request.Method != method{
writer.Write([]byte("error method"))
}
ctx := NewContext(writer,request)
handleFunc(ctx)
}
}
这样写虽然可行,但看上去总是不太舒服,所以我们换一条思路
改用http.Handler进行实现
在http库中,有一个Handle方法(http/server.go)
这个方法接收两个参数,string类型的pattern和一个Handler接口
首先,我们实现Handler接口
type HandlerBasedOnMap struct{
// key method+url 用于区别请求方法
handlers map[string]func(ctx *Context)
}
func (h *HandlerBasedOnMap) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
}
然后实现实现key的逻辑
func (h *HandlerBasedOnMap) key(req *http.Request) string{
return req.Mothed + "#" + req.URL.Path
}
重写Haddler接口里的ServeHTTP方法,实现请求方法处理逻辑
func (h *HandlerBasedOnMap) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
key := h.key(request)
if h.handler,ok:=h.handlers[key],ok{
handler(NewContext(writer,request))
}else{
writer.WriteHeader(statusCode:http.StatusNotFound)
writer.Write([]byte("Not Found"))
}
}
修改Route方法
func (s *sdkHttpServer) Route(method string, pattern string, handleFunc func(ctx *Context)) {
http.Handle("/",&HandlerBasedOnMap{})
}
不过因为我们只需要注册一次,所以我们将代码移动到Start方法,并且让Server持有Handler
type sdkHttpServer struct {
Name string
handler *HandlerBasedOnMap{}
}
// Start 启动服务
func (s *sdkHttpServer) Start(address string) error {
http.Handle("/",s.handler)
return http.ListenAndServe(address, nil)
}
而Route方法则做出下面的修改
func (s *sdkHttpServer) Route(method string, pattern string, handleFunc func(ctx *Context)) {
//加入请求方法限制
key := s.handler.key(method, pattern)
//TODO:处理重复注册
s.handler.handlers[key] = handleFunc
}
此时,我们已经可以支持对方法的限制,但是仍然存在一些问题
- Route方法的实现依赖于HandlerBasedOnMap的内部细节,和HandlerBaseOnMap强耦合
- 如果后期考虑路由树的扩展,sdkHttpServer也需要修改 后面我们需要针对这些问题做出调整