controller.go 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706
  1. // Copyright 2014 beego Author. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package beego
  15. import (
  16. "bytes"
  17. "errors"
  18. "fmt"
  19. "html/template"
  20. "io"
  21. "mime/multipart"
  22. "net/http"
  23. "net/url"
  24. "os"
  25. "reflect"
  26. "strconv"
  27. "strings"
  28. "github.com/astaxie/beego/context"
  29. "github.com/astaxie/beego/context/param"
  30. "github.com/astaxie/beego/session"
  31. )
  32. var (
  33. // ErrAbort custom error when user stop request handler manually.
  34. ErrAbort = errors.New("user stop run")
  35. // GlobalControllerRouter store comments with controller. pkgpath+controller:comments
  36. GlobalControllerRouter = make(map[string][]ControllerComments)
  37. )
  38. // ControllerFilter store the filter for controller
  39. type ControllerFilter struct {
  40. Pattern string
  41. Pos int
  42. Filter FilterFunc
  43. ReturnOnOutput bool
  44. ResetParams bool
  45. }
  46. // ControllerFilterComments store the comment for controller level filter
  47. type ControllerFilterComments struct {
  48. Pattern string
  49. Pos int
  50. Filter string // NOQA
  51. ReturnOnOutput bool
  52. ResetParams bool
  53. }
  54. // ControllerImportComments store the import comment for controller needed
  55. type ControllerImportComments struct {
  56. ImportPath string
  57. ImportAlias string
  58. }
  59. // ControllerComments store the comment for the controller method
  60. type ControllerComments struct {
  61. Method string
  62. Router string
  63. Filters []*ControllerFilter
  64. ImportComments []*ControllerImportComments
  65. FilterComments []*ControllerFilterComments
  66. AllowHTTPMethods []string
  67. Params []map[string]string
  68. MethodParams []*param.MethodParam
  69. }
  70. // ControllerCommentsSlice implements the sort interface
  71. type ControllerCommentsSlice []ControllerComments
  72. func (p ControllerCommentsSlice) Len() int { return len(p) }
  73. func (p ControllerCommentsSlice) Less(i, j int) bool { return p[i].Router < p[j].Router }
  74. func (p ControllerCommentsSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
  75. // Controller defines some basic http request handler operations, such as
  76. // http context, template and view, session and xsrf.
  77. type Controller struct {
  78. // context data
  79. Ctx *context.Context
  80. Data map[interface{}]interface{}
  81. // route controller info
  82. controllerName string
  83. actionName string
  84. methodMapping map[string]func() //method:routertree
  85. AppController interface{}
  86. // template data
  87. TplName string
  88. ViewPath string
  89. Layout string
  90. LayoutSections map[string]string // the key is the section name and the value is the template name
  91. TplPrefix string
  92. TplExt string
  93. EnableRender bool
  94. // xsrf data
  95. _xsrfToken string
  96. XSRFExpire int
  97. EnableXSRF bool
  98. // session
  99. CruSession session.Store
  100. }
  101. // ControllerInterface is an interface to uniform all controller handler.
  102. type ControllerInterface interface {
  103. Init(ct *context.Context, controllerName, actionName string, app interface{})
  104. Prepare()
  105. Get()
  106. Post()
  107. Delete()
  108. Put()
  109. Head()
  110. Patch()
  111. Options()
  112. Trace()
  113. Finish()
  114. Render() error
  115. XSRFToken() string
  116. CheckXSRFCookie() bool
  117. HandlerFunc(fn string) bool
  118. URLMapping()
  119. }
  120. // Init generates default values of controller operations.
  121. func (c *Controller) Init(ctx *context.Context, controllerName, actionName string, app interface{}) {
  122. c.Layout = ""
  123. c.TplName = ""
  124. c.controllerName = controllerName
  125. c.actionName = actionName
  126. c.Ctx = ctx
  127. c.TplExt = "tpl"
  128. c.AppController = app
  129. c.EnableRender = true
  130. c.EnableXSRF = true
  131. c.Data = ctx.Input.Data()
  132. c.methodMapping = make(map[string]func())
  133. }
  134. // Prepare runs after Init before request function execution.
  135. func (c *Controller) Prepare() {}
  136. // Finish runs after request function execution.
  137. func (c *Controller) Finish() {}
  138. // Get adds a request function to handle GET request.
  139. func (c *Controller) Get() {
  140. http.Error(c.Ctx.ResponseWriter, "Method Not Allowed", http.StatusMethodNotAllowed)
  141. }
  142. // Post adds a request function to handle POST request.
  143. func (c *Controller) Post() {
  144. http.Error(c.Ctx.ResponseWriter, "Method Not Allowed", http.StatusMethodNotAllowed)
  145. }
  146. // Delete adds a request function to handle DELETE request.
  147. func (c *Controller) Delete() {
  148. http.Error(c.Ctx.ResponseWriter, "Method Not Allowed", http.StatusMethodNotAllowed)
  149. }
  150. // Put adds a request function to handle PUT request.
  151. func (c *Controller) Put() {
  152. http.Error(c.Ctx.ResponseWriter, "Method Not Allowed", http.StatusMethodNotAllowed)
  153. }
  154. // Head adds a request function to handle HEAD request.
  155. func (c *Controller) Head() {
  156. http.Error(c.Ctx.ResponseWriter, "Method Not Allowed", http.StatusMethodNotAllowed)
  157. }
  158. // Patch adds a request function to handle PATCH request.
  159. func (c *Controller) Patch() {
  160. http.Error(c.Ctx.ResponseWriter, "Method Not Allowed", http.StatusMethodNotAllowed)
  161. }
  162. // Options adds a request function to handle OPTIONS request.
  163. func (c *Controller) Options() {
  164. http.Error(c.Ctx.ResponseWriter, "Method Not Allowed", http.StatusMethodNotAllowed)
  165. }
  166. // Trace adds a request function to handle Trace request.
  167. // this method SHOULD NOT be overridden.
  168. // https://tools.ietf.org/html/rfc7231#section-4.3.8
  169. // The TRACE method requests a remote, application-level loop-back of
  170. // the request message. The final recipient of the request SHOULD
  171. // reflect the message received, excluding some fields described below,
  172. // back to the client as the message body of a 200 (OK) response with a
  173. // Content-Type of "message/http" (Section 8.3.1 of [RFC7230]).
  174. func (c *Controller) Trace() {
  175. ts := func(h http.Header) (hs string) {
  176. for k, v := range h {
  177. hs += fmt.Sprintf("\r\n%s: %s", k, v)
  178. }
  179. return
  180. }
  181. hs := fmt.Sprintf("\r\nTRACE %s %s%s\r\n", c.Ctx.Request.RequestURI, c.Ctx.Request.Proto, ts(c.Ctx.Request.Header))
  182. c.Ctx.Output.Header("Content-Type", "message/http")
  183. c.Ctx.Output.Header("Content-Length", fmt.Sprint(len(hs)))
  184. c.Ctx.Output.Header("Cache-Control", "no-cache, no-store, must-revalidate")
  185. c.Ctx.WriteString(hs)
  186. }
  187. // HandlerFunc call function with the name
  188. func (c *Controller) HandlerFunc(fnname string) bool {
  189. if v, ok := c.methodMapping[fnname]; ok {
  190. v()
  191. return true
  192. }
  193. return false
  194. }
  195. // URLMapping register the internal Controller router.
  196. func (c *Controller) URLMapping() {}
  197. // Mapping the method to function
  198. func (c *Controller) Mapping(method string, fn func()) {
  199. c.methodMapping[method] = fn
  200. }
  201. // Render sends the response with rendered template bytes as text/html type.
  202. func (c *Controller) Render() error {
  203. if !c.EnableRender {
  204. return nil
  205. }
  206. rb, err := c.RenderBytes()
  207. if err != nil {
  208. return err
  209. }
  210. if c.Ctx.ResponseWriter.Header().Get("Content-Type") == "" {
  211. c.Ctx.Output.Header("Content-Type", "text/html; charset=utf-8")
  212. }
  213. return c.Ctx.Output.Body(rb)
  214. }
  215. // RenderString returns the rendered template string. Do not send out response.
  216. func (c *Controller) RenderString() (string, error) {
  217. b, e := c.RenderBytes()
  218. return string(b), e
  219. }
  220. // RenderBytes returns the bytes of rendered template string. Do not send out response.
  221. func (c *Controller) RenderBytes() ([]byte, error) {
  222. buf, err := c.renderTemplate()
  223. //if the controller has set layout, then first get the tplName's content set the content to the layout
  224. if err == nil && c.Layout != "" {
  225. c.Data["LayoutContent"] = template.HTML(buf.String())
  226. if c.LayoutSections != nil {
  227. for sectionName, sectionTpl := range c.LayoutSections {
  228. if sectionTpl == "" {
  229. c.Data[sectionName] = ""
  230. continue
  231. }
  232. buf.Reset()
  233. err = ExecuteViewPathTemplate(&buf, sectionTpl, c.viewPath(), c.Data)
  234. if err != nil {
  235. return nil, err
  236. }
  237. c.Data[sectionName] = template.HTML(buf.String())
  238. }
  239. }
  240. buf.Reset()
  241. ExecuteViewPathTemplate(&buf, c.Layout, c.viewPath(), c.Data)
  242. }
  243. return buf.Bytes(), err
  244. }
  245. func (c *Controller) renderTemplate() (bytes.Buffer, error) {
  246. var buf bytes.Buffer
  247. if c.TplName == "" {
  248. c.TplName = strings.ToLower(c.controllerName) + "/" + strings.ToLower(c.actionName) + "." + c.TplExt
  249. }
  250. if c.TplPrefix != "" {
  251. c.TplName = c.TplPrefix + c.TplName
  252. }
  253. if BConfig.RunMode == DEV {
  254. buildFiles := []string{c.TplName}
  255. if c.Layout != "" {
  256. buildFiles = append(buildFiles, c.Layout)
  257. if c.LayoutSections != nil {
  258. for _, sectionTpl := range c.LayoutSections {
  259. if sectionTpl == "" {
  260. continue
  261. }
  262. buildFiles = append(buildFiles, sectionTpl)
  263. }
  264. }
  265. }
  266. BuildTemplate(c.viewPath(), buildFiles...)
  267. }
  268. return buf, ExecuteViewPathTemplate(&buf, c.TplName, c.viewPath(), c.Data)
  269. }
  270. func (c *Controller) viewPath() string {
  271. if c.ViewPath == "" {
  272. return BConfig.WebConfig.ViewsPath
  273. }
  274. return c.ViewPath
  275. }
  276. // Redirect sends the redirection response to url with status code.
  277. func (c *Controller) Redirect(url string, code int) {
  278. LogAccess(c.Ctx, nil, code)
  279. c.Ctx.Redirect(code, url)
  280. }
  281. // SetData set the data depending on the accepted
  282. func (c *Controller) SetData(data interface{}) {
  283. accept := c.Ctx.Input.Header("Accept")
  284. switch accept {
  285. case context.ApplicationYAML:
  286. c.Data["yaml"] = data
  287. case context.ApplicationXML, context.TextXML:
  288. c.Data["xml"] = data
  289. default:
  290. c.Data["json"] = data
  291. }
  292. }
  293. // Abort stops controller handler and show the error data if code is defined in ErrorMap or code string.
  294. func (c *Controller) Abort(code string) {
  295. status, err := strconv.Atoi(code)
  296. if err != nil {
  297. status = 200
  298. }
  299. c.CustomAbort(status, code)
  300. }
  301. // CustomAbort stops controller handler and show the error data, it's similar Aborts, but support status code and body.
  302. func (c *Controller) CustomAbort(status int, body string) {
  303. // first panic from ErrorMaps, it is user defined error functions.
  304. if _, ok := ErrorMaps[body]; ok {
  305. c.Ctx.Output.Status = status
  306. panic(body)
  307. }
  308. // last panic user string
  309. c.Ctx.ResponseWriter.WriteHeader(status)
  310. c.Ctx.ResponseWriter.Write([]byte(body))
  311. panic(ErrAbort)
  312. }
  313. // StopRun makes panic of USERSTOPRUN error and go to recover function if defined.
  314. func (c *Controller) StopRun() {
  315. panic(ErrAbort)
  316. }
  317. // URLFor does another controller handler in this request function.
  318. // it goes to this controller method if endpoint is not clear.
  319. func (c *Controller) URLFor(endpoint string, values ...interface{}) string {
  320. if len(endpoint) == 0 {
  321. return ""
  322. }
  323. if endpoint[0] == '.' {
  324. return URLFor(reflect.Indirect(reflect.ValueOf(c.AppController)).Type().Name()+endpoint, values...)
  325. }
  326. return URLFor(endpoint, values...)
  327. }
  328. // ServeJSON sends a json response with encoding charset.
  329. func (c *Controller) ServeJSON(encoding ...bool) {
  330. var (
  331. hasIndent = BConfig.RunMode != PROD
  332. hasEncoding = len(encoding) > 0 && encoding[0]
  333. )
  334. c.Ctx.Output.JSON(c.Data["json"], hasIndent, hasEncoding)
  335. }
  336. // ServeJSONP sends a jsonp response.
  337. func (c *Controller) ServeJSONP() {
  338. hasIndent := BConfig.RunMode != PROD
  339. c.Ctx.Output.JSONP(c.Data["jsonp"], hasIndent)
  340. }
  341. // ServeXML sends xml response.
  342. func (c *Controller) ServeXML() {
  343. hasIndent := BConfig.RunMode != PROD
  344. c.Ctx.Output.XML(c.Data["xml"], hasIndent)
  345. }
  346. // ServeYAML sends yaml response.
  347. func (c *Controller) ServeYAML() {
  348. c.Ctx.Output.YAML(c.Data["yaml"])
  349. }
  350. // ServeFormatted serve YAML, XML OR JSON, depending on the value of the Accept header
  351. func (c *Controller) ServeFormatted(encoding ...bool) {
  352. hasIndent := BConfig.RunMode != PROD
  353. hasEncoding := len(encoding) > 0 && encoding[0]
  354. c.Ctx.Output.ServeFormatted(c.Data, hasIndent, hasEncoding)
  355. }
  356. // Input returns the input data map from POST or PUT request body and query string.
  357. func (c *Controller) Input() url.Values {
  358. if c.Ctx.Request.Form == nil {
  359. c.Ctx.Request.ParseForm()
  360. }
  361. return c.Ctx.Request.Form
  362. }
  363. // ParseForm maps input data map to obj struct.
  364. func (c *Controller) ParseForm(obj interface{}) error {
  365. return ParseForm(c.Input(), obj)
  366. }
  367. // GetString returns the input value by key string or the default value while it's present and input is blank
  368. func (c *Controller) GetString(key string, def ...string) string {
  369. if v := c.Ctx.Input.Query(key); v != "" {
  370. return v
  371. }
  372. if len(def) > 0 {
  373. return def[0]
  374. }
  375. return ""
  376. }
  377. // GetStrings returns the input string slice by key string or the default value while it's present and input is blank
  378. // it's designed for multi-value input field such as checkbox(input[type=checkbox]), multi-selection.
  379. func (c *Controller) GetStrings(key string, def ...[]string) []string {
  380. var defv []string
  381. if len(def) > 0 {
  382. defv = def[0]
  383. }
  384. if f := c.Input(); f == nil {
  385. return defv
  386. } else if vs := f[key]; len(vs) > 0 {
  387. return vs
  388. }
  389. return defv
  390. }
  391. // GetInt returns input as an int or the default value while it's present and input is blank
  392. func (c *Controller) GetInt(key string, def ...int) (int, error) {
  393. strv := c.Ctx.Input.Query(key)
  394. if len(strv) == 0 && len(def) > 0 {
  395. return def[0], nil
  396. }
  397. return strconv.Atoi(strv)
  398. }
  399. // GetInt8 return input as an int8 or the default value while it's present and input is blank
  400. func (c *Controller) GetInt8(key string, def ...int8) (int8, error) {
  401. strv := c.Ctx.Input.Query(key)
  402. if len(strv) == 0 && len(def) > 0 {
  403. return def[0], nil
  404. }
  405. i64, err := strconv.ParseInt(strv, 10, 8)
  406. return int8(i64), err
  407. }
  408. // GetUint8 return input as an uint8 or the default value while it's present and input is blank
  409. func (c *Controller) GetUint8(key string, def ...uint8) (uint8, error) {
  410. strv := c.Ctx.Input.Query(key)
  411. if len(strv) == 0 && len(def) > 0 {
  412. return def[0], nil
  413. }
  414. u64, err := strconv.ParseUint(strv, 10, 8)
  415. return uint8(u64), err
  416. }
  417. // GetInt16 returns input as an int16 or the default value while it's present and input is blank
  418. func (c *Controller) GetInt16(key string, def ...int16) (int16, error) {
  419. strv := c.Ctx.Input.Query(key)
  420. if len(strv) == 0 && len(def) > 0 {
  421. return def[0], nil
  422. }
  423. i64, err := strconv.ParseInt(strv, 10, 16)
  424. return int16(i64), err
  425. }
  426. // GetUint16 returns input as an uint16 or the default value while it's present and input is blank
  427. func (c *Controller) GetUint16(key string, def ...uint16) (uint16, error) {
  428. strv := c.Ctx.Input.Query(key)
  429. if len(strv) == 0 && len(def) > 0 {
  430. return def[0], nil
  431. }
  432. u64, err := strconv.ParseUint(strv, 10, 16)
  433. return uint16(u64), err
  434. }
  435. // GetInt32 returns input as an int32 or the default value while it's present and input is blank
  436. func (c *Controller) GetInt32(key string, def ...int32) (int32, error) {
  437. strv := c.Ctx.Input.Query(key)
  438. if len(strv) == 0 && len(def) > 0 {
  439. return def[0], nil
  440. }
  441. i64, err := strconv.ParseInt(strv, 10, 32)
  442. return int32(i64), err
  443. }
  444. // GetUint32 returns input as an uint32 or the default value while it's present and input is blank
  445. func (c *Controller) GetUint32(key string, def ...uint32) (uint32, error) {
  446. strv := c.Ctx.Input.Query(key)
  447. if len(strv) == 0 && len(def) > 0 {
  448. return def[0], nil
  449. }
  450. u64, err := strconv.ParseUint(strv, 10, 32)
  451. return uint32(u64), err
  452. }
  453. // GetInt64 returns input value as int64 or the default value while it's present and input is blank.
  454. func (c *Controller) GetInt64(key string, def ...int64) (int64, error) {
  455. strv := c.Ctx.Input.Query(key)
  456. if len(strv) == 0 && len(def) > 0 {
  457. return def[0], nil
  458. }
  459. return strconv.ParseInt(strv, 10, 64)
  460. }
  461. // GetUint64 returns input value as uint64 or the default value while it's present and input is blank.
  462. func (c *Controller) GetUint64(key string, def ...uint64) (uint64, error) {
  463. strv := c.Ctx.Input.Query(key)
  464. if len(strv) == 0 && len(def) > 0 {
  465. return def[0], nil
  466. }
  467. return strconv.ParseUint(strv, 10, 64)
  468. }
  469. // GetBool returns input value as bool or the default value while it's present and input is blank.
  470. func (c *Controller) GetBool(key string, def ...bool) (bool, error) {
  471. strv := c.Ctx.Input.Query(key)
  472. if len(strv) == 0 && len(def) > 0 {
  473. return def[0], nil
  474. }
  475. return strconv.ParseBool(strv)
  476. }
  477. // GetFloat returns input value as float64 or the default value while it's present and input is blank.
  478. func (c *Controller) GetFloat(key string, def ...float64) (float64, error) {
  479. strv := c.Ctx.Input.Query(key)
  480. if len(strv) == 0 && len(def) > 0 {
  481. return def[0], nil
  482. }
  483. return strconv.ParseFloat(strv, 64)
  484. }
  485. // GetFile returns the file data in file upload field named as key.
  486. // it returns the first one of multi-uploaded files.
  487. func (c *Controller) GetFile(key string) (multipart.File, *multipart.FileHeader, error) {
  488. return c.Ctx.Request.FormFile(key)
  489. }
  490. // GetFiles return multi-upload files
  491. // files, err:=c.GetFiles("myfiles")
  492. // if err != nil {
  493. // http.Error(w, err.Error(), http.StatusNoContent)
  494. // return
  495. // }
  496. // for i, _ := range files {
  497. // //for each fileheader, get a handle to the actual file
  498. // file, err := files[i].Open()
  499. // defer file.Close()
  500. // if err != nil {
  501. // http.Error(w, err.Error(), http.StatusInternalServerError)
  502. // return
  503. // }
  504. // //create destination file making sure the path is writeable.
  505. // dst, err := os.Create("upload/" + files[i].Filename)
  506. // defer dst.Close()
  507. // if err != nil {
  508. // http.Error(w, err.Error(), http.StatusInternalServerError)
  509. // return
  510. // }
  511. // //copy the uploaded file to the destination file
  512. // if _, err := io.Copy(dst, file); err != nil {
  513. // http.Error(w, err.Error(), http.StatusInternalServerError)
  514. // return
  515. // }
  516. // }
  517. func (c *Controller) GetFiles(key string) ([]*multipart.FileHeader, error) {
  518. if files, ok := c.Ctx.Request.MultipartForm.File[key]; ok {
  519. return files, nil
  520. }
  521. return nil, http.ErrMissingFile
  522. }
  523. // SaveToFile saves uploaded file to new path.
  524. // it only operates the first one of mutil-upload form file field.
  525. func (c *Controller) SaveToFile(fromfile, tofile string) error {
  526. file, _, err := c.Ctx.Request.FormFile(fromfile)
  527. if err != nil {
  528. return err
  529. }
  530. defer file.Close()
  531. f, err := os.OpenFile(tofile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
  532. if err != nil {
  533. return err
  534. }
  535. defer f.Close()
  536. io.Copy(f, file)
  537. return nil
  538. }
  539. // StartSession starts session and load old session data info this controller.
  540. func (c *Controller) StartSession() session.Store {
  541. if c.CruSession == nil {
  542. c.CruSession = c.Ctx.Input.CruSession
  543. }
  544. return c.CruSession
  545. }
  546. // SetSession puts value into session.
  547. func (c *Controller) SetSession(name interface{}, value interface{}) {
  548. if c.CruSession == nil {
  549. c.StartSession()
  550. }
  551. c.CruSession.Set(name, value)
  552. }
  553. // GetSession gets value from session.
  554. func (c *Controller) GetSession(name interface{}) interface{} {
  555. if c.CruSession == nil {
  556. c.StartSession()
  557. }
  558. return c.CruSession.Get(name)
  559. }
  560. // DelSession removes value from session.
  561. func (c *Controller) DelSession(name interface{}) {
  562. if c.CruSession == nil {
  563. c.StartSession()
  564. }
  565. c.CruSession.Delete(name)
  566. }
  567. // SessionRegenerateID regenerates session id for this session.
  568. // the session data have no changes.
  569. func (c *Controller) SessionRegenerateID() {
  570. if c.CruSession != nil {
  571. c.CruSession.SessionRelease(c.Ctx.ResponseWriter)
  572. }
  573. c.CruSession = GlobalSessions.SessionRegenerateID(c.Ctx.ResponseWriter, c.Ctx.Request)
  574. c.Ctx.Input.CruSession = c.CruSession
  575. }
  576. // DestroySession cleans session data and session cookie.
  577. func (c *Controller) DestroySession() {
  578. c.Ctx.Input.CruSession.Flush()
  579. c.Ctx.Input.CruSession = nil
  580. GlobalSessions.SessionDestroy(c.Ctx.ResponseWriter, c.Ctx.Request)
  581. }
  582. // IsAjax returns this request is ajax or not.
  583. func (c *Controller) IsAjax() bool {
  584. return c.Ctx.Input.IsAjax()
  585. }
  586. // GetSecureCookie returns decoded cookie value from encoded browser cookie values.
  587. func (c *Controller) GetSecureCookie(Secret, key string) (string, bool) {
  588. return c.Ctx.GetSecureCookie(Secret, key)
  589. }
  590. // SetSecureCookie puts value into cookie after encoded the value.
  591. func (c *Controller) SetSecureCookie(Secret, name, value string, others ...interface{}) {
  592. c.Ctx.SetSecureCookie(Secret, name, value, others...)
  593. }
  594. // XSRFToken creates a CSRF token string and returns.
  595. func (c *Controller) XSRFToken() string {
  596. if c._xsrfToken == "" {
  597. expire := int64(BConfig.WebConfig.XSRFExpire)
  598. if c.XSRFExpire > 0 {
  599. expire = int64(c.XSRFExpire)
  600. }
  601. c._xsrfToken = c.Ctx.XSRFToken(BConfig.WebConfig.XSRFKey, expire)
  602. }
  603. return c._xsrfToken
  604. }
  605. // CheckXSRFCookie checks xsrf token in this request is valid or not.
  606. // the token can provided in request header "X-Xsrftoken" and "X-CsrfToken"
  607. // or in form field value named as "_xsrf".
  608. func (c *Controller) CheckXSRFCookie() bool {
  609. if !c.EnableXSRF {
  610. return true
  611. }
  612. return c.Ctx.CheckXSRFCookie()
  613. }
  614. // XSRFFormHTML writes an input field contains xsrf token value.
  615. func (c *Controller) XSRFFormHTML() string {
  616. return `<input type="hidden" name="_xsrf" value="` +
  617. c.XSRFToken() + `" />`
  618. }
  619. // GetControllerAndAction gets the executing controller name and action name.
  620. func (c *Controller) GetControllerAndAction() (string, string) {
  621. return c.controllerName, c.actionName
  622. }