# 控制器
## 定義
在 orange 框架中,控制器是這樣一個函數 `func(ctx *app.Context) error`,如下是典型的控制器定義
```
import (
"gitee.com/zhucheer/orange/app"
)
func Welcome(c *app.Context) error {
return c.ToJson(map[string]interface{}{
"info": "orange is a fast api framework",
})
}
```
## 請求
### 獲取參數
#### URL變量參數
通過表達式定義的路由規則,如下所示
`groupName .GET("/userinfo/:uid", controller.UserInfo)`
`groupName .GET("/userinfo/*", controller.UserInfo)`
通過如下方法進行參數獲取:
```
?c.GetPathParam("iccid")
?c.GetPathParam("*")
```
#### GET參數
通過控制的中的 Request 可以獲得原始 request;使用 FormValue 即可獲得 GET 參數;
~~~
c.Request().FormValue("token")
~~~
#### POST / GET 參數獲取統一方案
在 orange 中通過 ***參數綁定*** 的方式可以獲取 GET/POST 參數,參數綁定方式能獲取表單提交類型的參數和json類型的參數,兼容性較好。
參數綁定方法如下:
```
// 這兩個方法是等效的,主要是考慮到 gin 框架中的命名習慣
c.ShouldBind(&req)
c.ParseForm(&req)
```
具體代碼如下:
```
...
func Welcome(c *app.Context) error {
req := struct {
Id int `json:"id"`
}{}
err := c.ShouldBind(&req)
if err != nil {
return c.ResponseWrite([]byte("參數解析錯誤"))
}
...
}
...
```
通過參數綁定可以使用 golang 結構體 tag 配置框架自帶的的內置過濾器對參數收尾空白字符進行過濾:
```
// 該方式獲取的參數會自動對參數首位空白字符進行過濾
req := struct {
VideoLink string `json:"videoLink" expr:"trim"`
}{}
err := c.ParseForm(&req)
```
> 注意1:請求參數中包含&、>、<等特殊符號時需要進行 urlencode 編碼,通過參數綁定后會自動進行 urldecode 解碼;
> 例如傳遞參數是一個 url 時,需要對該參數進行 urlencode 后傳入。
> 注意2:接口請求默認請全體大小限制32M,可根據app.maxBody配置進行調整;強烈建議設置一個合理的大小防止程序內存溢出,為支持特定場景框架同時也支持不限制請全體大小,將 app.maxBody 配置設置成 -1 即可。
### 請求響應
Orange 對原生http響應進行了封裝,有如下方法快速處理http響應
- c.ResponseWrite([]byte) 輸出原始響應內容
- c.ResponseHeader() 配置/獲取響應頭
- c.ToJson(interface{}) 以json的方式輸出響應
- c.ToString(string) 以字符串的方式輸出響應
- c.ToFile("./storage/file.txt", "fileName") 以文件流方式輸出一個文件,瀏覽器會提示下載文件
- c.ToImage("./storage/logo.png") 以文件流方式輸出一個圖片,瀏覽器會直接顯示該圖片
代碼參考
```
...
func Welcome(c *app.Context) error {
return c.ResponseWrite([]byte("歡迎訪問orange框架"))
...
}
func WelcomeJson(c *app.Context) error {
return c.ToJson(map[string]interface{}{
"info": "orange is a fast api framework",
})
}
func WelcomeText(c *app.Context) error {
c.ResponseHeader().Set("Content-Type","application/text")
return c.ToString( "orange is a fast api framework")
}
...
```
### 控制器異步后置操作
在特定的業務中,我們可能需要在請求正常返回后進行一些用戶不可見的處理邏輯;
例如:后臺業務中的行為記錄,批量插入異步處理等等;
Orange 框架提供了后置操作的能力;使用如下:
```
// 控制器方法
func Welcome(c *app.Context) error {
// 添加一個后置執行方法,包含一個執行方法和一個延時時間兩個參數
c.AddDelayAfterDo(func(ctx *app.Context) {
fmt.Println(string(ctx.ResponseBody()), ctx.OrangeInput.IP())
}, time.Second)
return c.ToString("hello world!")
}
```