monoculum / formam Goto Github PK
View Code? Open in Web Editor NEWa package for decode form's values into struct in Go
License: Apache License 2.0
a package for decode form's values into struct in Go
License: Apache License 2.0
For this example, I'm unable to use a multiselect. I have not tried any other element such as checkbox or file. This is a huge show-stopper for me.
<select multiple="multiple" name="mydata[]">
Or
<select multiple="multiple" name="mydata">
Struct:
type MyDataStruct struct {
Data []string `formam:"mydata"`
}
The way to access a map should be by [] like array.
The current way not give possibility to name a key as "go.lang" or "2.2"...
Hi! Thanks for your great library.
I have encountered an issue with decoding fieldsets:
<fieldset>
<legend>Select labels</legend>
<input type="checkbox" name="labels" value="label1">label1
<input type="checkbox" name="labels" value="label2">label2
<input type="checkbox" name="labels" value="label3">label3
<input type="checkbox" name="labels" value="label4">label4
</fieldset>
When selecting multiple checkboxes, the form data is sent appropriately as expected:
INFO[2020-09-20T08:44:35+02:00] /submit/ content_type=application/x-www-form-urlencoded db=0s duration=1.374036ms form="{\"authenticity_token\":[\"MONVHBgDotwySs80XP5vV901VtmULCrk73Sxe5oYSN+hUpiIPKnGdO8DBRUlizJBmbkganMr4C6QfPNJsHnncg==\"],\"description\":[\"test\"],\"labels\":[\"label1\",\"label2\",\"label3\",\"label4\"], ...
But then when decoded into a []string
only the first value is unmarshalled, and the []string
results in:
BOUND ENTRY: &models.Entry{Title:"Test", Description:"Test", Labels:slices.String{"tileable"}}
For extra info, I don't think it matters but just in case, I'm using gobuffalo's Bind() function and the type I unmarshal into is not directly a []string
but a wrapper around it, a slices.String
from gobuffalo's pop/slices package.
Code:
var s struct {
MapStringString map[string]string
MapStringPtrStruct map[string]struct {
ID string
}
MapStringMapStringString map[string]map[string]string
}
vals := url.Values{
"MapStringString[a[b][c]d]": []string{"MapStringString[a[b][c]d]"},
"MapStringString[name.with.dots]": []string{"MapStringString[name.with.dots]"},
"MapStringPtrStruct[k2]ID": []string{"MapStringPtrStruct[k2]ID"},
"MapStringMapStringString[a[b[c]d]]q]w": []string{"MapStringMapStringString[a[b[c]d]]q]w"},
}
dec := formam.NewDecoder(nil)
Expected: no errors, correct parsing with brakets in key's names
Actual: uninformative unrelated error: error when decode formam: has an array index but it is a string
First of all, I hope to make myself understood.
Sometimes when I try to bind the form, the values are incomplete, sometimes I just receive 1 user, other times I receive 2 users, but with empty fields like:
USERS-----------------------> 2
User 1 FN-----------------------> FirstName1
User 1 LN-----------------------> LastName1
User 1 EA-----------------------> [email protected]
User 2 FN-----------------------> FirstName2
User 2 LN-----------------------> LastName2
User 2 EA----------------------->
I'm not really sure why this is happening. Thanks in advance.
I have this model:
type User struct {
FirstName string `form:"FirstName"`
LastName string `form:"LastName"`
Email string `form:"Email"`
}
type Users []User
My HTML Form (or something like that):
<form method="POST">
<input type="text" name="User[0].FirstName" value="FirstName1">
<input type="text" name="User[0].LastName" value="LastName1">
<input type="text" name="User[0].Email" value="[email protected]">
<input type="text" name="User[1].FirstName" value="FirstName2">
<input type="text" name="User[1].LastName" value="LastName2">
<input type="text" name="User[1].Email" value="[email protected]">
<input type="submit">
</form>
My Handler
func MyHandler(w http.ResponseWriter, req *http.Request) error {
decoder = formam.NewDecoder(&formam.DecoderOptions{
TagName: "form",
IgnoreUnknownKeys: true,
})
if err := req.ParseForm(); err != nil {
return err
}
u := &models.Users{}
if err := decoder.Decode(req.Form, u); err != nil {
return err
}
}
If I write an html form with a checkbox that has no explicit value
attribute then when the checkbox is checked by the user the browser will send the string "on" in the form data. However, the string "on" is not recognized by strconv.ParseBool
and I get a parse error. It would be nice if this library handled this case.
I realize that I can work around this by setting value="true"
in my HTML form but I was wondering whether you would consider making that unnecessary by processing the string "on" as true when parsing booleans.
Could you please create a new minor release? The PR #17 seems important and this bug caused me some troubles.
Hi @monoculum I'm considering incorporating this library into gobuffalo/buffalo#335, but before I do that, I have to ask if this project is still maintained. If it is not, are you OK if I fork it and maintain a fork for the Buffalo project?
The code to expand a slice based on an array index ends up calling reflect.MakeSlice
with a user-controlled length value:
https://github.com/monoculum/formam/blob/master/formam.go#L570
This could be abused by a malicious user to force large memory allocations in a Go web application.
A workaround could be to provide a default length limit (16k or similar) in the DecoderOptions and allow the user to override this.
How to use not indexed arrays?
From your example, when I trying change:
<input type="text" name="Founders[0]" value="Masaru Ibuka"/>
<input type="text" name="Founders[1]" value="Akio Morita"/>
to
<input type="text" name="Founders[]" value="Masaru Ibuka"/>
<input type="text" name="Founders[]" value="Akio Morita"/>
I got:
runtime error: slice bounds out of range
Right now this library silently overflows integers. For example, filling in 300
for an uint8
results in 44
, since the maximum size is 256
and 300 - 256 = 44
.
Personally I think this behaviour is rather surprising, and would expect an error from this library.
Thoughts?
I think it's a good time? I can do it myself, but just wanted to check in ๐
Changelog:
- Only Go 1.10 and newer is supported (23)
- Add error codes to the returned errors (#23, 27)
- Fix intermittent failures when scanning an array of structs (#28)
- Error.Path is now exported (#29)
s := struct {
Array [2]string
}{}
vals := url.Values{
"Array[2]": []string{"10"},
}
dec := formam.NewDecoder(nil)
err := dec.Decode(vals, &s)
panics with array index is out of bound
Just updated (removed repo and did go get -u on this repo) and im getting a panic on reflection
18:6:37 app | 2016/05/15 18:06:37 panic: reflect: slice index out of range
Stack trace:
goroutine 42 [running]:
runtime/debug.Stack(0x0, 0x0, 0x0)
/home/david/.gvm/gos/go1.6/src/runtime/debug/stack.go:24 +0x80
gitlab.com/dvwallin/1spot/vendor/github.com/valyala/fasthttp.(*workerPool).workerFunc.func1(0xc82018c680, 0xc820199ed0)
/home/david/.gvm/pkgsets/go1.6/global/src/gitlab.com/dvwallin/1spot/vendor/github.com/valyala/fasthttp/workerpool.go:207 +0x53
panic(0x99b7c0, 0xc820075c10)
/home/david/.gvm/gos/go1.6/src/runtime/panic.go:426 +0x4e9
reflect.Value.Index(0x9877a0, 0xc8200a41d0, 0x197, 0xffffffffffffffff, 0x0, 0x0, 0x0)
/home/david/.gvm/gos/go1.6/src/reflect/value.go:854 +0x151
gitlab.com/dvwallin/1spot/vendor/github.com/monoculum/formam.(*decoder).decode(0xc820199250, 0x0, 0x0)
/home/david/.gvm/pkgsets/go1.6/global/src/gitlab.com/dvwallin/1spot/vendor/github.com/monoculum/formam/formam.go:209 +0x10ad
gitlab.com/dvwallin/1spot/vendor/github.com/monoculum/formam.(*decoder).end(0xc820199250, 0x0, 0x0)
/home/david/.gvm/pkgsets/go1.6/global/src/gitlab.com/dvwallin/1spot/vendor/github.com/monoculum/formam/formam.go:189 +0xb5
gitlab.com/dvwallin/1spot/vendor/github.com/monoculum/formam.(*decoder).begin(0xc820199250, 0x0, 0x0)
/home/david/.gvm/pkgsets/go1.6/global/src/gitlab.com/dvwallin/1spot/vendor/github.com/monoculum/formam/formam.go:132 +0x562
gitlab.com/dvwallin/1spot/vendor/github.com/monoculum/formam.Decode(0xc820199350, 0x970ee0, 0xc8200a41b0, 0x0, 0x0)
/home/david/.gvm/pkgsets/go1.6/global/src/gitlab.com/dvwallin/1spot/vendor/github.com/monoculum/formam/formam.go:68 +0x3bf
gitlab.com/dvwallin/1spot/vendor/github.com/kataras/iris.(*Context).ReadForm(0xc820098780, 0x970ee0, 0xc8200a41b0, 0x0, 0x0)
/home/david/.gvm/pkgsets/go1.6/global/src/gitlab.com/dvwallin/1spot/vendor/github.com/kataras/iris/context_binder.go:98 +0x26b
gitlab.com/dvwallin/1spot/libs/handlerslib.AddEventPostHandler(0xc820098780)
/home/david/.gvm/pkgsets/go1.6/global/src/gitlab.com/dvwallin/1spot/libs/handlerslib/eventsRouteHandler.go:45 +0x9b
gitlab.com/dvwallin/1spot/vendor/github.com/kataras/iris.HandlerFunc.Serve(0xc6e788, 0xc820098780)
/home/david/.gvm/pkgsets/go1.6/global/src/gitlab.com/dvwallin/1spot/vendor/github.com/kataras/iris/handler.go:62 +0x26
gitlab.com/dvwallin/1spot/vendor/github.com/kataras/iris.(*Context).Next(0xc820098780)
/home/david/.gvm/pkgsets/go1.6/global/src/gitlab.com/dvwallin/1spot/vendor/github.com/kataras/iris/context.go:154 +0x80
main.IsLord(0xc820098780)
/home/david/.gvm/pkgsets/go1.6/global/src/gitlab.com/dvwallin/1spot/main.go:37 +0x1b8
gitlab.com/dvwallin/1spot/vendor/github.com/kataras/iris.HandlerFunc.Serve(0xc6eed0, 0xc820098780)
/home/david/.gvm/pkgsets/go1.6/global/src/gitlab.com/dvwallin/1spot/vendor/github.com/kataras/iris/handler.go:62 +0x26
gitlab.com/dvwallin/1spot/vendor/github.com/kataras/iris.(*Context).Next(0xc820098780)
/home/david/.gvm/pkgsets/go1.6/global/src/gitlab.com/dvwallin/1spot/vendor/github.com/kataras/iris/context.go:154 +0x80
main.IsLoggedIn(0xc820098780)
/home/david/.gvm/pkgsets/go1.6/global/src/gitlab.com/dvwallin/1spot/main.go:19 +0x1b8
gitlab.com/dvwallin/1spot/vendor/github.com/kataras/iris.HandlerFunc.Serve(0xc6eec8, 0xc820098780)
/home/david/.gvm/pkgsets/go1.6/global/src/gitlab.com/dvwallin/1spot/vendor/github.com/kataras/iris/handler.go:62 +0x26
gitlab.com/dvwallin/1spot/vendor/github.com/kataras/iris.(*Context).Next(0xc820098780)
/home/david/.gvm/pkgsets/go1.6/global/src/gitlab.com/dvwallin/1spot/vendor/github.com/kataras/iris/context.go:154 +0x80
gitlab.com/dvwallin/1spot/vendor/github.com/kataras/iris/middleware/pongo2.(*pongo2Middleware).Serve(0x10e2380, 0xc820098780)
/home/david/.gvm/pkgsets/go1.6/global/src/gitlab.com/dvwallin/1spot/vendor/github.com/kataras/iris/middleware/pongo2/pongo2.go:39 +0x33
gitlab.com/dvwallin/1spot/vendor/github.com/kataras/iris.(*Context).Do(0xc820098780)
/home/david/.gvm/pkgsets/go1.6/global/src/gitlab.com/dvwallin/1spot/vendor/github.com/kataras/iris/context.go:144 +0x5d
gitlab.com/dvwallin/1spot/vendor/github.com/kataras/iris.(*tree).serve(0xc820162d20, 0xc820152480, 0xc8200df380, 0x11, 0x1)
/home/david/.gvm/pkgsets/go1.6/global/src/gitlab.com/dvwallin/1spot/vendor/github.com/kataras/iris/tree.go:140 +0x1be
gitlab.com/dvwallin/1spot/vendor/github.com/kataras/iris.(*router).serveFunc(0xc82017e190, 0xc820152480)
/home/david/.gvm/pkgsets/go1.6/global/src/gitlab.com/dvwallin/1spot/vendor/github.com/kataras/iris/router.go:159 +0x256
gitlab.com/dvwallin/1spot/vendor/github.com/kataras/iris.(*router).(gitlab.com/dvwallin/1spot/vendor/github.com/kataras/iris.serveFunc)-fm(0xc820152480)
/home/david/.gvm/pkgsets/go1.6/global/src/gitlab.com/dvwallin/1spot/vendor/github.com/kataras/iris/router.go:74 +0x2a
gitlab.com/dvwallin/1spot/vendor/github.com/valyala/fasthttp.(*Server).serveConn(0xc82018a8c0, 0x7fc6450a4668, 0xc82016a2a8, 0x0, 0x0)
/home/david/.gvm/pkgsets/go1.6/global/src/gitlab.com/dvwallin/1spot/vendor/github.com/valyala/fasthttp/server.go:1452 +0x767
gitlab.com/dvwallin/1spot/vendor/github.com/valyala/fasthttp.(*Server).(gitlab.com/dvwallin/1spot/vendor/github.com/valyala/fasthttp.serveConn)-fm(0x7fc6450a4668, 0xc82016a2a8, 0x0, 0x0)
/home/david/.gvm/pkgsets/go1.6/global/src/gitlab.com/dvwallin/1spot/vendor/github.com/valyala/fasthttp/server.go:1183 +0x42
gitlab.com/dvwallin/1spot/vendor/github.com/valyala/fasthttp.(*workerPool).workerFunc(0xc82018c680, 0xc8201d65e0)
/home/david/.gvm/pkgsets/go1.6/global/src/gitlab.com/dvwallin/1spot/vendor/github.com/valyala/fasthttp/workerpool.go:224 +0x11c
gitlab.com/dvwallin/1spot/vendor/github.com/valyala/fasthttp.(*workerPool).getCh.func1(0xc82018c680, 0xc8201d65e0, 0x973220, 0xc8201d65e0)
/home/david/.gvm/pkgsets/go1.6/global/src/gitlab.com/dvwallin/1spot/vendor/github.com/valyala/fasthttp/workerpool.go:183 +0x2b
created by gitlab.com/dvwallin/1spot/vendor/github.com/valyala/fasthttp.(*workerPool).getCh
/home/david/.gvm/pkgsets/go1.6/global/src/gitlab.com/dvwallin/1spot/vendor/github.com/valyala/fasthttp/workerpool.go:185 +0x1e9
Code to reproduce:
func TestMapToPtrStruct(t *testing.T) {
s := struct {
// pointer to struct
M map[string]*struct {
ID string
}
}{}
vals := url.Values{
"M[key].ID": []string{"M[key].ID"},
}
dec := formam.NewDecoder(nil)
if err := dec.Decode(vals, &s); err != nil {
t.Fatalf("error when decode %s", err)
}
if v, ok := s.M["key"]; !ok {
t.Error("The key \"key\" in M does not exists")
} else if v.ID != "M[key].ID" {
t.Error("The value in key \"key\" of M is incorrect")
}
}
Expected: no error
Actual: error when decode formam: unsupported type; maybe include it the UnmarshalText interface or register it using custom type?
Currently this module shows up on go.dev as having no version released https://pkg.go.dev/github.com/monoculum/formam.
This is because there is no release where the major version matches the import version.
The only change needed is to to add the suffix v3 to the module name declared in go.mod.
module github.com/monoculum/formam/v3
Of course a new minor release would be necessary too.
An effect this will have is that from now on people would need to use SIV when importing your module.
Cheers.
First off, like the library.
Just wondering if there were any plans to implement registering of custom types?
TextMarshler and Unmarshler is great, but when the objects are not under your control, such as bson.ObjectId from the mgo package; can't implement/add TextMarshler and Unmarshler support.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.