路由注冊到app.routes
http請求的處理跪解,相較于基本的net/http包卑雁,iris框架將http請求(w,*r)及其它上下文码邻,封裝成ctx,逐個調(diào)用handler閉包進行處理套腹,最后分發(fā)函數(shù)返回值(反射)以及響應绪抛。請求響應相當于流水線上的一個商品,被一組當中的每個handler處理电禀。路由注冊的過程幢码,在完成之前的方法解析,path解析之后尖飞,就需要組裝一個handler鏈到路由了症副。
每一步先由api.relativePath和方法傳入的參數(shù)構(gòu)成fullPath。
第二步然后添加handler政基,順序為:
- macroHandler贞铣,解析路徑中的參數(shù)值
- api.middleware,類型為[]handler
- anymiddleware沮明,由app.Handle()方法傳入
- 控制器方法的對應閉包
- 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)提過,由于反射字段的不可復用性佑附,造成go的反射效率下降用含。如果處理每次的請求都要在運行時重新構(gòu)建context,就會降低性能帮匾。iris用c.pool保存ctx,實現(xiàn)ctx的可復用痴鳄。c.pool的類型是sync.pool瘟斜。id確定ctx的唯一性,方便保存在c.pool集合中。request writer都是net/http標準庫的類型螺句,直接傳遞虽惭。
params RequestParams 是一個專用的KV存儲,類型為[string]interface{}蛇尚。用來保存path param芽唇。values用來保存其它KV信息。
app引用自iris實例取劫,可以獲取全部的實例字段匆笤。其中路由信息單獨拿出:currentRouteName路由名,對應c.routes的鍵谱邪。路由handlers炮捧,currentHandlerIndex。
ctx是可復用的惦银,需要構(gòu)建ctx時咆课,不是初始化而是直接從池中拿一個實例〕毒悖空實例僅配置了app字段书蚪。第一步包裝net/http包的(w,*r)。第二步根據(jù)request確定路由信息迅栅,并賦到ctx相應字段殊校。第三步會執(zhí)行流水線式地Do(handlers),反射調(diào)用得到響應信息库继,并寫入到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
}