@@ -19,6 +19,7 @@ import ( | |||||
"github.com/gogits/gogs/modules/base" | "github.com/gogits/gogs/modules/base" | ||||
"github.com/gogits/gogs/modules/log" | "github.com/gogits/gogs/modules/log" | ||||
"github.com/gogits/gogs/modules/middleware" | "github.com/gogits/gogs/modules/middleware" | ||||
"github.com/gogits/gogs/modules/middleware/binding" | |||||
"github.com/gogits/gogs/routers" | "github.com/gogits/gogs/routers" | ||||
"github.com/gogits/gogs/routers/admin" | "github.com/gogits/gogs/routers/admin" | ||||
"github.com/gogits/gogs/routers/api/v1" | "github.com/gogits/gogs/routers/api/v1" | ||||
@@ -62,7 +63,7 @@ func runWeb(*cli.Context) { | |||||
reqSignOut := middleware.Toggle(&middleware.ToggleOptions{SignOutRequire: true}) | reqSignOut := middleware.Toggle(&middleware.ToggleOptions{SignOutRequire: true}) | ||||
bindIgnErr := middleware.BindIgnErr | |||||
bindIgnErr := binding.BindIgnErr | |||||
// Routers. | // Routers. | ||||
m.Get("/", ignSignIn, routers.Home) | m.Get("/", ignSignIn, routers.Home) | ||||
@@ -101,7 +102,7 @@ func runWeb(*cli.Context) { | |||||
r.Post("/settings", bindIgnErr(auth.UpdateProfileForm{}), user.SettingPost) | r.Post("/settings", bindIgnErr(auth.UpdateProfileForm{}), user.SettingPost) | ||||
}, reqSignIn) | }, reqSignIn) | ||||
m.Group("/user", func(r martini.Router) { | m.Group("/user", func(r martini.Router) { | ||||
r.Get("/feeds", middleware.Bind(auth.FeedsForm{}), user.Feeds) | |||||
r.Get("/feeds", binding.Bind(auth.FeedsForm{}), user.Feeds) | |||||
r.Any("/activate", user.Activate) | r.Any("/activate", user.Activate) | ||||
r.Get("/email2user", user.Email2User) | r.Get("/email2user", user.Email2User) | ||||
r.Get("/forget_password", user.ForgotPasswd) | r.Get("/forget_password", user.ForgotPasswd) | ||||
@@ -20,7 +20,7 @@ import ( | |||||
// Test that go1.2 tag above is included in builds. main.go refers to this definition. | // Test that go1.2 tag above is included in builds. main.go refers to this definition. | ||||
const go12tag = true | const go12tag = true | ||||
const APP_VER = "0.3.2.0503 Alpha" | |||||
const APP_VER = "0.3.2.0505 Alpha" | |||||
func init() { | func init() { | ||||
base.AppVer = APP_VER | base.AppVer = APP_VER | ||||
@@ -12,6 +12,7 @@ import ( | |||||
"github.com/gogits/gogs/modules/base" | "github.com/gogits/gogs/modules/base" | ||||
"github.com/gogits/gogs/modules/log" | "github.com/gogits/gogs/modules/log" | ||||
"github.com/gogits/gogs/modules/middleware/binding" | |||||
) | ) | ||||
type AdminEditUserForm struct { | type AdminEditUserForm struct { | ||||
@@ -33,7 +34,7 @@ func (f *AdminEditUserForm) Name(field string) string { | |||||
return names[field] | return names[field] | ||||
} | } | ||||
func (f *AdminEditUserForm) Validate(errors *base.BindingErrors, req *http.Request, context martini.Context) { | |||||
func (f *AdminEditUserForm) Validate(errors *binding.BindingErrors, req *http.Request, context martini.Context) { | |||||
if req.Method == "GET" || errors.Count() == 0 { | if req.Method == "GET" || errors.Count() == 0 { | ||||
return | return | ||||
} | } | ||||
@@ -13,6 +13,7 @@ import ( | |||||
"github.com/gogits/gogs/modules/base" | "github.com/gogits/gogs/modules/base" | ||||
"github.com/gogits/gogs/modules/log" | "github.com/gogits/gogs/modules/log" | ||||
"github.com/gogits/gogs/modules/middleware/binding" | |||||
) | ) | ||||
// Web form interface. | // Web form interface. | ||||
@@ -37,7 +38,7 @@ func (f *RegisterForm) Name(field string) string { | |||||
return names[field] | return names[field] | ||||
} | } | ||||
func (f *RegisterForm) Validate(errors *base.BindingErrors, req *http.Request, context martini.Context) { | |||||
func (f *RegisterForm) Validate(errors *binding.BindingErrors, req *http.Request, context martini.Context) { | |||||
if req.Method == "GET" || errors.Count() == 0 { | if req.Method == "GET" || errors.Count() == 0 { | ||||
return | return | ||||
} | } | ||||
@@ -70,7 +71,7 @@ func (f *LogInForm) Name(field string) string { | |||||
return names[field] | return names[field] | ||||
} | } | ||||
func (f *LogInForm) Validate(errors *base.BindingErrors, req *http.Request, context martini.Context) { | |||||
func (f *LogInForm) Validate(errors *binding.BindingErrors, req *http.Request, context martini.Context) { | |||||
if req.Method == "GET" || errors.Count() == 0 { | if req.Method == "GET" || errors.Count() == 0 { | ||||
return | return | ||||
} | } | ||||
@@ -98,7 +99,7 @@ func getMinMaxSize(field reflect.StructField) string { | |||||
return "" | return "" | ||||
} | } | ||||
func validate(errors *base.BindingErrors, data base.TmplData, form Form) { | |||||
func validate(errors *binding.BindingErrors, data base.TmplData, form Form) { | |||||
typ := reflect.TypeOf(form) | typ := reflect.TypeOf(form) | ||||
val := reflect.ValueOf(form) | val := reflect.ValueOf(form) | ||||
@@ -119,19 +120,19 @@ func validate(errors *base.BindingErrors, data base.TmplData, form Form) { | |||||
if err, ok := errors.Fields[field.Name]; ok { | if err, ok := errors.Fields[field.Name]; ok { | ||||
data["Err_"+field.Name] = true | data["Err_"+field.Name] = true | ||||
switch err { | switch err { | ||||
case base.BindingRequireError: | |||||
case binding.BindingRequireError: | |||||
data["ErrorMsg"] = form.Name(field.Name) + " cannot be empty" | data["ErrorMsg"] = form.Name(field.Name) + " cannot be empty" | ||||
case base.BindingAlphaDashError: | |||||
case binding.BindingAlphaDashError: | |||||
data["ErrorMsg"] = form.Name(field.Name) + " must be valid alpha or numeric or dash(-_) characters" | data["ErrorMsg"] = form.Name(field.Name) + " must be valid alpha or numeric or dash(-_) characters" | ||||
case base.BindingAlphaDashDotError: | |||||
case binding.BindingAlphaDashDotError: | |||||
data["ErrorMsg"] = form.Name(field.Name) + " must be valid alpha or numeric or dash(-_) or dot characters" | data["ErrorMsg"] = form.Name(field.Name) + " must be valid alpha or numeric or dash(-_) or dot characters" | ||||
case base.BindingMinSizeError: | |||||
case binding.BindingMinSizeError: | |||||
data["ErrorMsg"] = form.Name(field.Name) + " must contain at least " + getMinMaxSize(field) + " characters" | data["ErrorMsg"] = form.Name(field.Name) + " must contain at least " + getMinMaxSize(field) + " characters" | ||||
case base.BindingMaxSizeError: | |||||
case binding.BindingMaxSizeError: | |||||
data["ErrorMsg"] = form.Name(field.Name) + " must contain at most " + getMinMaxSize(field) + " characters" | data["ErrorMsg"] = form.Name(field.Name) + " must contain at most " + getMinMaxSize(field) + " characters" | ||||
case base.BindingEmailError: | |||||
case binding.BindingEmailError: | |||||
data["ErrorMsg"] = form.Name(field.Name) + " is not a valid e-mail address" | data["ErrorMsg"] = form.Name(field.Name) + " is not a valid e-mail address" | ||||
case base.BindingUrlError: | |||||
case binding.BindingUrlError: | |||||
data["ErrorMsg"] = form.Name(field.Name) + " is not a valid URL" | data["ErrorMsg"] = form.Name(field.Name) + " is not a valid URL" | ||||
default: | default: | ||||
data["ErrorMsg"] = "Unknown error: " + err | data["ErrorMsg"] = "Unknown error: " + err | ||||
@@ -196,7 +197,7 @@ func (f *InstallForm) Name(field string) string { | |||||
return names[field] | return names[field] | ||||
} | } | ||||
func (f *InstallForm) Validate(errors *base.BindingErrors, req *http.Request, context martini.Context) { | |||||
func (f *InstallForm) Validate(errors *binding.BindingErrors, req *http.Request, context martini.Context) { | |||||
if req.Method == "GET" || errors.Count() == 0 { | if req.Method == "GET" || errors.Count() == 0 { | ||||
return | return | ||||
} | } | ||||
@@ -12,6 +12,7 @@ import ( | |||||
"github.com/gogits/gogs/modules/base" | "github.com/gogits/gogs/modules/base" | ||||
"github.com/gogits/gogs/modules/log" | "github.com/gogits/gogs/modules/log" | ||||
"github.com/gogits/gogs/modules/middleware/binding" | |||||
) | ) | ||||
type CreateIssueForm struct { | type CreateIssueForm struct { | ||||
@@ -29,7 +30,7 @@ func (f *CreateIssueForm) Name(field string) string { | |||||
return names[field] | return names[field] | ||||
} | } | ||||
func (f *CreateIssueForm) Validate(errors *base.BindingErrors, req *http.Request, context martini.Context) { | |||||
func (f *CreateIssueForm) Validate(errors *binding.BindingErrors, req *http.Request, context martini.Context) { | |||||
if req.Method == "GET" || errors.Count() == 0 { | if req.Method == "GET" || errors.Count() == 0 { | ||||
return | return | ||||
} | } | ||||
@@ -12,6 +12,7 @@ import ( | |||||
"github.com/gogits/gogs/modules/base" | "github.com/gogits/gogs/modules/base" | ||||
"github.com/gogits/gogs/modules/log" | "github.com/gogits/gogs/modules/log" | ||||
"github.com/gogits/gogs/modules/middleware/binding" | |||||
) | ) | ||||
type NewReleaseForm struct { | type NewReleaseForm struct { | ||||
@@ -30,7 +31,7 @@ func (f *NewReleaseForm) Name(field string) string { | |||||
return names[field] | return names[field] | ||||
} | } | ||||
func (f *NewReleaseForm) Validate(errors *base.BindingErrors, req *http.Request, context martini.Context) { | |||||
func (f *NewReleaseForm) Validate(errors *binding.BindingErrors, req *http.Request, context martini.Context) { | |||||
if req.Method == "GET" || errors.Count() == 0 { | if req.Method == "GET" || errors.Count() == 0 { | ||||
return | return | ||||
} | } | ||||
@@ -12,6 +12,7 @@ import ( | |||||
"github.com/gogits/gogs/modules/base" | "github.com/gogits/gogs/modules/base" | ||||
"github.com/gogits/gogs/modules/log" | "github.com/gogits/gogs/modules/log" | ||||
"github.com/gogits/gogs/modules/middleware/binding" | |||||
) | ) | ||||
type CreateRepoForm struct { | type CreateRepoForm struct { | ||||
@@ -31,7 +32,7 @@ func (f *CreateRepoForm) Name(field string) string { | |||||
return names[field] | return names[field] | ||||
} | } | ||||
func (f *CreateRepoForm) Validate(errors *base.BindingErrors, req *http.Request, context martini.Context) { | |||||
func (f *CreateRepoForm) Validate(errors *binding.BindingErrors, req *http.Request, context martini.Context) { | |||||
if req.Method == "GET" || errors.Count() == 0 { | if req.Method == "GET" || errors.Count() == 0 { | ||||
return | return | ||||
} | } | ||||
@@ -69,7 +70,7 @@ func (f *MigrateRepoForm) Name(field string) string { | |||||
return names[field] | return names[field] | ||||
} | } | ||||
func (f *MigrateRepoForm) Validate(errors *base.BindingErrors, req *http.Request, context martini.Context) { | |||||
func (f *MigrateRepoForm) Validate(errors *binding.BindingErrors, req *http.Request, context martini.Context) { | |||||
if req.Method == "GET" || errors.Count() == 0 { | if req.Method == "GET" || errors.Count() == 0 { | ||||
return | return | ||||
} | } | ||||
@@ -13,6 +13,7 @@ import ( | |||||
"github.com/gogits/gogs/modules/base" | "github.com/gogits/gogs/modules/base" | ||||
"github.com/gogits/gogs/modules/log" | "github.com/gogits/gogs/modules/log" | ||||
"github.com/gogits/gogs/modules/middleware/binding" | |||||
) | ) | ||||
type AddSSHKeyForm struct { | type AddSSHKeyForm struct { | ||||
@@ -28,7 +29,7 @@ func (f *AddSSHKeyForm) Name(field string) string { | |||||
return names[field] | return names[field] | ||||
} | } | ||||
func (f *AddSSHKeyForm) Validate(errors *base.BindingErrors, req *http.Request, context martini.Context) { | |||||
func (f *AddSSHKeyForm) Validate(errors *binding.BindingErrors, req *http.Request, context martini.Context) { | |||||
data := context.Get(reflect.TypeOf(base.TmplData{})).Interface().(base.TmplData) | data := context.Get(reflect.TypeOf(base.TmplData{})).Interface().(base.TmplData) | ||||
AssignForm(f, data) | AssignForm(f, data) | ||||
@@ -15,6 +15,7 @@ import ( | |||||
"github.com/gogits/gogs/models" | "github.com/gogits/gogs/models" | ||||
"github.com/gogits/gogs/modules/base" | "github.com/gogits/gogs/modules/base" | ||||
"github.com/gogits/gogs/modules/log" | "github.com/gogits/gogs/modules/log" | ||||
"github.com/gogits/gogs/modules/middleware/binding" | |||||
) | ) | ||||
// SignedInId returns the id of signed in user. | // SignedInId returns the id of signed in user. | ||||
@@ -93,7 +94,7 @@ func (f *UpdateProfileForm) Name(field string) string { | |||||
return names[field] | return names[field] | ||||
} | } | ||||
func (f *UpdateProfileForm) Validate(errors *base.BindingErrors, req *http.Request, context martini.Context) { | |||||
func (f *UpdateProfileForm) Validate(errors *binding.BindingErrors, req *http.Request, context martini.Context) { | |||||
if req.Method == "GET" || errors.Count() == 0 { | if req.Method == "GET" || errors.Count() == 0 { | ||||
return | return | ||||
} | } | ||||
@@ -126,7 +127,7 @@ func (f *UpdatePasswdForm) Name(field string) string { | |||||
return names[field] | return names[field] | ||||
} | } | ||||
func (f *UpdatePasswdForm) Validate(errors *base.BindingErrors, req *http.Request, context martini.Context) { | |||||
func (f *UpdatePasswdForm) Validate(errors *binding.BindingErrors, req *http.Request, context martini.Context) { | |||||
if req.Method == "GET" || errors.Count() == 0 { | if req.Method == "GET" || errors.Count() == 0 { | ||||
return | return | ||||
} | } | ||||
@@ -9,51 +9,4 @@ type ( | |||||
TmplData map[string]interface{} | TmplData map[string]interface{} | ||||
) | ) | ||||
// __________.__ .___.__ | |||||
// \______ \__| ____ __| _/|__| ____ ____ | |||||
// | | _/ |/ \ / __ | | |/ \ / ___\ | |||||
// | | \ | | \/ /_/ | | | | \/ /_/ > | |||||
// |______ /__|___| /\____ | |__|___| /\___ / | |||||
// \/ \/ \/ \//_____/ | |||||
// Errors represents the contract of the response body when the | |||||
// binding step fails before getting to the application. | |||||
type BindingErrors struct { | |||||
Overall map[string]string `json:"overall"` | |||||
Fields map[string]string `json:"fields"` | |||||
} | |||||
// Total errors is the sum of errors with the request overall | |||||
// and errors on individual fields. | |||||
func (err BindingErrors) Count() int { | |||||
return len(err.Overall) + len(err.Fields) | |||||
} | |||||
func (this *BindingErrors) Combine(other BindingErrors) { | |||||
for key, val := range other.Fields { | |||||
if _, exists := this.Fields[key]; !exists { | |||||
this.Fields[key] = val | |||||
} | |||||
} | |||||
for key, val := range other.Overall { | |||||
if _, exists := this.Overall[key]; !exists { | |||||
this.Overall[key] = val | |||||
} | |||||
} | |||||
} | |||||
const ( | |||||
BindingRequireError string = "Required" | |||||
BindingAlphaDashError string = "AlphaDash" | |||||
BindingAlphaDashDotError string = "AlphaDashDot" | |||||
BindingMinSizeError string = "MinSize" | |||||
BindingMaxSizeError string = "MaxSize" | |||||
BindingEmailError string = "Email" | |||||
BindingUrlError string = "Url" | |||||
BindingDeserializationError string = "DeserializationError" | |||||
BindingIntegerTypeError string = "IntegerTypeError" | |||||
BindingBooleanTypeError string = "BooleanTypeError" | |||||
BindingFloatTypeError string = "FloatTypeError" | |||||
) | |||||
var GoGetMetas = make(map[string]bool) | var GoGetMetas = make(map[string]bool) |
@@ -3,7 +3,7 @@ | |||||
// Use of this source code is governed by a MIT-style | // Use of this source code is governed by a MIT-style | ||||
// license that can be found in the LICENSE file. | // license that can be found in the LICENSE file. | ||||
package middleware | |||||
package binding | |||||
import ( | import ( | ||||
"encoding/json" | "encoding/json" | ||||
@@ -17,8 +17,6 @@ import ( | |||||
"unicode/utf8" | "unicode/utf8" | ||||
"github.com/go-martini/martini" | "github.com/go-martini/martini" | ||||
"github.com/gogits/gogs/modules/base" | |||||
) | ) | ||||
/* | /* | ||||
@@ -103,7 +101,7 @@ func Form(formStruct interface{}, ifacePtr ...interface{}) martini.Handler { | |||||
// Because an empty request body or url can also mean absence of all needed values, | // Because an empty request body or url can also mean absence of all needed values, | ||||
// it is not in all cases a bad request, so let's return 422. | // it is not in all cases a bad request, so let's return 422. | ||||
if parseErr != nil { | if parseErr != nil { | ||||
errors.Overall[base.BindingDeserializationError] = parseErr.Error() | |||||
errors.Overall[BindingDeserializationError] = parseErr.Error() | |||||
} | } | ||||
mapForm(formStruct, req.Form, errors) | mapForm(formStruct, req.Form, errors) | ||||
@@ -123,12 +121,12 @@ func MultipartForm(formStruct interface{}, ifacePtr ...interface{}) martini.Hand | |||||
// https://code.google.com/p/go/issues/detail?id=6334 | // https://code.google.com/p/go/issues/detail?id=6334 | ||||
multipartReader, err := req.MultipartReader() | multipartReader, err := req.MultipartReader() | ||||
if err != nil { | if err != nil { | ||||
errors.Overall[base.BindingDeserializationError] = err.Error() | |||||
errors.Overall[BindingDeserializationError] = err.Error() | |||||
} else { | } else { | ||||
form, parseErr := multipartReader.ReadForm(MaxMemory) | form, parseErr := multipartReader.ReadForm(MaxMemory) | ||||
if parseErr != nil { | if parseErr != nil { | ||||
errors.Overall[base.BindingDeserializationError] = parseErr.Error() | |||||
errors.Overall[BindingDeserializationError] = parseErr.Error() | |||||
} | } | ||||
req.MultipartForm = form | req.MultipartForm = form | ||||
@@ -156,7 +154,7 @@ func Json(jsonStruct interface{}, ifacePtr ...interface{}) martini.Handler { | |||||
} | } | ||||
if err := json.NewDecoder(req.Body).Decode(jsonStruct.Interface()); err != nil && err != io.EOF { | if err := json.NewDecoder(req.Body).Decode(jsonStruct.Interface()); err != nil && err != io.EOF { | ||||
errors.Overall[base.BindingDeserializationError] = err.Error() | |||||
errors.Overall[BindingDeserializationError] = err.Error() | |||||
} | } | ||||
validateAndMap(jsonStruct, context, errors, ifacePtr...) | validateAndMap(jsonStruct, context, errors, ifacePtr...) | ||||
@@ -186,7 +184,7 @@ var ( | |||||
urlPattern = regexp.MustCompile(`(http|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?`) | urlPattern = regexp.MustCompile(`(http|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?`) | ||||
) | ) | ||||
func validateStruct(errors *base.BindingErrors, obj interface{}) { | |||||
func validateStruct(errors *BindingErrors, obj interface{}) { | |||||
typ := reflect.TypeOf(obj) | typ := reflect.TypeOf(obj) | ||||
val := reflect.ValueOf(obj) | val := reflect.ValueOf(obj) | ||||
@@ -220,17 +218,17 @@ func validateStruct(errors *base.BindingErrors, obj interface{}) { | |||||
switch { | switch { | ||||
case rule == "Required": | case rule == "Required": | ||||
if reflect.DeepEqual(zero, fieldValue) { | if reflect.DeepEqual(zero, fieldValue) { | ||||
errors.Fields[field.Name] = base.BindingRequireError | |||||
errors.Fields[field.Name] = BindingRequireError | |||||
break | break | ||||
} | } | ||||
case rule == "AlphaDash": | case rule == "AlphaDash": | ||||
if alphaDashPattern.MatchString(fmt.Sprintf("%v", fieldValue)) { | if alphaDashPattern.MatchString(fmt.Sprintf("%v", fieldValue)) { | ||||
errors.Fields[field.Name] = base.BindingAlphaDashError | |||||
errors.Fields[field.Name] = BindingAlphaDashError | |||||
break | break | ||||
} | } | ||||
case rule == "AlphaDashDot": | case rule == "AlphaDashDot": | ||||
if alphaDashDotPattern.MatchString(fmt.Sprintf("%v", fieldValue)) { | if alphaDashDotPattern.MatchString(fmt.Sprintf("%v", fieldValue)) { | ||||
errors.Fields[field.Name] = base.BindingAlphaDashDotError | |||||
errors.Fields[field.Name] = BindingAlphaDashDotError | |||||
break | break | ||||
} | } | ||||
case strings.HasPrefix(rule, "MinSize("): | case strings.HasPrefix(rule, "MinSize("): | ||||
@@ -240,12 +238,12 @@ func validateStruct(errors *base.BindingErrors, obj interface{}) { | |||||
break | break | ||||
} | } | ||||
if str, ok := fieldValue.(string); ok && utf8.RuneCountInString(str) < min { | if str, ok := fieldValue.(string); ok && utf8.RuneCountInString(str) < min { | ||||
errors.Fields[field.Name] = base.BindingMinSizeError | |||||
errors.Fields[field.Name] = BindingMinSizeError | |||||
break | break | ||||
} | } | ||||
v := reflect.ValueOf(fieldValue) | v := reflect.ValueOf(fieldValue) | ||||
if v.Kind() == reflect.Slice && v.Len() < min { | if v.Kind() == reflect.Slice && v.Len() < min { | ||||
errors.Fields[field.Name] = base.BindingMinSizeError | |||||
errors.Fields[field.Name] = BindingMinSizeError | |||||
break | break | ||||
} | } | ||||
case strings.HasPrefix(rule, "MaxSize("): | case strings.HasPrefix(rule, "MaxSize("): | ||||
@@ -255,22 +253,22 @@ func validateStruct(errors *base.BindingErrors, obj interface{}) { | |||||
break | break | ||||
} | } | ||||
if str, ok := fieldValue.(string); ok && utf8.RuneCountInString(str) > max { | if str, ok := fieldValue.(string); ok && utf8.RuneCountInString(str) > max { | ||||
errors.Fields[field.Name] = base.BindingMaxSizeError | |||||
errors.Fields[field.Name] = BindingMaxSizeError | |||||
break | break | ||||
} | } | ||||
v := reflect.ValueOf(fieldValue) | v := reflect.ValueOf(fieldValue) | ||||
if v.Kind() == reflect.Slice && v.Len() > max { | if v.Kind() == reflect.Slice && v.Len() > max { | ||||
errors.Fields[field.Name] = base.BindingMinSizeError | |||||
errors.Fields[field.Name] = BindingMinSizeError | |||||
break | break | ||||
} | } | ||||
case rule == "Email": | case rule == "Email": | ||||
if !emailPattern.MatchString(fmt.Sprintf("%v", fieldValue)) { | if !emailPattern.MatchString(fmt.Sprintf("%v", fieldValue)) { | ||||
errors.Fields[field.Name] = base.BindingEmailError | |||||
errors.Fields[field.Name] = BindingEmailError | |||||
break | break | ||||
} | } | ||||
case rule == "Url": | case rule == "Url": | ||||
if !urlPattern.MatchString(fmt.Sprintf("%v", fieldValue)) { | if !urlPattern.MatchString(fmt.Sprintf("%v", fieldValue)) { | ||||
errors.Fields[field.Name] = base.BindingUrlError | |||||
errors.Fields[field.Name] = BindingUrlError | |||||
break | break | ||||
} | } | ||||
} | } | ||||
@@ -278,7 +276,7 @@ func validateStruct(errors *base.BindingErrors, obj interface{}) { | |||||
} | } | ||||
} | } | ||||
func mapForm(formStruct reflect.Value, form map[string][]string, errors *base.BindingErrors) { | |||||
func mapForm(formStruct reflect.Value, form map[string][]string, errors *BindingErrors) { | |||||
typ := formStruct.Elem().Type() | typ := formStruct.Elem().Type() | ||||
for i := 0; i < typ.NumField(); i++ { | for i := 0; i < typ.NumField(); i++ { | ||||
@@ -319,10 +317,10 @@ func mapForm(formStruct reflect.Value, form map[string][]string, errors *base.Bi | |||||
// This is a "default" handler, of sorts, and you are | // This is a "default" handler, of sorts, and you are | ||||
// welcome to use your own instead. The Bind middleware | // welcome to use your own instead. The Bind middleware | ||||
// invokes this automatically for convenience. | // invokes this automatically for convenience. | ||||
func ErrorHandler(errs base.BindingErrors, resp http.ResponseWriter) { | |||||
func ErrorHandler(errs BindingErrors, resp http.ResponseWriter) { | |||||
if errs.Count() > 0 { | if errs.Count() > 0 { | ||||
resp.Header().Set("Content-Type", "application/json; charset=utf-8") | resp.Header().Set("Content-Type", "application/json; charset=utf-8") | ||||
if _, ok := errs.Overall[base.BindingDeserializationError]; ok { | |||||
if _, ok := errs.Overall[BindingDeserializationError]; ok { | |||||
resp.WriteHeader(http.StatusBadRequest) | resp.WriteHeader(http.StatusBadRequest) | ||||
} else { | } else { | ||||
resp.WriteHeader(422) | resp.WriteHeader(422) | ||||
@@ -337,7 +335,7 @@ func ErrorHandler(errs base.BindingErrors, resp http.ResponseWriter) { | |||||
// matching value from the request (via Form middleware) in the | // matching value from the request (via Form middleware) in the | ||||
// same type, so that not all deserialized values have to be strings. | // same type, so that not all deserialized values have to be strings. | ||||
// Supported types are string, int, float, and bool. | // Supported types are string, int, float, and bool. | ||||
func setWithProperType(valueKind reflect.Kind, val string, structField reflect.Value, nameInTag string, errors *base.BindingErrors) { | |||||
func setWithProperType(valueKind reflect.Kind, val string, structField reflect.Value, nameInTag string, errors *BindingErrors) { | |||||
switch valueKind { | switch valueKind { | ||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: | ||||
if val == "" { | if val == "" { | ||||
@@ -345,7 +343,7 @@ func setWithProperType(valueKind reflect.Kind, val string, structField reflect.V | |||||
} | } | ||||
intVal, err := strconv.ParseInt(val, 10, 64) | intVal, err := strconv.ParseInt(val, 10, 64) | ||||
if err != nil { | if err != nil { | ||||
errors.Fields[nameInTag] = base.BindingIntegerTypeError | |||||
errors.Fields[nameInTag] = BindingIntegerTypeError | |||||
} else { | } else { | ||||
structField.SetInt(intVal) | structField.SetInt(intVal) | ||||
} | } | ||||
@@ -355,7 +353,7 @@ func setWithProperType(valueKind reflect.Kind, val string, structField reflect.V | |||||
} | } | ||||
uintVal, err := strconv.ParseUint(val, 10, 64) | uintVal, err := strconv.ParseUint(val, 10, 64) | ||||
if err != nil { | if err != nil { | ||||
errors.Fields[nameInTag] = base.BindingIntegerTypeError | |||||
errors.Fields[nameInTag] = BindingIntegerTypeError | |||||
} else { | } else { | ||||
structField.SetUint(uintVal) | structField.SetUint(uintVal) | ||||
} | } | ||||
@@ -367,7 +365,7 @@ func setWithProperType(valueKind reflect.Kind, val string, structField reflect.V | |||||
} | } | ||||
floatVal, err := strconv.ParseFloat(val, 32) | floatVal, err := strconv.ParseFloat(val, 32) | ||||
if err != nil { | if err != nil { | ||||
errors.Fields[nameInTag] = base.BindingFloatTypeError | |||||
errors.Fields[nameInTag] = BindingFloatTypeError | |||||
} else { | } else { | ||||
structField.SetFloat(floatVal) | structField.SetFloat(floatVal) | ||||
} | } | ||||
@@ -377,7 +375,7 @@ func setWithProperType(valueKind reflect.Kind, val string, structField reflect.V | |||||
} | } | ||||
floatVal, err := strconv.ParseFloat(val, 64) | floatVal, err := strconv.ParseFloat(val, 64) | ||||
if err != nil { | if err != nil { | ||||
errors.Fields[nameInTag] = base.BindingFloatTypeError | |||||
errors.Fields[nameInTag] = BindingFloatTypeError | |||||
} else { | } else { | ||||
structField.SetFloat(floatVal) | structField.SetFloat(floatVal) | ||||
} | } | ||||
@@ -398,7 +396,7 @@ func ensureNotPointer(obj interface{}) { | |||||
// Performs validation and combines errors from validation | // Performs validation and combines errors from validation | ||||
// with errors from deserialization, then maps both the | // with errors from deserialization, then maps both the | ||||
// resulting struct and the errors to the context. | // resulting struct and the errors to the context. | ||||
func validateAndMap(obj reflect.Value, context martini.Context, errors *base.BindingErrors, ifacePtr ...interface{}) { | |||||
func validateAndMap(obj reflect.Value, context martini.Context, errors *BindingErrors, ifacePtr ...interface{}) { | |||||
context.Invoke(Validate(obj.Interface())) | context.Invoke(Validate(obj.Interface())) | ||||
errors.Combine(getErrors(context)) | errors.Combine(getErrors(context)) | ||||
context.Map(*errors) | context.Map(*errors) | ||||
@@ -408,12 +406,12 @@ func validateAndMap(obj reflect.Value, context martini.Context, errors *base.Bin | |||||
} | } | ||||
} | } | ||||
func newErrors() *base.BindingErrors { | |||||
return &base.BindingErrors{make(map[string]string), make(map[string]string)} | |||||
func newErrors() *BindingErrors { | |||||
return &BindingErrors{make(map[string]string), make(map[string]string)} | |||||
} | } | ||||
func getErrors(context martini.Context) base.BindingErrors { | |||||
return context.Get(reflect.TypeOf(base.BindingErrors{})).Interface().(base.BindingErrors) | |||||
func getErrors(context martini.Context) BindingErrors { | |||||
return context.Get(reflect.TypeOf(BindingErrors{})).Interface().(BindingErrors) | |||||
} | } | ||||
type ( | type ( | ||||
@@ -421,7 +419,7 @@ type ( | |||||
// validation before the request even gets to your application. | // validation before the request even gets to your application. | ||||
// The Validate method will be executed during the validation phase. | // The Validate method will be executed during the validation phase. | ||||
Validator interface { | Validator interface { | ||||
Validate(*base.BindingErrors, *http.Request, martini.Context) | |||||
Validate(*BindingErrors, *http.Request, martini.Context) | |||||
} | } | ||||
) | ) | ||||
@@ -430,3 +428,43 @@ var ( | |||||
// Set this to whatever value you prefer; default is 10 MB. | // Set this to whatever value you prefer; default is 10 MB. | ||||
MaxMemory = int64(1024 * 1024 * 10) | MaxMemory = int64(1024 * 1024 * 10) | ||||
) | ) | ||||
// Errors represents the contract of the response body when the | |||||
// binding step fails before getting to the application. | |||||
type BindingErrors struct { | |||||
Overall map[string]string `json:"overall"` | |||||
Fields map[string]string `json:"fields"` | |||||
} | |||||
// Total errors is the sum of errors with the request overall | |||||
// and errors on individual fields. | |||||
func (err BindingErrors) Count() int { | |||||
return len(err.Overall) + len(err.Fields) | |||||
} | |||||
func (this *BindingErrors) Combine(other BindingErrors) { | |||||
for key, val := range other.Fields { | |||||
if _, exists := this.Fields[key]; !exists { | |||||
this.Fields[key] = val | |||||
} | |||||
} | |||||
for key, val := range other.Overall { | |||||
if _, exists := this.Overall[key]; !exists { | |||||
this.Overall[key] = val | |||||
} | |||||
} | |||||
} | |||||
const ( | |||||
BindingRequireError string = "Required" | |||||
BindingAlphaDashError string = "AlphaDash" | |||||
BindingAlphaDashDotError string = "AlphaDashDot" | |||||
BindingMinSizeError string = "MinSize" | |||||
BindingMaxSizeError string = "MaxSize" | |||||
BindingEmailError string = "Email" | |||||
BindingUrlError string = "Url" | |||||
BindingDeserializationError string = "DeserializationError" | |||||
BindingIntegerTypeError string = "IntegerTypeError" | |||||
BindingBooleanTypeError string = "BooleanTypeError" | |||||
BindingFloatTypeError string = "FloatTypeError" | |||||
) |
@@ -3,7 +3,7 @@ | |||||
// Use of this source code is governed by a MIT-style | // Use of this source code is governed by a MIT-style | ||||
// license that can be found in the LICENSE file. | // license that can be found in the LICENSE file. | ||||
package middleware | |||||
package binding | |||||
import ( | import ( | ||||
"bytes" | "bytes" |
@@ -0,0 +1,6 @@ | |||||
[host] | |||||
LISTEN_ADDR = 127.0.0.1:5000 | |||||
REMOTE_ADDR = 127.0.0.1:5000 | |||||
[rules] | |||||
IGNORES = .git|.DS_Store|*.tmp|data |