路由注冊到app.routes
http請求的處理,相較于基本的net/http包,iris框架將http請求(w,*r)及其它上下文,封裝成ctx,逐個調(diào)用handler閉包進行處理,最后分發(fā)函數(shù)返回值(反射)以及響應(yīng)。請求響應(yīng)相當于流水線上的一個商品,被一組當中的每個handler處理。路由注冊的過程,在完成之前的方法解析,path解析之后,就需要組裝一個handler鏈到路由了。
每一步先由api.relativePath和方法傳入的參數(shù)構(gòu)成fullPath。
第二步然后添加handler,順序為:
- macroHandler,解析路徑中的參數(shù)值
- api.middleware,類型為[]handler
- anymiddleware,由app.Handle()方法傳入
- 控制器方法的對應(yīng)閉包
- api.doneHandlers
- api的全局handlers
第三步構(gòu)建Route:
type Route struct {
Name string `json:"name"`
Method string `json:"method"`
methodBckp string
Subdomain string `json:"subdomain"`
tmpl *macro.Template
beginHandlers context.Handlers
Handlers context.Handlers `json:"-"`
MainHandlerName string `json:"mainHandlerName"`
doneHandlers context.Handlers
Path string `json:"path"`
FormattedPath string `json:"formattedPath"`
}
Name格式為defaultName := method + subdomain + 未注值的路徑格式。其中路徑有三個相關(guān)變量:Subdomain Path FormattedPath。FormattedPath是將path中的:變量替換為%v。構(gòu)建路由Router時將路徑解析的macroHandler,添加在最前面。
最后將路由注冊到app.APIBuilder.routes,類型為[]Route。
context數(shù)據(jù)結(jié)構(gòu)
iris框架定義了handler閉包的操作對象context.context。不是指TCP的context,也不是net/http中的context。數(shù)據(jù)結(jié)構(gòu)如下:
type context struct {
id uint64
writer ResponseWriter
request *http.Request
currentRouteName string
app Application
handlers Handlers
currentHandlerIndex int
}
前文已經(jīng)提過,由于反射字段的不可復(fù)用性,造成go的反射效率下降。如果處理每次的請求都要在運行時重新構(gòu)建context,就會降低性能。iris用c.pool保存ctx,實現(xiàn)ctx的可復(fù)用。c.pool的類型是sync.pool。id確定ctx的唯一性,方便保存在c.pool集合中。request writer都是net/http標準庫的類型,直接傳遞。
params RequestParams 是一個專用的KV存儲,類型為[string]interface{}。用來保存path param。values用來保存其它KV信息。
app引用自iris實例,可以獲取全部的實例字段。其中路由信息單獨拿出:currentRouteName路由名,對應(yīng)c.routes的鍵。路由handlers,currentHandlerIndex。
ctx是可復(fù)用的,需要構(gòu)建ctx時,不是初始化而是直接從池中拿一個實例。空實例僅配置了app字段。第一步包裝net/http包的(w,*r)。第二步根據(jù)request確定路由信息,并賦到ctx相應(yīng)字段。第三步會執(zhí)行流水線式地Do(handlers),反射調(diào)用得到響應(yīng)信息,并寫入到ctx中。最后一步將針對特定http請求的信息清掉,并放回c.pool。
標準庫中的net/http Request
type Request struct {
Method string
URL *url.URL
Header Header
Body io.ReadCloser
GetBody func() (io.ReadCloser, error)
ContentLength int64
TransferEncoding []string
Close bool
Host string
Form url.Values
PostForm url.Values
MultipartForm *multipart.Form
Trailer Header
RemoteAddr string
RequestURI string
TLS *tls.ConnectionState
Cancel <-chan struct{}
Response *Response
ctx context.Context
}
標準庫net/http Response
type Response struct {
Status string
StatusCode int
Proto string
ProtoMajor int
ProtoMinor int
Header Header
Body io.ReadCloser
ContentLength int64
TransferEncoding []string
Close bool
Uncompressed bool
Trailer Header
Request *Request
TLS *tls.ConnectionState
}