From cd7338dbe01fcbb6b6f10fdc47c25c9da9068dba Mon Sep 17 00:00:00 2001
From: Fenny <fenny@protonmail.com>
Date: Thu, 13 Feb 2020 06:48:14 +0100
Subject: [PATCH] Add BodyParser v1.6.0

---
 LICENSE => .github/LICENSE |  0
 application.go             |  1 +
 go.mod                     |  1 +
 go.sum                     |  2 ++
 request.go                 | 33 +++++++++++++++++++++++++++------
 utils.go                   | 25 +++++++++++++++++++++----
 6 files changed, 52 insertions(+), 10 deletions(-)
 rename LICENSE => .github/LICENSE (100%)

diff --git a/LICENSE b/.github/LICENSE
similarity index 100%
rename from LICENSE
rename to .github/LICENSE
diff --git a/application.go b/application.go
index 87f35037..7aec5648 100644
--- a/application.go
+++ b/application.go
@@ -93,6 +93,7 @@ type engine struct {
 // New https://fiber.wiki/application#new
 func New() *Application {
 	flag.Parse()
+	schemaDecoder.SetAliasTag("form")
 	return &Application{
 		Server:     "",
 		httpServer: nil,
diff --git a/go.mod b/go.mod
index 89aa1a4d..01c7106d 100644
--- a/go.mod
+++ b/go.mod
@@ -3,6 +3,7 @@ module github.com/gofiber/fiber
 go 1.11
 
 require (
+	github.com/gorilla/schema v1.1.0
 	github.com/json-iterator/go v1.1.9
 	github.com/valyala/fasthttp v1.9.0
 )
diff --git a/go.sum b/go.sum
index 4f5f5e7a..db5566ca 100644
--- a/go.sum
+++ b/go.sum
@@ -1,6 +1,8 @@
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+github.com/gorilla/schema v1.1.0 h1:CamqUDOFUBqzrvxuz2vEwo8+SUdwsluFh7IlzJh30LY=
+github.com/gorilla/schema v1.1.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU=
 github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
 github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
 github.com/klauspost/compress v1.8.2 h1:Bx0qjetmNjdFXASH02NSAREKpiaDwkO1DRZ3dV2KCcs=
diff --git a/request.go b/request.go
index 6e123e75..23d9b902 100644
--- a/request.go
+++ b/request.go
@@ -13,6 +13,7 @@ import (
 	"fmt"
 	"mime"
 	"mime/multipart"
+	"net/url"
 	"strings"
 
 	jsoniter "github.com/json-iterator/go"
@@ -198,13 +199,33 @@ func (ctx *Ctx) Body(args ...interface{}) string {
 
 // BodyParser : https://fiber.wiki/context#bodyparser
 func (ctx *Ctx) BodyParser(v interface{}) error {
-	cType := getString(ctx.Fasthttp.Request.Header.ContentType())
-	if cType == contentTypeJSON {
-		return jsoniter.Unmarshal(ctx.Fasthttp.Request.Body(), &v)
-	} else if cType == contentTypeXML {
-		return xml.Unmarshal(ctx.Fasthttp.Request.Body(), &v)
+	ctype := getString(ctx.Fasthttp.Request.Header.ContentType())
+	// application/json
+	if strings.HasPrefix(ctype, mimeApplicationJSON) {
+		return jsoniter.Unmarshal(ctx.Fasthttp.Request.Body(), v)
 	}
-	return fmt.Errorf("cannot parse content-type: %v", cType)
+	// application/xml text/xml
+	if strings.HasPrefix(ctype, mimeApplicationXML) || strings.HasPrefix(ctype, mimeTextXML) {
+		return xml.Unmarshal(ctx.Fasthttp.Request.Body(), v)
+	}
+	// application/x-www-form-urlencoded
+	if strings.HasPrefix(ctype, mimeApplicationForm) {
+		data, err := url.ParseQuery(getString(ctx.Fasthttp.PostBody()))
+		if err != nil {
+			return err
+		}
+		return schemaDecoder.Decode(v, data)
+	}
+	// multipart/form-data
+	if strings.HasPrefix(ctype, mimeMultipartForm) {
+		data, err := ctx.Fasthttp.MultipartForm()
+		if err != nil {
+			return err
+		}
+		return schemaDecoder.Decode(v, data.Value)
+
+	}
+	return fmt.Errorf("cannot parse content-type: %v", ctype)
 }
 
 // Cookies : https://fiber.wiki/context#cookies
diff --git a/utils.go b/utils.go
index 2296740f..3ee2a41e 100644
--- a/utils.go
+++ b/utils.go
@@ -18,8 +18,12 @@ import (
 	"strings"
 	"time"
 	"unsafe"
+
+	"github.com/gorilla/schema"
 )
 
+var schemaDecoder = schema.NewDecoder()
+
 func getParams(path string) (params []string) {
 	segments := strings.Split(path, "/")
 	replacer := strings.NewReplacer(":", "", "?", "")
@@ -209,10 +213,23 @@ var statusMessages = map[int]string{
 }
 
 const (
-	contentTypeJSON        = "application/json"
-	contentTypeJs          = "application/javascript"
-	contentTypeXML         = "application/xml"
-	contentTypeOctetStream = "application/octet-stream"
+	contentTypeJSON              = "application/json"
+	contentTypeJs                = "application/javascript"
+	contentTypeXML               = "application/xml"
+	contentTypeOctetStream       = "application/octet-stream"
+	contentTypeFormURLEncoded    = "application/x-www-form-urlencoded"
+	contentTypeMultipartFormData = "multipart/form-data"
+)
+
+const (
+	mimeApplicationJSON           = "application/json"
+	mimeApplicationJavascrippt    = "application/javascript"
+	mimeApplicationXML            = "application/xml"
+	mimeTextXML                   = "text/xml"
+	mimeApplicationOctetStream    = "application/octet-stream"
+	mimeApplicationFormURLEncoded = "application/x-www-form-urlencoded"
+	mimeApplicationForm           = "application/x-www-form-urlencoded"
+	mimeMultipartForm             = "multipart/form-data"
 )
 
 // https://github.com/nginx/nginx/blob/master/conf/mime.types