Browse Source

initial import

Bozhin Zafirov 8 years ago
parent
commit
5537c7ad54
6 changed files with 127 additions and 1 deletions
  1. 1 1
      LICENSE
  2. 2 0
      README.md
  3. 14 0
      constructors.go
  4. 12 0
      errors.go
  5. 43 0
      forms.go
  6. 55 0
      validate.go

+ 1 - 1
LICENSE

@@ -1,6 +1,6 @@
 BSD 2-Clause License
 BSD 2-Clause License
 
 
-Copyright (c) 2017, 
+Copyright (c) 2017, Bozhin Zafirov.
 All rights reserved.
 All rights reserved.
 
 
 Redistribution and use in source and binary forms, with or without
 Redistribution and use in source and binary forms, with or without

+ 2 - 0
README.md

@@ -0,0 +1,2 @@
+# forms
+A golang library for HTTP form parsing.

+ 14 - 0
constructors.go

@@ -0,0 +1,14 @@
+package form
+
+// Generate new CharField field with type text
+func NewCharField(Name, Label string, Value *string, Validators *ValidatorsList) FormField {
+	if Value == nil {
+		return FormField{Name, "text", Label, "", nil, Validators}
+	}
+	return FormField{Name, "text", Label, *Value, nil, Validators}
+}
+
+// Generate new CharField field with type password
+func NewPasswordField(Name, Label string, Validators *ValidatorsList) FormField {
+	return FormField{Name, "password", Label, "", nil, Validators}
+}

+ 12 - 0
errors.go

@@ -0,0 +1,12 @@
+package form
+
+import (
+	"errors"
+)
+
+// pre-defined form errors
+var (
+	EInvalidMethod     = errors.New("Invalid method")
+	EInvalidIntValue   = errors.New("Field value must be integer.")
+	EInvalidFloatValue = errors.New("Field value must be float.")
+)

+ 43 - 0
forms.go

@@ -0,0 +1,43 @@
+package form
+
+import (
+	"context"
+	"strconv"
+)
+
+// ValidatorFunc defines a function for FormField data validation
+type ValidatorFunc func(FormField, context.Context) error
+
+// ValidatorsList defines a list of ValidatorFunc
+type ValidatorsList []ValidatorFunc
+
+// A general purpose form  field struct
+type FormField struct {
+	Name       string
+	Type       string
+	Label      string
+	Value      string
+	Error      error
+	Validators *ValidatorsList
+}
+
+// GetString returns FormField.Value as string
+func (f FormField) GetString() string {
+	return f.Value
+}
+
+// GetInt returns FormField.Value as int
+func (f FormField) GetInt() (int, error) {
+	return strconv.Atoi(f.Value)
+}
+
+// GetFloat returns FormField.Value as float
+func (f FormField) GetFloat() (float64, error) {
+	return strconv.ParseFloat(f.Value, 64)
+}
+
+// GetBool returns boolean value for checkbox fields
+func (f FormField) GetBool() (bool, error) {
+	// placeholder
+	return false, nil
+}

+ 55 - 0
validate.go

@@ -0,0 +1,55 @@
+package form
+
+import (
+	"net/http"
+	"reflect"
+)
+
+// ValidateForm parses a POST form into pre-defined struct
+func ValidateForm(r *http.Request, p interface{}) error {
+	// only support POST methods
+	if r.Method != "POST" {
+		return EInvalidMethod
+	}
+
+	// parse POST data into form
+	if err := r.ParseForm(); err != nil {
+		return err
+	}
+
+	var FormError error
+	// Parse form data into interface
+	formStruct := reflect.ValueOf(p).Elem()
+
+	// populate FormField value
+	for HttpFormField, HttpFormValue := range r.Form {
+		for n := 0; n < formStruct.NumField(); n++ {
+			fieldt := formStruct.Type().Field(n)
+			// only proceed if field name or tag matches that of form field
+			if fieldt.Name != HttpFormField && fieldt.Tag.Get("form") != HttpFormField {
+				continue
+			}
+			// get n-th field
+			fieldn := formStruct.Field(n)
+			// set form data to field
+			// equivalent of form.Value = HttpFormValue[0]
+			fieldn.Field(3).Set(reflect.ValueOf(HttpFormValue[0]))
+		}
+	}
+
+	// run form field validators
+	for n := 0; n < formStruct.NumField(); n++ {
+		fieldn := formStruct.Field(n)
+		field := fieldn.Interface().(FormField)
+		for _, validator := range *field.Validators {
+			if err := validator(field, r.Context()); err != nil {
+				fieldn.Field(4).Set(reflect.ValueOf(err))
+				FormError = err
+				break
+			}
+		}
+	}
+
+	// return status
+	return FormError
+}