{"id":22394260,"url":"https://github.com/neox5/go-formdata","last_synced_at":"2025-06-17T03:33:26.995Z","repository":{"id":53328731,"uuid":"353277451","full_name":"neox5/go-formdata","owner":"neox5","description":"A Go library for parsing \u0026 validating multipart/form-data requests. ","archived":false,"fork":false,"pushed_at":"2021-03-31T15:30:56.000Z","size":36,"stargazers_count":3,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2023-12-25T09:48:01.206Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/neox5.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-03-31T08:09:50.000Z","updated_at":"2023-10-07T10:46:13.000Z","dependencies_parsed_at":"2022-09-26T19:01:47.601Z","dependency_job_id":null,"html_url":"https://github.com/neox5/go-formdata","commit_stats":null,"previous_names":[],"tags_count":2,"template":null,"template_full_name":null,"purl":"pkg:github/neox5/go-formdata","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/neox5%2Fgo-formdata","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/neox5%2Fgo-formdata/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/neox5%2Fgo-formdata/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/neox5%2Fgo-formdata/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/neox5","download_url":"https://codeload.github.com/neox5/go-formdata/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/neox5%2Fgo-formdata/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":260285780,"owners_count":22986459,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-12-05T05:09:34.957Z","updated_at":"2025-06-17T03:33:26.968Z","avatar_url":"https://github.com/neox5.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# \u003cimg alt=\"formdata\" src=\"https://cdn.statically.io/gh/neox5/go-formdata/main/formdata_logo.svg\" width=\"300\" /\u003e\n\n[![GoDoc](https://img.shields.io/badge/go-documentation-blue.svg?style=flat-square)](https://pkg.go.dev/mod/github.com/neox5/go-formdata)\n\n`formdata` is a simple and idomatic Go library for `multipart/form-data`.\n\nThe main focus for this library is parsing, validating and accessing\nform-data from HTTP requests. The core element of this libary is `FormData`,\nwhich wraps the multipart.Form object and adds additional validation\ncapabilities.\n\nValidation is written to enable chaining and therefore improve code readability.\n\n## Features\n\n- **Parsing** - Directly parsing http.Requests into `FormData`. A wrapper which\n  extends `multipart.Form` with additional validation capabilities. \n\n- **Chainability** - Easy and intuative validation with chainable functions \n  (examples below).\n\n- **Independent** - No external dependencies besides the Go standard library,\n  meaning it won't bloat your project.\n\n- **Documentation** - With real world examples.\n\n## Install\n\n`go get -u github.com/neox5/go-formdata`\n\n## Usage\nExample shows how `formdata` helps handling a request for an email endpoint:\n\n```go\nfunc (s *Server) handleMailRequestV1() http.HandlerFunc {\n\treturn func(w http.ResponseWriter, r *http.Request) {\n    // set http.MaxBytesReader before parsing to limit the size of the incoming\n    // request.\n    r.Body = http.MaxBytesReader(w, r.Body, formdata.DefaultParseMaxMemory) // 1MiB\n\n    // PARSE formdata from request\n    fd, err := formdata.Parse(r)\n    if err == formdata.ErrNotMultipartFormData {\n      // ...handle unsupported media type\n      return\n    }\n    if err != nil {\n      // ...handle internal server error\n      return\n    }\n\n    // VALIDATE formdata\n    fd.Validate(\"from\").Required().HasN(1)\n    fd.Validate(\"subject\").Required().HasN(1)\n    fd.Validate(\"body\").Required().HasN(1)\n    fd.Validate(\"to\").Required().HasNMin(1).MatchAllEmail()\n\n    if fd.HasErrors() {\n      message := fmt.Sprintf(\"validation errors: %s\", strings.Join(fd.Errors(), \"; \"))\n      // ...handle bad request\n      return\n    }\n\n    // ACCESS formdata values\n    from := fd.Get(\"from\").First()\n    subject := fd.Get(\"subject\").First()\n    body := fd.Get(\"body\").First()\n\n    msg := NewMail(from, subject, body)\n\n    to := fd.Get(\"to\")\n\n    for _, recipient := range to {\n      msg.AddRecipient(recipient)\n    }\n\n    if fd.FileExists(\"attachment\") {\n      for _, file := range fd.GetFile(\"attachment\") {\n        reader, err := file.Open()\n        if err != nil {\n          // ...handle invalid attachment\n          return\n        }\n        msg.AddReaderAttachment(file.Filename, reader)\n      }\n    }\n\n    s.sendMessage(msg)\n  }\n}\n```\n\n## Parsing\n\n### Methods\n\n- **Parse** - envokes ParseMax(r, DefaultParseMaxMemory), DefaultParseMaxMemory = 1MiB\n  \n- **ParseMax** - parses a request body as multipart/form-data. The whole request\n  body is parsed and up to a total of `maxMemory` bytes of its files parts are\n  stored in memory, with the rmainder stored on disk in temporary files.\n\n\n## FormData\n\n`FormData` is the central element of formdata and it is returned from either \n[Parse](#parsing) or [ParseMax](#parsing).\n\n```go\n// FormData extends multipart.Form with additional validation capabilities.\ntype FormData struct {\n\t*multipart.Form\n\terrors []*ValidationError\n}\n```\n\n### FormData Methods\n- **Validate** - returns a Value Validation on the given key\n- **ValidateFile** - returns a File Validation on the given key\n- **HasErrors** - checks if FormData has validation errors\n- **Errors** - returns validation errors as `[]string`\n- **Exists** - checks if key exists in FormData.Value\n- **FileExists** - checks if key exists in FormData.File\n- **Get** - returns [FormDataValue](#formdatavalue) for given key\n- **GetFile** - returns [FormDataFile](#formdatafile) for given key\n\n## Validation\n\n### Global Validation\n- **Required** - add required validation, checks if key exists in FormData\n- **HasN** - checks if Value/File has `N` elements\n- **HasNMin** - cheks if Value/File has minimum `N` elements\n\n### Value Validation\n- **Match** - validates if the first element matches a regular expression\n- **MatchAll** - validates if all elements match a given regular expression\n- **MatchEmail** - validates if the first element matches an email\n- **MatchAllEmail** - validates if all elements are matching an email \n\n### File Validation\n...still loading\n\n## FormDataValue\n\n`FormDataValue` is the returned type of the [Get](#formdata-methods) method on the \n[FormData](#formdata) type.\n\n### Methods\n- **At** - gets element of FormDataValue at the given index\n- **First** - gets the first element of FormDataValue\n\n## FormDataFile\n\n`FormDataFile` is the returned type of the [GetFile](#formdata-methods) method on the \n[FormData](#formdata) type.\n\n### Methods\n- **At** - gets element of FormDataFile at the given index\n- **First** - gets the first element of FormDataFile\n\n## Inspiration\n\nThis library is conceptually similar to [albrow/forms](https://github.com/albrow/forms), with the following major behavioral differences:\n\n- Focusing only on multipart/form-data.\n- Wrapping multipart.Form without redefining a new data struct.\n- Support for chainable validation.\n- Support for multiple files per key.\n\n## License\n\n`formdata` is licensed under the MIT License. See the LICENSE file for more information.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fneox5%2Fgo-formdata","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fneox5%2Fgo-formdata","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fneox5%2Fgo-formdata/lists"}