danielgtaylor / huma

Huma REST/HTTP API Framework for Golang with OpenAPI 3.1
https://huma.rocks/
MIT License
2.15k stars 152 forks source link

Handling Field Matching and Validation for application/x-www-form-urlencoded in Huma #642

Open learning-go123 opened 1 week ago

learning-go123 commented 1 week ago

Refer to this: https://github.com/danielgtaylor/huma/issues/285 I wrote the following code

var DefaultFormPostFormat = huma.Format{
    Marshal: nil,
    Unmarshal: func(data []byte, v any) error {
        params, err := url.ParseQuery(string(data))
        if err != nil {
            return err
        }
        if vPtr, ok := v.(*interface{}); ok {
            m := map[string]any{}
            for k := range params {
                m[snakeToCamel(k)] = params.Get(k)
            }
            *vPtr = m
            return nil
        }
        return mapForm(v, params)
    },
}

config.Formats["application/x-www-form-urlencoded"] = DefaultFormPostFormat

There is a problem here. If the fields of params are more than the fields of the structure in v, it will not pass the validation. Turning off validation will introduce additional validators. Is there some better way to make the code more unified?

danielgtaylor commented 1 day ago

@learning-go123 sorry I don't entirely understand the question. Do you have a runnable example or some input example vs. input struct where this fails and what you would prefer to see happen?

learning-go123 commented 18 hours ago

@danielgtaylor https://go.dev/play/p/58af3WgDFjg

danielgtaylor commented 8 hours ago

@learning-go123 aaaaah now I understand. Thank you for the example! Here's how you can make it work: https://go.dev/play/p/7oVfLkGBmcJ. What I did was make sure the schema is generated with additionalProperties: true rather than the default of false for strict validation. See the docs here:

https://huma.rocks/features/request-validation/?h=additionalproperties#strict-vs-loose-field-validation

It's also possible to modify the schemas after generation, e.g. go through api.OpenAPI().Components.Schemas and set the AdditionalProperties field to true manually wherever you need to, or to provide your own custom schema for a particular operation. Hope this helps!