2022-02-08 08:30:13 +02:00
< a href = "https://ggicci.github.io/httpin/" >
< img src = "https://ggicci.github.io//httpin/img/emoji-dango.png" alt = "httpin logo" title = "httpin Documentation" align = "right" height = "60" / >
< / a >
2021-04-13 07:33:04 +02:00
2022-02-08 08:30:13 +02:00
# httpin - HTTP Input for Go
2021-06-24 09:12:18 +02:00
2023-12-28 00:35:53 +02:00
< div align = "center" > < h3 > HTTP Request from/to Go Struct< / h3 > < / div >
2022-02-08 08:30:13 +02:00
< div align = "center" >
2022-02-21 14:37:10 +02:00
[![Go ](https://github.com/ggicci/httpin/actions/workflows/go.yml/badge.svg?branch=main )](https://github.com/ggicci/httpin/actions/workflows/go.yml) [![documentation ](https://github.com/ggicci/httpin/actions/workflows/documentation.yml/badge.svg?branch=documentation )](https://github.com/ggicci/httpin/actions/workflows/documentation.yml) [![codecov ](https://codecov.io/gh/ggicci/httpin/branch/main/graph/badge.svg?token=RT61L9ngHj )](https://codecov.io/gh/ggicci/httpin) [![Go Report Card ](https://goreportcard.com/badge/github.com/ggicci/httpin )](https://goreportcard.com/report/github.com/ggicci/httpin) [![Mentioned in Awesome Go ](https://awesome.re/mentioned-badge.svg )](https://github.com/avelino/awesome-go) [![Go Reference ](https://pkg.go.dev/badge/github.com/ggicci/httpin.svg )](https://pkg.go.dev/github.com/ggicci/httpin)
2021-05-08 10:15:26 +02:00
2021-10-27 09:00:21 +02:00
< table >
< tr >
< td align = "center" >
< a href = "https://ggicci.github.io/httpin/" >
< img src = "https://docusaurus.io/img/docusaurus.svg" height = "48px" / >
< / a >
< / td >
< / tr >
< tr >
< td >
< a href = "https://ggicci.github.io/httpin/" > Documentation< / a >
< / td >
< / tr >
< / table >
2021-04-29 05:55:02 +02:00
2022-02-08 08:30:13 +02:00
< / div >
2021-04-29 05:55:02 +02:00
2022-02-08 08:30:13 +02:00
## Core Features
2023-12-28 00:35:53 +02:00
**httpin** helps you easily decode data from an HTTP request, including:
2022-02-08 08:30:13 +02:00
- **Query parameters**, e.g. `?name=john&is_member=true`
- **Headers**, e.g. `Authorization: xxx`
- **Form data**, e.g. `username=john&password=******`
- **JSON/XML Body**, e.g. `POST {"name":"john"}`
- **Path variables**, e.g. `/users/{username}`
- **File uploads**
You **only** need to define a struct to receive/bind data from an HTTP request, **without** writing any parsing stuff code by yourself.
2023-12-28 00:35:53 +02:00
Since v0.15.0, httpin also supports creating an HTTP request (`http.Request`) from a Go struct instance.
**httpin** is:
- **well documented**: at https://ggicci.github.io/httpin/
- **open integrated**: with [net/http ](https://ggicci.github.io/httpin/integrations/http ), [go-chi/chi ](https://ggicci.github.io/httpin/integrations/gochi ), [gorilla/mux ](https://ggicci.github.io/httpin/integrations/gorilla ), [gin-gonic/gin ](https://ggicci.github.io/httpin/integrations/gin ), etc.
- **extensible** (advanced feature): by adding your custom directives. Read [httpin - custom directives ](https://ggicci.github.io/httpin/directives/custom ) for more details.
## How to decode an HTTP request to Go struct?
2022-02-08 08:30:13 +02:00
```go
type ListUsersInput struct {
2022-11-09 18:59:52 +02:00
Token string `in:"query=access_token;header=x-access-token"`
Page int `in:"query=page;default=1"`
PerPage int `in:"query=per_page;default=20"`
IsMember bool `in:"query=is_member"`
2022-02-08 08:30:13 +02:00
}
func ListUsers(rw http.ResponseWriter, r *http.Request) {
input := r.Context().Value(httpin.Input).(*ListUsersInput)
if input.IsMember {
// Do sth.
}
// Do sth.
}
```
2023-12-28 00:35:53 +02:00
## How to encode a Go struct to HTTP request?
2022-02-08 08:30:13 +02:00
2023-12-28 00:35:53 +02:00
```go
type ListUsersInput struct {
Token string `in:"query=access_token;header=x-access-token"`
Page int `in:"query=page;default=1"`
PerPage int `in:"query=per_page;default=20"`
IsMember bool `in:"query=is_member"`
}
func SDKListUsers() {
payload := & ListUsersInput{
Token: os.Getenv("MY_APP_ACCESS_TOKEN"),
Page: 2,
IsMember: true,
}
// Easy to remember, http.NewRequest -> httpin.NewRequest
req, err := httpin.NewRequest("GET", "/users", payload)
// ...
}
```
2022-02-08 08:30:13 +02:00
## Why this package?
#### Compared with using `net/http` package
2021-04-29 05:55:02 +02:00
2021-05-08 08:07:09 +02:00
```go
func ListUsers(rw http.ResponseWriter, r *http.Request) {
page, err := strconv.ParseInt(r.FormValue("page"), 10, 64)
if err != nil {
2021-05-10 09:35:02 +02:00
// Invalid parameter: page.
2021-05-08 08:07:09 +02:00
return
}
perPage, err := strconv.ParseInt(r.FormValue("per_page"), 10, 64)
if err != nil {
2021-05-10 09:35:02 +02:00
// Invalid parameter: per_page.
return
}
isMember, err := strconv.ParseBool(r.FormValue("is_member"))
if err != nil {
// Invalid parameter: is_member.
2021-05-08 08:07:09 +02:00
return
}
2021-05-10 09:35:02 +02:00
// Do sth.
2021-05-08 08:07:09 +02:00
}
```
2021-04-29 05:55:02 +02:00
2022-02-08 08:30:13 +02:00
| Benefits | Before (use net/http package) | After (use ggicci/httpin package) |
| ----------------------- | ------------------------------------------ | ---------------------------------------------------------------------------------------------- |
| ⌛️ Developer Time | 😫 Expensive (too much parsing stuff code) | 🚀 **Faster** (define the struct for receiving input data and leave the parsing job to httpin) |
| ♻️ Code Repetition Rate | 😞 High | 😍 **Lower** |
| 📖 Code Readability | 😟 Poor | 🤩 **Highly readable** |
| 🔨 Maintainability | 😡 Poor | 🥰 **Highly maintainable** |
2022-03-07 13:08:56 +02:00
2022-11-09 18:59:52 +02:00
## Alternatives and Similars
2022-03-07 13:08:56 +02:00
- [gorilla/schema ](https://github.com/gorilla/schema ): converts structs to and from form values
2022-11-09 18:59:52 +02:00
- [google/go-querystring ](https://github.com/google/go-querystring ): encoding structs into URL query parameters