func ParseParams(params *Params, req *Request) { params.Query = req.URL.Query() // Parse the body depending on the content type. switch req.ContentType { case "application/x-www-form-urlencoded": // Typical form. if err := req.ParseForm(); err != nil { glog.Warningln("Error parsing request body:", err) } else { params.Form = req.Form } case "multipart/form-data": // Multipart form. // TODO: Extract the multipart form param so app can set it. if err := req.ParseMultipartForm(32 << 20 /* 32 MB */); err != nil { glog.Warningln("Error parsing request body:", err) } else { params.Form = req.MultipartForm.Value params.Files = req.MultipartForm.File } } params.Values = params.calcValues() }
func bindFile(params *Params, name string, typ reflect.Type) reflect.Value { reader := getMultipartFile(params, name) if reader == nil { return reflect.Zero(typ) } // If it's already stored in a temp file, just return that. if osFile, ok := reader.(*os.File); ok { return reflect.ValueOf(osFile) } // Otherwise, have to store it. tmpFile, err := ioutil.TempFile("", "revel-upload") if err != nil { glog.Warningln("Failed to create a temp file to store upload:", err) return reflect.Zero(typ) } // Register it to be deleted after the request is done. params.tmpFiles = append(params.tmpFiles, tmpFile) _, err = io.Copy(tmpFile, reader) if err != nil { glog.Warningln("Failed to copy upload to temp file:", err) return reflect.Zero(typ) } _, err = tmpFile.Seek(0, 0) if err != nil { glog.Warningln("Failed to seek to beginning of temp file:", err) return reflect.Zero(typ) } return reflect.ValueOf(tmpFile) }
func bindStruct(params *Params, name string, typ reflect.Type) reflect.Value { result := reflect.New(typ).Elem() fieldValues := make(map[string]reflect.Value) for key, _ := range params.Values { if !strings.HasPrefix(key, name+".") { continue } // Get the name of the struct property. // Strip off the prefix. e.g. foo.bar.baz => bar.baz suffix := key[len(name)+1:] fieldName := nextKey(suffix) fieldLen := len(fieldName) if _, ok := fieldValues[fieldName]; !ok { // Time to bind this field. Get it and make sure we can set it. fieldValue := result.FieldByName(fieldName) if !fieldValue.IsValid() { glog.Warningln("W: bindStruct: Field not found:", fieldName) continue } if !fieldValue.CanSet() { glog.Warningln("W: bindStruct: Field not settable:", fieldName) continue } boundVal := Bind(params, key[:len(name)+1+fieldLen], fieldValue.Type()) fieldValue.Set(boundVal) fieldValues[fieldName] = boundVal } } return result }
func bindByteArray(params *Params, name string, typ reflect.Type) reflect.Value { if reader := getMultipartFile(params, name); reader != nil { b, err := ioutil.ReadAll(reader) if err == nil { return reflect.ValueOf(b) } glog.Warningln("Error reading uploaded file contents:", err) } return reflect.Zero(typ) }
// Helper that returns an upload of the given name, or nil. func getMultipartFile(params *Params, name string) multipart.File { for _, fileHeader := range params.Files[name] { file, err := fileHeader.Open() if err == nil { return file } glog.Warningln("Failed to open uploaded file", name, ":", err) } return nil }
func binderForType(typ reflect.Type) (Binder, bool) { binder, ok := TypeBinders[typ] if !ok { binder, ok = KindBinders[typ.Kind()] if !ok { glog.Warningln("revel/binder: no binder for type:", typ) return Binder{}, false } } return binder, true }
func errorClass(name string, renderArgs map[string]interface{}) template.HTML { errorMap, ok := renderArgs["errors"].(map[string]*ValidationError) if !ok || errorMap == nil { glog.Warningln("Called 'errorClass' without 'errors' in the render args.") return template.HTML("") } valError, ok := errorMap[name] if !ok || valError == nil { return template.HTML("") } return template.HTML(ERROR_CLASS) }
func ParamsFilter(c *Controller, fc []Filter) { ParseParams(c.Params, c.Request) // Clean up from the request. defer func() { // Delete temp files. if c.Request.MultipartForm != nil { err := c.Request.MultipartForm.RemoveAll() if err != nil { glog.Warningln("Error removing temporary files:", err) } } for _, tmpFile := range c.Params.tmpFiles { err := os.Remove(tmpFile.Name()) if err != nil { glog.Warningln("Could not remove upload temp file:", err) } } }() fc[0](c, fc[1:]) }
func RouterFilter(c *Controller, fc []Filter) { // Figure out the Controller/Action var route *RouteMatch = MainRouter.Route(c.Request.Request) if route == nil { c.Result = c.NotFound("No matching route found") return } // The route may want to explicitly return a 404. if route.Action == "404" { c.Result = c.NotFound("(intentionally)") return } // Set the action. if err := c.SetAction(route.ControllerName, route.MethodName); err != nil { c.Result = c.NotFound(err.Error()) return } // Add the route and fixed params to the Request Params. for k, v := range route.Params { if c.Params.Route == nil { c.Params.Route = make(map[string][]string) } c.Params.Route[k] = []string{v} } // Add the fixed parameters mapped by name. for i, value := range route.FixedParams { if c.Params.Fixed == nil { c.Params.Fixed = make(url.Values) } if i < len(c.MethodType.Args) { arg := c.MethodType.Args[i] c.Params.Fixed.Set(arg.Name, value) } else { glog.Warningln("Too many parameters to", route.Action, "trying to add", value) break } } fc[0](c, fc[1:]) }
// Return a file, either displayed inline or downloaded as an attachment. // The name and size are taken from the file info. func (c *Controller) RenderFile(file *os.File, delivery ContentDisposition) Result { var ( modtime = time.Now() fileInfo, err = file.Stat() ) if err != nil { glog.Warningln("RenderFile error:", err) } if fileInfo != nil { modtime = fileInfo.ModTime() } return &BinaryResult{ Reader: file, Name: filepath.Base(file.Name()), Delivery: delivery, Length: -1, // http.ServeContent gets the length itself ModTime: modtime, } }