Controller
package revel
type Controller struct {
Name string
Type *ControllerType
MethodName string
MethodType *MethodType
AppController interface{}
Action string
Request *Request
Response *Response
Result Result
Flash Flash
Session Session
Params *Params
Args map[string]interface{}
RenderArgs map[string]interface{}
Validation *Validation
}
func NewController(req *Request, resp *Response) *Controller {
return &Controller{
Request: req,
Response: resp,
Params: new(Params),
Args: map[string]interface{}{},
RenderArgs: map[string]interface{}{
"RunMode": RunMode,
"DevMode": DevMode,
},
}
}
func (c *Controller) FlashParams() {
for key, vals := range c.Params.Values {
c.Flash.Out[key] = strings.Join(vals, ",")
}
}
func (c *Controller) SetCookie(cookie *http.Cookie) {
http.SetCookie(c.Response.Out, cookie)
}
func (c *Controller) RenderError(err error) Result {
return ErrorResult{c.RenderArgs, err}
}
func (c *Controller) Render(extraRenderArgs ...interface{}) Result {
_, _, line, ok := runtime.Caller(1)
if !ok {
ERROR.Println("Failed to get Caller information")
}
if renderArgNames, ok := c.MethodType.RenderArgNames[line]; ok {
if len(renderArgNames) == len(extraRenderArgs) {
for i, extraRenderArg := range extraRenderArgs {
c.RenderArgs[renderArgNames[i]] = extraRenderArg
}
} else {
ERROR.Println(len(renderArgNames), "RenderArg names found for",
len(extraRenderArgs), "extra RenderArgs")
}
} else {
ERROR.Println("No RenderArg names found for Render call on line", line,
"(Action", c.Action, ")")
}
return c.RenderTemplate(c.Name + "/" + c.MethodType.Name + "." + c.Request.Format)
}
func (c *Controller) RenderTemplate(templatePath string) Result {
template, err := MainTemplateLoader.Template(templatePath)
if err != nil {
return c.RenderError(err)
}
return &RenderTemplateResult{
Template: template,
RenderArgs: c.RenderArgs,
}
}
func (c *Controller) RenderJson(o interface{}) Result {
return RenderJsonResult{o, ""}
}
func (c *Controller) RenderJsonP(callback string, o interface{}) Result {
return RenderJsonResult{o, callback}
}
func (c *Controller) RenderXml(o interface{}) Result {
return RenderXmlResult{o}
}
func (c *Controller) RenderText(text string, objs ...interface{}) Result {
finalText := text
if len(objs) > 0 {
finalText = fmt.Sprintf(text, objs...)
}
return &RenderTextResult{finalText}
}
func (c *Controller) RenderHtml(html string) Result {
return &RenderHtmlResult{html}
}
func (c *Controller) Todo() Result {
c.Response.Status = http.StatusNotImplemented
return c.RenderError(&Error{
Title: "TODO",
Description: "This action is not implemented",
})
}
func (c *Controller) NotFound(msg string, objs ...interface{}) Result {
finalText := msg
if len(objs) > 0 {
finalText = fmt.Sprintf(msg, objs...)
}
c.Response.Status = http.StatusNotFound
return c.RenderError(&Error{
Title: "Not Found",
Description: finalText,
})
}
func (c *Controller) Forbidden(msg string, objs ...interface{}) Result {
finalText := msg
if len(objs) > 0 {
finalText = fmt.Sprintf(msg, objs...)
}
c.Response.Status = http.StatusForbidden
return c.RenderError(&Error{
Title: "Forbidden",
Description: finalText,
})
}
func (c *Controller) RenderFile(file *os.File, delivery ContentDisposition) Result {
var (
modtime = time.Now()
fileInfo, err = file.Stat()
)
if err != nil {
WARN.Println("RenderFile error:", err)
}
if fileInfo != nil {
modtime = fileInfo.ModTime()
}
return c.RenderBinary(file, filepath.Base(file.Name()), delivery, modtime)
}
func (c *Controller) RenderBinary(memfile io.Reader, filename string, delivery ContentDisposition, modtime time.Time) Result {
return &BinaryResult{
Reader: memfile,
Name: filename,
Delivery: delivery,
Length: -1,
ModTime: modtime,
}
}
func (c *Controller) Redirect(val interface{}, args ...interface{}) Result {
if url, ok := val.(string); ok {
if len(args) == 0 {
return &RedirectToUrlResult{url}
}
return &RedirectToUrlResult{fmt.Sprintf(url, args...)}
}
return &RedirectToActionResult{val}
}
func (c *Controller) Message(message string, args ...interface{}) (value string) {
return Message(c.Request.Locale, message, args...)
}
func (c *Controller) SetAction(controllerName, methodName string) error {
var ok bool
if c.Type, ok = controllers[strings.ToLower(controllerName)]; !ok {
return errors.New("revel/controller: failed to find controller " + controllerName)
}
if c.MethodType = c.Type.Method(methodName); c.MethodType == nil {
return errors.New("revel/controller: failed to find action " + methodName)
}
c.Name, c.MethodName = c.Type.Type.Name(), methodName
c.Action = c.Name + "." + c.MethodName
c.AppController = initNewAppController(c.Type, c).Interface()
return nil
}
type ControllerType struct {
Type reflect.Type
Methods []*MethodType
ControllerIndexes [][]int
}
type MethodType struct {
Name string
Args []*MethodArg
RenderArgNames map[int][]string
}
type MethodArg struct {
Name string
Type reflect.Type
}
func (ct *ControllerType) Method(name string) *MethodType {
lowerName := strings.ToLower(name)
for _, method := range ct.Methods {
if method.lowerName == lowerName {
return method
}
}
return nil
}
func RegisterController(c interface{}, methods []*MethodType) {
var t reflect.Type = reflect.TypeOf(c)
var elem reflect.Type = t.Elem()
for _, m := range methods {
m.lowerName = strings.ToLower(m.Name)
for _, arg := range m.Args {
arg.Type = arg.Type.Elem()
}
}
controllers[strings.ToLower(elem.Name())] = &ControllerType{
Type: elem,
Methods: methods,
ControllerIndexes: findControllers(elem),
}
TRACE.Printf("Registered controller: %s", elem.Name())
}